Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Danbooru Enhanced Gallery View
- // @namespace http://tampermonkey.net/
- // @version 1.0
- // @description Adds functionality to the image gallery like media preview and download without the need to open the post.
- // @author SomeHornyDev
- // @match https://danbooru.donmai.us/*
- // @exclude https://danbooru.donmai.us/posts/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=donmai.us
- // @grant none
- // ==/UserScript==
- const MEDIA_VIEWER_ELEM_CLASS = 'media-viewer-element';
- const MEDIA_VIEWER_DOWNLOAD_BUTTON_CLASS = 'media-viewer-download';
- const MEDIA_VIEWER_DOWNLOAD_BUTTON_POST_URL_DATA_ATTR = 'data-post-url';
- class MediaViewer {
- #container;
- #content;
- #downloadButton;
- #isOpen;
- constructor() {
- this.#isOpen = false;
- this.#container = document.createElement('div');
- Object.assign(this.#container.style, {
- isolation: 'isolate',
- position: 'fixed',
- inset: 0,
- display: 'none',
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center',
- padding: '48px',
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
- pointerEvents: 'none'
- });
- this.#container.addEventListener('click', (evt) => {
- const elem = evt.target;
- if (this.#isOpen && !elem.classList.contains(MEDIA_VIEWER_ELEM_CLASS) && !elem.classList.contains(MEDIA_VIEWER_DOWNLOAD_BUTTON_CLASS)) {
- this.close();
- }
- });
- document.addEventListener('keyup', (evt) => {
- if (evt.key === "Escape") {
- if (this.#isOpen) this.close();
- }
- });
- this.#content = document.createElement('div');
- this.#container.append(this.#content);
- this.#downloadButton = document.createElement('button');
- this.#downloadButton.textContent = '⬇️ Download';
- Object.assign(this.#downloadButton.style, {
- display: 'inline-flex',
- alignItems: 'center',
- justifyContent: 'center',
- gap: '2px',
- marginTop: '8px',
- padding: '12px',
- backgroundColor: 'white',
- color: 'black',
- fontSize: '1rem',
- border: '0',
- borderRadius: '4px',
- boxShadow: 'none',
- });
- this.#downloadButton.classList.add(MEDIA_VIEWER_DOWNLOAD_BUTTON_CLASS);
- this.#downloadButton.addEventListener('click', (evt) => {
- const postUrl = evt.target.getAttribute(MEDIA_VIEWER_DOWNLOAD_BUTTON_POST_URL_DATA_ATTR);
- downloadMediaFromPostUrl(postUrl);
- });
- this.#container.append(this.#downloadButton);
- document.body.append(this.#container);
- }
- open(url) {
- this.#content.innerHTML = 'Loading...';
- getMediaElemFromPostUrl(url)
- .then((elem) => {
- this.#content.innerHTML = '';
- Object.assign(elem.style, {
- display: 'block',
- maxInlineSize: '100%',
- blockSize: 'auto',
- maxHeight: 'calc(100vh - 96px)',
- border: '4px solid white',
- borderRadius: '4px'
- });
- elem.classList.add(MEDIA_VIEWER_ELEM_CLASS);
- this.#content.append(elem);
- this.#downloadButton.setAttribute(MEDIA_VIEWER_DOWNLOAD_BUTTON_POST_URL_DATA_ATTR, url);
- Object.assign(this.#container.style, {
- display: 'flex',
- pointerEvents: 'auto'
- });
- this.#isOpen = true;
- });
- }
- close() {
- Object.assign(this.#container.style, {
- display: 'none',
- pointerEvents: 'none'
- });
- this.#isOpen = false;
- }
- }
- function getOrigSrcFromPostUrl(postUrl) {
- return fetch(postUrl)
- .then((response) => response.text())
- .then((html) => {
- const parser = new DOMParser();
- const doc = parser.parseFromString(html, 'text/html');
- const videoElem = doc.querySelector('video');
- if (videoElem) {
- return videoElem.src;
- }
- const viewOriginalLink = doc.querySelector('a.image-view-original-link');
- return viewOriginalLink.href;
- })
- .catch((err) => console.error(err));
- }
- function getMediaElemFromPostUrl(postUrl) {
- return fetch(postUrl)
- .then((response) => response.text())
- .then((html) => {
- const parser = new DOMParser();
- const doc = parser.parseFromString(html, 'text/html');
- const videoElem = doc.querySelector('video');
- if (videoElem) {
- videoElem.muted = true;
- return videoElem;
- }
- const img = new Image();
- const mainImage = doc.getElementById('image');
- const viewOriginalLink = doc.querySelector('a.image-view-original-link');
- if (viewOriginalLink) {
- img.src = viewOriginalLink.href;
- } else {
- img.src = mainImage.src;
- }
- return img;
- })
- .catch((err) => console.error(err));
- }
- function getBlobFromUrl(url) {
- return fetch(url)
- .then((response) => response.blob())
- .catch((err) => console.error(err));
- }
- function downloadMediaFromPostUrl(postUrl) {
- getOrigSrcFromPostUrl(postUrl)
- .then((src) => {
- getBlobFromUrl(src)
- .then((blob) => {
- const anchor = document.createElement("a");
- anchor.href = URL.createObjectURL(blob);
- const fileName = src.match(/[^\/]+$/);
- anchor.download = fileName;
- document.body.appendChild(anchor);
- anchor.click();
- document.body.removeChild(anchor);
- URL.revokeObjectURL(blob);
- });
- });
- }
- (function() {
- 'use strict';
- const mediaViewer = new MediaViewer();
- const postGallery = document.querySelector('.post-gallery');
- const imagePreviews = postGallery.querySelectorAll('.post-preview');
- imagePreviews.forEach((imagePreview) => {
- const link = imagePreview.querySelector('.post-preview-link');
- const source = imagePreview.querySelector('source');
- const postUrl = link.href;
- Object.assign(imagePreview.style, {
- position: 'relative',
- padding: '32px',
- backgroundColor: 'rgba(255, 255, 255, 0.03)',
- borderRadius: '2px',
- boxShadow: '0px 3px 15px rgba(0,0,0,0.2)'
- });
- const buttonGroup = document.createElement('div');
- Object.assign(buttonGroup.style, {
- position: 'absolute',
- top: '-6px',
- right: '-6px',
- display: 'flex',
- alignItems: 'center',
- visibility: 'hidden',
- });
- imagePreview.append(buttonGroup);
- imagePreview.addEventListener('mouseenter', () => {
- imagePreview.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
- buttonGroup.style.visibility = 'visible';
- });
- imagePreview.addEventListener('mouseleave', () => {
- imagePreview.style.backgroundColor = 'rgba(255, 255, 255, 0.03)';
- buttonGroup.style.visibility = 'hidden';
- });
- const buttonStyles = {
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- alignSelf: 'end',
- padding: '8px',
- backgroundColor: 'transparent',
- lineHeight: '1.25',
- fontSize: '1.25rem',
- border: '0',
- boxShadow: 'none'
- };
- const previewButton = document.createElement('button');
- previewButton.textContent = '🔎';
- Object.assign(previewButton.style, buttonStyles);
- previewButton.addEventListener('click', () => mediaViewer.open(postUrl));
- const downloadButton = document.createElement('button');
- downloadButton.textContent = '⬇️';
- Object.assign(downloadButton.style, buttonStyles);
- downloadButton.addEventListener('click', () => downloadMediaFromPostUrl(postUrl));
- buttonGroup.append(previewButton);
- buttonGroup.append(downloadButton);
- });
- })();
Add Comment
Please, Sign In to add comment