Greasy Fork is available in English.
Button in catalog that shows all the images in all posts.
当前为
// ==UserScript==
// @name 4chan browser
// @namespace e343367e7d795211da74d4a886e28f9c
// @description Button in catalog that shows all the images in all posts.
// @version 1.0.1
// @include http://boards.4chan.org/*/catalog
// @include https://boards.4chan.org/*/catalog
// @grant none
// ==/UserScript==
(function () {
const width = 200;
const height = 200;
const queries = {
thread: '.thread',
subject: '.teaser',
image: '.fileThumb'
};
const button = document.createElement('button');
button.innerHTML = 'Browse images';
document.body.insertBefore(button, document.body.firstChild);
button.addEventListener('click', () => {
const window = open();
const document = window.document;
document.body.style.paddingTop = '20px';
document.body.style.background = '#F1F1F1';
navigation(window, document, threads(document));
});
function threads(newDocument) {
const play = makePlay(newDocument);
const tags = Array.from(document.querySelectorAll(queries.thread));
return tags.map(tag => new Thread(newDocument, tag, play));
}
class Thread {
constructor(document, tag, play) {
let subject = tag.querySelector(queries.subject);
if (subject) {
subject = subject.innerHTML;
} else {
subject = 'Thread';
}
const a = document.createElement('a');
a.href = tag.querySelector('a').href;
a.innerHTML = subject;
const p = document.createElement('p');
p.appendChild(a);
const loading = document.createTextNode('Loading');
this.div = document.createElement('div');
this.div.appendChild(p);
this.div.appendChild(loading);
this.request = new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('GET', a.href);
request.responseType = 'document';
request.addEventListener('load', () => {
this.div.removeChild(loading);
let images = queries.image;
images = request.response.querySelectorAll(images);
images = Array.from(images);
images = images.filter(image => image.href);
this.thumbnails = images.map(image => {
return new Thumbnail(document, image, this.div, play);
});
resolve();
});
request.send();
});
}
load() {
this.request.then(() => {
for (let thumbnail of this.thumbnails) {
thumbnail.load();
}
});
}
}
class Thumbnail {
constructor(document, image, container, play) {
this.image = image;
this.img = document.createElement('img');
this.img.style.display = 'block';
this.img.style.margin = 'auto';
this.img.addEventListener('error', () => {
container.removeChild(this.div);
});
this.img.addEventListener('load', () => {
if (this.img.naturalWidth > this.img.naturalHeight) {
this.img.width = width;
} else {
this.img.height = height;
}
});
const a = document.createElement('a');
a.style.display = 'block';
a.style.position = 'relative';
a.href = image.href;
a.target = '_blank';
a.appendChild(this.img);
this.div = document.createElement('div');
this.div.style.width = width + 'px';
this.div.style.height = height + 'px';
this.div.style.padding = '10px';
this.div.style.margin = '10px';
this.div.style.borderRadius = '4px';
this.div.style.display = 'inline-block';
this.div.style.background = 'white';
this.div.style.border = '1px solid #D8D8D8';
this.div.appendChild(a);
if (image.href.match(/.webm/)) {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.style.position = 'absolute';
canvas.style.top = '0px';
canvas.getContext('2d').drawImage(play, 0, 0);
a.appendChild(canvas);
}
container.appendChild(this.div);
}
load() {
this.img.src = this.image.querySelector('img').src;
}
}
function navigation(window, document, threads) {
let i = 0;
const next = document.createElement('button');
next.innerHTML = 'next';
next.style.position = 'fixed';
next.style.right = '0px';
next.style.top = '0px';
next.style.zIndex = '1';
next.addEventListener('click', function () {
if (i == 0) {
document.body.appendChild(previous);
}
document.body.removeChild(threads[i].div);
i += 1;
document.body.appendChild(threads[i].div);
threads[i].load();
if (i == threads.length - 1) {
document.body.removeChild(next);
}
window.scrollTo(0, 0);
});
const previous = document.createElement('button');
previous.innerHTML = 'previous';
previous.style.position = 'fixed';
previous.style.left = '0px';
previous.style.top = '0px';
previous.style.zIndex = '1';
previous.addEventListener('click', function () {
if (i == threads.length - 1) {
document.body.appendChild(next);
}
document.body.removeChild(threads[i].div);
i -= 1;
document.body.appendChild(threads[i].div);
threads[i].load();
if (i == 0) {
document.body.removeChild(previous);
}
window.scrollTo(0, 0);
});
document.body.appendChild(threads[i].div);
document.body.appendChild(next);
threads[i].load();
window.addEventListener('keydown', function (event) {
if (event.keyCode == 37 && i > 0) {
previous.click();
}
if (event.keyCode == 39 && i < threads.length - 1) {
next.click();
}
});
}
function makePlay(document) {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
context.fillStyle = 'hsla(0, 0%, 80%, 0.25)';
context.strokeStyle = 'hsla(0, 0%, 100%, 0.5)';
context.lineWidth = 2;
context.moveTo(width / 3, height / 3);
context.lineTo(width / 3 * 2, height / 2);
context.lineTo(width / 3, height / 3 * 2);
context.closePath();
context.fill();
context.stroke();
return canvas;
}
})();