Greasy Fork is available in English.
4chan grid based Image Gallery for threads that can load images, images with sounds, webms with sounds (Button on the Bottom Right)
当前为
// ==UserScript==
// @name 4chan Gallery
// @namespace http://tampermonkey.net/
// @version 2024-03-26
// @description 4chan grid based Image Gallery for threads that can load images, images with sounds, webms with sounds (Button on the Bottom Right)
// @author TheDarkEnjoyer
// @match http://boards.4chan.org/vt/thread/*
// @match https://boards.4chan.org/vt/thread/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @license GNU GPLv3
// ==/UserScript==
(function () {
"use strict";
// Function to load the button
const loadButton = () => {
const posts = document.querySelectorAll(".postContainer");
// Check if there are at least two posts
if (posts.length >= 2) {
const button = document.createElement("button");
button.textContent = "Open Image Gallery";
button.style.position = "fixed";
button.style.bottom = "20px";
button.style.right = "20px";
button.style.zIndex = "1000";
button.style.backgroundColor = "var(--main-color)"; // Dark mode compatible background
button.style.color = "var(--text-color)"; // Dark mode compatible text color
// Append the button to the body after 2 seconds
setTimeout(() => document.body.appendChild(button), 2000);
const openImageGallery = () => {
const gallery = document.createElement("div");
gallery.style.position = "fixed";
gallery.style.top = "0";
gallery.style.left = "0";
gallery.style.width = "100%";
gallery.style.height = "100%";
gallery.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
gallery.style.display = "flex";
gallery.style.justifyContent = "center";
gallery.style.alignItems = "center";
gallery.style.zIndex = "9999";
const gridContainer = document.createElement("div");
gridContainer.style.display = "grid";
gridContainer.style.gridTemplateColumns = "repeat(auto-fit, minmax(200px, 1fr))";
gridContainer.style.gridGap = "10px";
gridContainer.style.padding = "20px";
gridContainer.style.backgroundColor = "var(--main-color)"; // Dark mode compatible background
gridContainer.style.color = "var(--text-color)"; // Dark mode compatible text color
gridContainer.style.maxWidth = "80%";
gridContainer.style.maxHeight = "80%";
gridContainer.style.overflowY = "auto";
gridContainer.style.resize = "both"; // Make the grid resizable
gridContainer.style.overflow = "auto"; // Add scrollbars when resized
gridContainer.style.border = "1px solid var(--text-color)"; // Add border to the grid container
// Loop through each post and add its image/video to the grid
posts.forEach((post) => {
const mediaLink = post.querySelector(".fileText a");
const comment = post.querySelector(".postMessage");
if (mediaLink) {
const isVideo = mediaLink.href.includes(".webm");
const fileName = mediaLink.href.split("/").pop();
const soundLink = mediaLink.title.match(/\[sound=(.+?)\]/);
const cell = document.createElement("div");
cell.style.border = "1px solid var(--text-color)"; // Add border to each cell
cell.style.position = "relative"; // Make the cell position relative
const buttonDiv = document.createElement("div");
buttonDiv.style.display = "flex";
buttonDiv.style.justifyContent = "space-between";
buttonDiv.style.alignItems = "center";
buttonDiv.style.padding = "5px";
if (isVideo) {
const videoContainer = document.createElement("div");
videoContainer.style.position = "relative";
const video = document.createElement("video");
video.src = mediaLink.href;
video.style.maxWidth = "100%";
video.style.maxHeight = "200px";
video.style.objectFit = "contain";
video.muted = true;
video.style.cursor = "pointer";
video.addEventListener("click", () => {
post.scrollIntoView({ behavior: "smooth" });
document.body.removeChild(gallery);
});
video.controls = true;
video.title = comment.textContent;
videoContainer.appendChild(video);
if (soundLink) {
const audio = document.createElement("audio");
audio.src = decodeURIComponent(soundLink[1].startsWith("http") ? soundLink[1] : `https://${soundLink[1]}`);
videoContainer.appendChild(audio);
const playPauseButton = document.createElement("button");
playPauseButton.textContent = "Play/Pause";
playPauseButton.addEventListener("click", () => {
if (video.paused && audio.paused) {
video.play();
audio.play();
} else {
video.pause();
audio.pause();
}
});
buttonDiv.appendChild(playPauseButton);
const resetButton = document.createElement("button");
resetButton.textContent = "Reset";
resetButton.addEventListener("click", () => {
video.currentTime = 0;
audio.currentTime = 0;
});
buttonDiv.appendChild(resetButton);
}
const cellButton = document.createElement("button");
cellButton.textContent = "View Post";
cellButton.style.backgroundColor = "var(--main-color)";
cellButton.style.color = "var(--text-color)";
cellButton.addEventListener("click", () => {
post.scrollIntoView({ behavior: "smooth" });
document.body.removeChild(gallery);
});
buttonDiv.appendChild(cellButton);
cell.appendChild(videoContainer);
cell.appendChild(buttonDiv);
} else {
const image = document.createElement("img");
image.src = mediaLink.href;
image.style.maxWidth = "100%";
image.style.maxHeight = "200px";
image.style.objectFit = "contain";
image.style.cursor = "pointer";
image.addEventListener("click", () => {
post.scrollIntoView({ behavior: "smooth" });
document.body.removeChild(gallery);
});
image.title = comment.textContent;
if (soundLink) {
const audio = document.createElement("audio");
audio.src = decodeURIComponent(soundLink[1].startsWith("http") ? soundLink[1] : `https://${soundLink[1]}`);
const playPauseButton = document.createElement("button");
playPauseButton.textContent = "Play/Pause";
playPauseButton.style.position = "absolute";
playPauseButton.style.bottom = "10px";
playPauseButton.style.left = "10px";
playPauseButton.addEventListener("click", () => {
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
});
buttonDiv.appendChild(playPauseButton);
}
cell.appendChild(image);
cell.appendChild(buttonDiv);
}
gridContainer.appendChild(cell);
}
});
gallery.appendChild(gridContainer);
const closeButton = document.createElement("button");
closeButton.textContent = "Close";
closeButton.style.position = "absolute";
closeButton.style.top = "10px";
closeButton.style.right = "10px";
closeButton.style.zIndex = "10000";
closeButton.style.backgroundColor = "var(--main-color)";
closeButton.style.color = "var(--text-color)";
closeButton.addEventListener("click", () => {
document.body.removeChild(gallery);
});
gallery.appendChild(closeButton);
document.body.appendChild(gallery);
};
button.addEventListener("click", openImageGallery);
} else {
// If there are less than two posts, try again after 5 seconds
setTimeout(loadButton, 5000);
}
};
loadButton();
console.log("4chan Gallery loaded successfully!");
})();