Skip to content

Instantly share code, notes, and snippets.

@MaxMatti
Created October 10, 2020 14:41
Show Gist options
  • Save MaxMatti/7c4375c5fa956c3aebed5e9f84619b33 to your computer and use it in GitHub Desktop.
Save MaxMatti/7c4375c5fa956c3aebed5e9f84619b33 to your computer and use it in GitHub Desktop.
[WIP] Creates an overlay for https://boards.4chan.org/wg/catalog to display and scroll through all posted images above a certain resolution.
// ==UserScript==
// @name WG-Viewer
// @namespace http://tampermonkey.net/
// @version 0.1
// @description view images above a certain resolution
// @author Max Staff <max.staff@gmx.de>
// @match https://boards.4chan.org/wg/catalog
// @grant GM.xmlHttpRequest
// ==/UserScript==
var minWidth = 3500;
var minHeight = 2000;
var previewImageCount = 5;
var mainImageDisplaySize = 10;
var threads = [];
var images = [];
var displayImages = {};
var imagePos = 0;
var displayContainer;
var displayNextBtn;
var displayPrevBtn;
var styleString = `
div#displayContainer {
position: fixed;
margin: 5%;
padding: 10px;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000000;
display: grid;
grid-template-columns: [left] repeat(` + previewImageCount + `, 1fr) [center] repeat(` + previewImageCount + `, 1fr) [right];
grid-template-rows: ` + mainImageDisplaySize + `fr 1fr auto auto;
column-gap: 10px;
row-gap: 10px;
transition: 0.2s;
}
img.displayMainImage {
grid-row: 1;
grid-column-start: left;
grid-column-end: right;
object-fit: cover;
max-height: 100%;
max-width: 100%;
place-self: center;
transition: 0.2s;
}
img.displayPreviewImage {
grid-row: 2;
object-fit: cover;
max-height: 100%;
max-width: 100%;
place-self: center;
opacity: 0;
cursor: pointer;
transition: 0.2s;
}
button#displayPrevBtn {
grid-row: 3;
grid-column-start: left;
grid-column-end: center;
}
button#displayNextBtn {
grid-row: 3;
grid-column-start: center;
grid-column-end: right;
}
button#ballernBtn {
grid-row: 4;
grid-column-start: left;
grid-column-end: right;
}
`;
var previewImageSvg = "data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='margin: auto; display: block; shape-rendering: auto;' width='200px' height='200px' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid'%3E%3Ccircle cx='50' cy='50' r='32' stroke-width='8' stroke='%23e15b64' stroke-dasharray='50.26548245743669 50.26548245743669' fill='none' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' dur='1s' repeatCount='indefinite' keyTimes='0;1' values='0 50 50;360 50 50'%3E%3C/animateTransform%3E%3C/circle%3E%3Ccircle cx='50' cy='50' r='23' stroke-width='8' stroke='%23f8b26a' stroke-dasharray='36.12831551628262 36.12831551628262' stroke-dashoffset='36.12831551628262' fill='none' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' dur='1s' repeatCount='indefinite' keyTimes='0;1' values='0 50 50;-360 50 50'%3E%3C/animateTransform%3E%3C/circle%3E%3C/svg%3E";
function handleNextThread() {
var thread = threads.pop();
var req = GM.xmlHttpRequest({
method: "GET",
url: "https://a.4cdn.org/wg/thread/" + thread + ".json",
onload: function(response) {
var content = JSON.parse(response.responseText);
for (var i = 0; i < content.posts.length; ++i) {
content.posts[i];
if ("tim" in content.posts[i] && "ext" in content.posts[i] && "w" in content.posts[i] && "h" in content.posts[i] && content.posts[i].w > minWidth && content.posts[i].h > minHeight) {
images.push("https://i.4cdn.org/wg/" + content.posts[i].tim + content.posts[i].ext);
}
}
updateImages();
console.log("Thread done: " + thread);
window.setTimeout(handleNextThread, 1000);
}
});
}
function buttonClicked(e) {
var req = GM.xmlHttpRequest({
method: "GET",
url: "https://a.4cdn.org/wg/threads.json",
onload: function(response) {
var content = JSON.parse(response.responseText);
for (var i = 0; i < content.length; ++i) {
for (var j = 0; j < content[i].threads.length; ++j) {
threads.push(content[i].threads[j].no);
}
}
window.setTimeout(handleNextThread, 1000);
}
});
}
function nextImage(e) {
if (images.length == 0) {
return;
}
++imagePos;
if (imagePos >= images.length) {
imagePos = 0;
}
updateImages();
}
function prevImage(e) {
if (images.length == 0) {
return;
}
--imagePos;
if (imagePos <= 0) {
imagePos = images.length - 1;
}
updateImages();
}
function updateImages() {
if (images.length == 0) {
return;
}
for (var i = 0; i < previewImageCount * 2 + 1; ++i) {
var src = images[(imagePos - previewImageCount + i + images.length) % images.length];
if (!(src in displayImages)) {
var img = document.createElement("img");
img.src = src;
img.addEventListener("click", clickPreviewImage, true);
img.addEventListener("load", previewImageLoaded, true);
displayImages[src] = img;
}
displayImages[src].className = (i == previewImageCount) ? "displayMainImage" : "displayPreviewImage";
displayContainer.appendChild(displayImages[src]);
}
for (i = 0; i < displayContainer.children.length; ++i) {
if (displayContainer.children[i].className != "displayPreviewImage") {
continue;
}
src = displayContainer.children[i].src;
if (Math.abs(imagePos - images.indexOf(src)) > previewImageCount) {
displayContainer.removeChild(displayContainer.children[i]);
}
}
}
function previewImageLoaded(e) {
e.currentTarget.style.opacity = 1;
}
function clickPreviewImage(e) {
if (images.length == 0) {
return;
}
imagePos = images.indexOf(e.currentTarget.src);
if (imagePos < 0 || imagePos >= images.length) {
imagePos = 0;
}
updateImages();
}
function handleKeyPress(e) {
if (e.code == "ArrowRight") {
nextImage(e);
} else if (e.code == "ArrowLeft") {
prevImage(e);
} else {
console.log(e.code);
}
}
function load(e) {
if (document.getElementById("ballernBtn")) {
return;
}
document.addEventListener('keydown', handleKeyPress, true);
var style = document.createElement("style");
style.type = "text/css";
style.innerHTML = styleString;
document.head.appendChild(style);
displayContainer = document.createElement("div");
displayContainer.id = "displayContainer";
displayPrevBtn = document.createElement("button");
displayPrevBtn.id = "displayPrevBtn";
displayPrevBtn.innerHTML = "&lt;";
displayPrevBtn.addEventListener("click", prevImage, true);
displayNextBtn = document.createElement("button");
displayNextBtn.id = "displayNextBtn";
displayNextBtn.innerHTML = "&gt;";
displayNextBtn.addEventListener("click", nextImage, true);
var ballernBtn = document.createElement("button");
ballernBtn.id = "ballernBtn";
ballernBtn.innerHTML = "load images";
ballernBtn.addEventListener("click", buttonClicked, true);
displayContainer.appendChild(displayPrevBtn);
displayContainer.appendChild(displayNextBtn);
displayContainer.appendChild(ballernBtn);
document.body.appendChild(displayContainer);
}
(function() {
'use strict';
document.addEventListener("load", load, true);
// Your code here...
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment