Gelbooru Image Viewer

Adds a fullscreen image view option when you click on images

От 23.11.2016. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @id             gelbooru-slide
// @name           Gelbooru Image Viewer
// @version        1.0.4
// @namespace      intermission
// @author         intermission
// @license        CC0; https://wiki.creativecommons.org/wiki/CC0
// @description    Adds a fullscreen image view option when you click on images
// @include        http://gelbooru.com/index.php?*
// @include        https://gelbooru.com/index.php?*
// @run-at         document-start
// @grant          GM_registerMenuCommand
// ==/UserScript==

(function(){
	"use strict";
	var d = document, array = a => [].slice.call(a), observer, request, mouseUp, slideEl, slider, slidin, base = a => a.split("/").pop().split(".")[0].split("_").pop(), keyDown, find, current, preload, stor = localStorage, l, toggle = stor["gelbooru-slide"] == "true";
	
	if (!stor["gelbooru-slide"]) stor["gelbooru-slide"] = "false";
	
	GM_registerMenuCommand("Current image mode: " + (toggle ? "Always original size" : "Sample only"), () => {
		stor["gelbooru-slide"] = toggle ? "false" : "true";
		location.reload();
	});
	
	l = toggle ? ["ul>li>a[style*='font-weight:']", "href"] : ["#image", "src"];
	
	current = a => d.querySelector("img.preview[src*='" + base(slideEl.src) + "']").parentNode.parentNode;
	
	mouseUp = e => e.button == 0 && (e.preventDefault(), e.stopPropagation(), slider(e.target.parentNode));
	
	find = function(el, method) {
		var a;
		do {
			try {
				el = el[(method ? "next" : "previous") + "ElementSibling"];
				a = el.querySelector("a[data-full]");
			} catch(err) {
				return false;
			}
			if (a) break;
			a = false;
		} while(!a);
		return a;
	};
	
	preload = function() {
		var curr = current(), a = find(curr, true), b = find(curr, false);
		a && request(a);
		b && request(b);
		return;
	};
	
	keyDown = function(e) {
		var move;
		switch(e.keyCode) {
			case 32:
			case 39:
				move = true;
				break;
			case 37:
				move = false;
				break;
			case 38:
				window.location = current().firstElementChild.href;
				break;
			case 40:
				e.preventDefault();
				slideEl.click();
				break;
		}
		if (typeof move != "undefined") {
			e = find(current(), move);
			if (e) {
				let source = e.dataset.full
				if (source == "loading") {
					source = e.firstElementChild.src;
					request(e);
				}
				slideEl.removeAttribute("src");
				slideEl.src = source;
			}
			preload();
		}
	};
	
	slider = function(a) {
		var source = a.dataset.full, list;
		if (source == "loading") {
			source = a.firstElementChild.src;
			request(a);
		}
		list = array(d.querySelectorAll("body > *"));
		if (slidin) {
			let center;
			slidin = false;
			a = current().firstElementChild;
			slideEl.remove();
			slideEl = null;
			d.documentElement.removeAttribute("style");
			d.body.removeAttribute("style");
			list.forEach(a => a.dataset.slide = "false");
			a.classList.add("outlined");
			d.removeEventListener("keydown", keyDown, false);
			center = a.offsetTop + a.offsetHeight / 2 - window.innerHeight / 2;
			window.scrollTo(0, center < 0 ? 0 : center);
		} else {
			slidin = true;
			list.forEach(a => a.dataset.slide = "true");
			array(d.querySelectorAll("span>a.outlined")).map(a => a.classList.remove("outlined"));
			d.documentElement.style.height = d.body.style.height = d.documentElement.style.width = d.body.style.width = "100%";
			slideEl = d.createElement("img");
			slideEl.id = "slide";
			slideEl.alt = "Loading...";
			slideEl.src = source;
			slideEl.onclick = () => slider(a);
			d.body.appendChild(slideEl);
			d.addEventListener("keydown", keyDown, false);
			preload();
		} return;
	};
	
	request = function(node) {
		if (node.dataset.alreadyLoading) return;
		node.dataset.alreadyLoading = "true";
		return fetch(node.href).then(x => {
			if (x.ok) {
				x.text().then(text => {
					var doc = d.createElement("div"), img, _base;
					doc.innerHTML = text;
					if (img = doc.querySelector(l[0])) {
						_base = base(img[l[1]]);
						node.dataset.full = img[l[1]];
						if (slideEl.src.indexOf(_base) > -1)
							slideEl.src = img[l[1]];
					} else {
						fetch("/intermission.php").then(x2 => request(node))
					}
				});
			} else alert("Failed to make HTTP request\nDo you have an internet connection?")
		});
	};
	
	observer = new MutationObserver(function(mutations) {
		mutations.forEach(function(mutation) {
			array(mutation.addedNodes).forEach(function(node) {
				let a;
				if (node.nodeType == 1 && node.matches("span.thumb[id^='s']") && (a = node.firstElementChild) && !a.dataset.full) {
					if (node.querySelector("img[alt*='webm']")) return;
					a.dataset.full = "loading";
					a.onclick = mouseUp;
				}
			});
		}); 
	});
	observer.observe(d, {
		childList: true,
		subtree: true
	});
	
	d.addEventListener("animationend", e => e.animationName == 'Outlined' && e.target.classList.remove("outlined"), false);
	
	{
		let css = d.createElement("style");
		css.textContent = '@keyframes Outlined{0%{outline:6px solid orange}60%{outline:6px solid orange}100%{outline:6px solid transparent}}\n[data-slide="true"]{display:none!important;}#slide{max-width:100%;max-height:100%;min-width:100%;min-height:100%;object-fit:contain}.outlined{outline:6px solid transparent;animation-duration:4s;animation-name:Outlined}';
		d.head.appendChild(css);
	}
}())