您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a fullscreen image view option when you click on images
当前为
// ==UserScript== // @id gelbooru-slide // @name Gelbooru Image Viewer // @version 1.9.6.6 // @namespace intermission // @author intermission // @license WTFPL; http://www.wtfpl.net/about/ // @description Adds a fullscreen image view option when you click on images // @include http://gelbooru.com/* // @include https://gelbooru.com/* // @include http://gelbooru.com/ // @include https://gelbooru.com/ // @include http://rule34.xxx/* // @include https://rule34.xxx/* // @include http://rule34.xxx/ // @include https://rule34.xxx/ // @include http://e621.net/* // @include https://e621.net/* // @include http://e621.net/ // @include https://e621.net/ // @include http://*.booru.org/* // @include https://*.booru.org/* // @include http://*.booru.org/* // @include https://*.booru.org/* // @include http://*.paheal.net/ // @include https://*.paheal.net/ // @include http://*.paheal.net/* // @include https://*.paheal.net/* // @include http://*.sankakucomplex.com/* // @include https://*.sankakucomplex.com/* // @exclude http://www.sankakucomplex.com/* // @exclude https://www.sankakucomplex.com/* // @run-at document-start // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @grant GM_info // ==/UserScript== /* This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ (function (d, w, stor) { "use strict"; var domain = location.hostname.match(/[^\.]+\.[^\.]+$/)[0], ns = "gelbooru-slide", toggle = stor[ns] === "true", notification, Pos, Menu, Btn, slideshow, Main, Prog, Hover, paheal = domain == "paheal.net" ? 20 : 0, passive = { passive: true }; if (!stor[ns]) stor[ns] = "false"; GM_registerMenuCommand("Current image mode: " + (toggle ? "Always original size" : "Sample only"), () = > { if (domain !== "booru.org") stor[ns] = toggle ? "false" : "true"; return location.reload(); }); if (stor[ns + "-firstrun"] != "1.8.8") { (function (l) { var a, r = /^gelbooru-slide./; for (a in l) if (r.test(a)) l.removeItem(a); }(stor)); stor[ns + "-firstrun"] = "1.8.8"; } const $ = function (a, b) { return [...(b || d).querySelectorAll(a)]; }; $.extend = function (obj, props) { var key, val; for (key in props) { if (!props.hasOwnProperty(key)) continue; val = props[key]; obj[key] = val; } }; $.extend($, { cache(id, b) { var val = toggle ? "original" : "sample", ret, obj, temp; if (!b) { try { ret = JSON.parse(stor[ns + id])[val]; } catch (e) {} ret = ret || "loading"; } else { try { temp = JSON.parse(stor[ns + id]); } catch (e) {} obj = temp || {}; obj[val] = b; stor[ns + id] = JSON.stringify(obj); ret = b; } return ret; }, base: a = > a.match(Main.r[5]), current: src = > $("a[data-id] > img[src*='" + $.base(src || Main.el.dataset.src) + "']")[0].parentNode, find(el, method) { var a; el = el.parentNode; 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() { var curr = $.current(); Main.req($.find(curr, true)); return Main.req($.find(curr, false)); }, keyDown(e) { var move; if (slideshow) return; switch (e.keyCode) { case 32: case 39: move = true; break; case 37: move = false; break; case 38: if (e.event) Menu.fn(e.event); else w.location = $.current().href; return; case 40: e.preventDefault(); return Main.el.click(); } if (typeof move != "undefined") { e = $.find($.current(), move); if (e) { if (Prog.el) { Prog.el.classList.remove("progdone"); Prog.el.style.width = 0; } Main.slide(e.firstElementChild.src); Pos.fn(move); $.preload(); } else if (!notification) { notification = $.c("div"); notification.classList.add("nomoreimages"); notification.setAttribute("style", "background: linear-gradient(to " + (move ? "right" : "left") + ", transparent, rgba(255,0,0,.5));" + (move ? "right" : "left") + ": 0;"); d.body.insertBefore(notification, d.body.lastElementChild); } } return; }, c: c = > d.createElement(c), r: fn = > d.addEventListener("DOMContentLoaded", fn, { passive: true, once: true }), rm: (el, u) = > (el && el.parentNode.removeChild(el)) && u, eval(text) { let script = $.c("script"); script.appendChild(d.createTextNode(text)); d.body.appendChild(script); $.rm(script); } }); Pos = { fn(a) { var no, thumbs, el = Pos.el; if (typeof a === "boolean") { no = el.firstElementChild; no.innerHTML = Number(no.innerHTML) + (a ? 1 : -1); if (Menu.el) for (let a of $("a", Menu.el)) a.href = $.current().href; } else { if (Main.el && !el) { thumbs = $(".thumb a[data-full]"); Pos.el = el = $.c("div"); el.insertAdjacentHTML("beforeend", "<span>" + (thumbs.indexOf($.current()) + 1) + "</span> / " + thumbs.length); el.className = "posel"; Main.el.insertAdjacentElement("afterend", el); } else if (el) Pos.el = $.rm(el); } return; } }; Menu = { fn(e) { var _l = e.clientX + 1, _t = e.clientY + 1, left = (_l > w.innerWidth - 139 ? (_l - 139) : _l) + "px", top = (_t > w.innerHeight - 48 ? (_t - 48) : _t) + "px", href, el = Menu.el; if (el) { el.removeAttribute("class"); el.style.left = left; el.style.top = top; setTimeout(() = > el.classList.add("menuel"), 10); } else { href = $.current().href; Menu.el = el = $.c("div"); el.id = "menuel"; el.insertAdjacentHTML("beforeend", '<a href="' + href + '" style="margin-bottom: 2px">Open in This Tab</a><a href="' + href + '" target="_blank">Open in New Tab</a>'); el.style.left = left; el.style.top = top; d.body.appendChild(el); el.classList.add("menuel"); } return; } }; Btn = { fn() { var sel, el = Btn.el; sel = "this.previousElementSibling.firstElementChild"; if (el) { clearTimeout(Btn.hide_timer); Btn.clear(); Btn.el = $.rm(Btn.el); Hover.el.removeAttribute("style"); } else { Btn.el = el = $.c("div"); el.setAttribute("style", 'opacity: .7;'); el.className = "slideshow"; el.insertAdjacentHTML('beforeend', '<span title="Slideshow">' + Btn.svg_play + "</span>" + ` < div style = "display: none;padding: 10px 0" > Options < hr > < label > Loop: & nbsp; < input type = "checkbox" checked > < /label> <label onclick="${sel}.checked=true;${sel}.disabled=!${sel}.disabled">Shuffle: <input type="checkbox"></label > < br > Interval: < input type = "number" value = "5" style = "width: 100px" > < /div>`); Btn.svg_state = true; el.firstElementChild.onclick = Btn.cb; d.body.appendChild(el); } }, clear: () => clearTimeout(Number(Btn.el.dataset.timer) || 0), cb: (function() { var el, sel = ".thumb a[data-full]", options, _fnS = () => { el.dataset.timer = setTimeout(_fnT, options[2]); }, _fnT = () => { var _el; if (thumbs.length === 0) thumbs = $(sel); if (options[1]) { thumbs.splice(thumbs.indexOf($.current()), 1); _el = thumbs[Math.random() * thumbs.length & -1]; } else _el = $.find($.current(), true); if (!_el && options[0]) _el = $(sel)[0]; if (!_el) return Btn.cb(); Main.el.addEventListener("load", _fnS, { passive: true, once: true }); Main.slide(_el.firstElementChild.src); }, thumbs, orig; return function () { el = Btn.el; Pos.fn(); slideshow = !!Btn.svg_state; el.firstElementChild.innerHTML = (Btn.svg_state = !Btn.svg_state) ? Btn.svg_play : Btn.svg_pause; if (slideshow) { thumbs = []; options = $("div input", el).map(a => a.type == "number" ? (+a.value >= 1 ? +a.value : 1) * 1E3 : a.checked ); el.dataset.timer = setTimeout(_fnT, options[2]); el.style.opacity = ".4"; Hover.el.setAttribute("style", "display: none !important"); orig = d.body.getAttribute("style"); d.addEventListener("mousemove", Btn.hide); } else { Btn.clear(); el.style.opacity = ".7"; el.removeAttribute("data-timer"); Hover.el.removeAttribute("style"); Hover.center($.current().firstElementChild.src); d.removeEventListener("mousemove", Btn.hide); clearTimeout(Btn.hide_timer); if (orig) b.body.setAttribute("style", orig); else d.body.removeAttribute("style"); } }; })(), hide() { var b = d.body; b.style.cursor = ""; clearTimeout(Btn.hide_timer); Btn.hide_timer = setTimeout(b => b.style.cursor = "none", 5E3, b); }, hide_timer: -1, svg_play: '<svg width="50" height="50" version="1.1" xmlns="http:/ / www.w3.org / 2000 / svg "><rect rx=" 5 " height=" 48 " width=" 48 " y=" 1 " x=" 1 " fill="#fff " /><polygon fill=" #000" points= "16 12 16 38 36 25" / > < /svg>', svg_pause: '<span><svg width="50" height="50" xmlns="http:/ / www.w3.org / 2000 / svg "><rect fill="#fff " x=" 1 " y=" 1 " width=" 48 " height=" 48 " rx=" 5 " /><rect fill=" #000" x= "12" y = "12" width = "10" height = "26" / > < rect fill = "#000" x = "28" y = "12" width = "10" height = "26" / > < /svg>' }; Prog = { check: id => Main.el.dataset.id == id, load(e) { var blob, type, el = Prog.el, img = Main.el, c = e.context; delete Prog.reqs[c.id]; if (!el) throw Error("There was an event order issue with GM_xmlhttpRequest"); if (!(e.status === 200 || e.status === 304) || !Main.r[5].test(e.finalUrl)) if (c.url !== false && e.finalUrl.split('/ ').pop() == "redirect.png") Prog.fn(c.url, c.id, true); else return Prog.error(e); else { let blob_url; type = "image/" + c.ext.replace("jpeg", "jpg"); blob = new Blob([e.response], {type: type}); blob_url = w.URL.createObjectURL(blob); $("a[data-id=' " + c.id + " ']")[0].dataset.blob = blob_url; if (img && Prog.check(c.id)) { el.classList.add("progdone"); img.src = blob_url; } } }, progress(e) { var el = Prog.el, id = e && e.context.id; if (!el) { Prog.el = el = $.c("span"); el.setAttribute("style", "width:0"); el.classList.add("progress"); d.body.appendChild(el); } if (e && e.lengthComputable && Main.el && Prog.check(id) && el) { el.classList.remove("progfail"); el.style.width = (id in Prog.reqs ? e.loaded / e.total * 100 : 0) + "%"; } else return el; }, error(e) { var el = Prog.el, id = e.context.id; if (Main.el && Prog.check(id) && el) { el.classList.add("progfail"); try { Prog.reqs[id].abort(); } catch(err) {} delete Prog.reqs[id]; } if (slideshow) Main.el.dispatchEvent(new Event("load")); stor.removeItem(ns + id); $("a[data-id=' " + id + " ']")[0].dataset.full = "loading"; }, fn(url, id, nocache) { var details, context = { id: id, url: url, ext: url.match(Main.r[2])[1], nocache: nocache }; if (Prog.el) Prog.el.style.width = 0; details = { context: context, method: "GET", url: url, responseType: "arraybuffer", onload: Prog.load, onprogress: Prog.progress, onerror: Prog.error, onabort: Prog.error, ontimeout: Prog.error, headers: {} }; if (domain == "sankakucomplex.com") details.headers["Referrer"] = details.headers["Origin"] = location.origin + "/post/show/" + id; if (nocache === true) { details.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"; context.nocache = false; } if (!(id in Prog.reqs)) Prog.reqs[id] = GM_xmlhttpRequest(details); }, reqs: {} }; Hover = { fn() { var el = Hover.el; if (el) { el = el.firstElementChild; Hover.cancel(); Hover.el.children[1].removeAttribute("style"); if (el.getAttribute("style")) el.removeAttribute("style"); else el.setAttribute("style", "display: none"); } else { Hover.el = el = $.c("div"); el.insertAdjacentHTML("beforeend", `<div class="layover"></div><div class="tentcon"><div class="wrapthatshit"><div class="listimage"></div></div></div><svg style="width: 0; height: 0" xmlns="http://www.w3.org/2000/svg"><filter id="__dropshadow"><feGaussianBlur in="SourceAlpha" stdDeviation="2"></feGaussianBlur><feOffset result="offsetblur" dx="1" dy="1"></feOffset><feMerge><feMergeNode></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></svg>`); el.className = "viewpre"; d.body.appendChild(el); Hover.index = -1; Hover.target = $(".listimage", Hover.el)[0]; if (domain != "sankakucomplex.com") { Hover.target.appendChild(Hover.next_el = $.c("span")); Hover.next_el.className = "next"; Hover.next_el.addEventListener("click", Hover.next, passive); } for (let el of $("a[data-full]")) Hover.build(el); Hover.kinetic(); } }, next() { var timer; if (Hover.next_el.classList.contains("loadingu")) return; timer = setTimeout(() => { Hover.next_el = $.rm(Hover.next_el); Hover.size(); }, 2E3); Hover.next_el.classList.add("loadingu"); d.dispatchEvent(new CustomEvent(ns + "-next", { detail: timer })); }, size() { Hover.target.style.width = Hover.target.children.length * (180 + paheal) + "px"; }, build(el) { var span = $.c("span"), img = $.c("img"); img.src = el.firstElementChild.src; img.dataset.nth = ++Hover.index; span.title = el.firstElementChild.title; if (el.dataset.gif) img.style.outline = "2px solid lime"; span.appendChild(img); if (Hover.next_el) Hover.target.insertBefore(span, Hover.next_el); else Hover.target.appendChild(span); img.addEventListener("click", Hover.click, passive); img.addEventListener("dragstart", e => e.preventDefault()); Hover.size(); }, click(e) { if (Hover.prevent) return Hover.prevent = null; e = e.currentTarget.src; Main.slide(e); Hover.center(e); if (Pos.el) Pos.el.children[0].innerHTML = +$("img[src*=' " + $.base(e) + " ']", Hover.el)[0].dataset.nth + 1; }, center (src) { var base = $.base(src), img = $("img[src*=' " + base + " ']", Hover.el)[0], pos = +img.dataset.nth, scroll = $(".wrapthatshit", Hover.el)[0], half = scroll.offsetWidth / 2, width = 180 + paheal, dist = pos * width + width / 2, res = dist - half, curr = $(".current", Hover.el)[0]; if (curr) curr.removeAttribute("class"); Hover.cancel(); Hover.el.children[1].removeAttribute("style"); scroll.scrollLeft = res > 0 ? res : 0; img.parentNode.setAttribute("class", "current"); }, kinetic() { var view = Hover.target.parentNode, offset, reference, pressed = !1, velocity, frame, timestamp, ticker, amplitude, target, rm = _ => Hover.el.children[1].removeAttribute("style"); function scroll(x) { var max = view.scrollLeftMax; offset = x > max ? max : x < 0 ? 0 : x; view.scrollLeft = offset; if (offset === 0 || offset === max) { amplitude = 0; Hover.cancel(); rm(); } } function track() { var now, elapsed, delta, v; now = Date.now(); elapsed = now - timestamp; timestamp = now; delta = offset - frame; frame = offset; v = 1000 * delta / (1 + elapsed); velocity = 0.8 * v + 0.2 * velocity; } function autoScroll() { var elapsed, delta; if (amplitude) { elapsed = Date.now() - timestamp; delta = -amplitude * Math.exp(-elapsed / 15E2); if (delta > 5 || delta < -5) { Hover.el.children[1].setAttribute("style", "transform: unset"); scroll(target + delta); Hover.kinetID = requestAnimationFrame(autoScroll); } else { rm(); scroll(target); } } } function tap(e) { Hover.prevent = !(pressed = true); rm(); clearInterval(ticker); velocity = amplitude = 0; if (e.target == Hover.target.parentNode) return pressed = false; reference = e.clientX; offset = view.scrollLeft; frame = offset; timestamp = Date.now(); ticker = setInterval(track, 100 / 3); } function drag(e) { var x, delta; if (pressed) { x = e.clientX; delta = reference - x; if (delta > 1 || delta < -1) { Hover.prevent = true; reference = x; scroll(offset + delta); } } } function release(e) { pressed = false; clearInterval(ticker); if (velocity > 10 || velocity < -10) { amplitude = 0.8 * velocity; target = offset + amplitude & -1; timestamp = Date.now(); Hover.kinetID = requestAnimationFrame(autoScroll); } } view.addEventListener(' mousedown ', tap, passive); view.addEventListener(' mousemove ', drag, passive); view.addEventListener(' mouseup ', release, passive); }, cancel() { try { cancelAnimationFrame(Hover.kinetID); } catch(e) {} } }; Main = { sel: ".thumb", init() { var observer; if (domain != "sankakucomplex.com" && location.pathname == "/") return $.r(Main.front); function click(e) { if (e.button === 0) { e.preventDefault(); e.stopPropagation(); Main.fn(e.currentTarget); } } function process(node) { var a, id, alt; try { if (node && node.nodeType === 1 && node.matches(Main.sel) && (a = node.firstElementChild) && !a.dataset.full) { alt = $("img[alt]", node)[0]; if (!alt) return; alt = alt.alt || alt.title || ""; if (Main.r[3].test(alt) || $("img[src*=' webm - preview.png ']", node).length) return; id = (node.id || a.id || a.children[0].id).match(Main.r[4])[0]; if (!id) throw Error("Incompatible booru - missing IDs from thumbnails"); if (domain == "gelbooru.com") a.setAttribute("href", "/index.php?page=post&s=view&id=" + id); if (alt && ~alt.indexOf("animated_gif")) { a.firstElementChild.style.border = "2px solid lime"; a.dataset.gif = "gif"; } a.dataset.id = id; if (domain == "paheal.net") a.dataset.full = node.lastElementChild.previousElementSibling.href; else a.dataset.full = $.cache(id); node.removeAttribute("onclick"); a.removeAttribute("onclick"); a.addEventListener("click", click); if (Hover.el) Hover.build(a); } } catch(err) { console.error(err); } } function hijack() { var qS = ' document.querySelector("#post-list > .content', iB = 'insertBefore'; if (!$(Main.sel).length) return; $.eval(` Object.defineProperty(${qS}"), "${iB}", { value: function $ { iB }(newEl, pos) { if (newEl.nodeType !== 11) return (pos.nodeType === 3 ? pos.nextElementSibling : pos).insertAdjacentElement("beforebegin", newEl); else { let s = $ { qS } > div: first - of - type "); for (let t of newEl.firstElementChild.children) { t.classList.remove(" blacklisted "); t.removeAttribute(" style "); s.appendChild(t); } } return newEl; } })`); } switch(domain) { case " booru.org ": Main.r[0] = Main.r[1] = /<img alt=" img " src=" ([ ^ "]+)/i; Main.css += "\nspan.thumb {\n float: left\n } "; break; case " e621.net ": Main.css += "\n.thumb > a[data - id] {\n display: inline - block;\n margin - bottom: -3px\n } "; break; case " sankakucomplex.com ": Main.r[0] = /<a href=" ([ ^ "> ]+)" id = highres[ ^ > ] * ?> /; Main.r[1] = / < img[ ^ > ] * ? id = "?image" ? [ ^ > ] * ? src = "?([^" > ] + ) "?[^>]*>/; Main.sel = "#post - list div.content > div: first - of - type > .thumb "; Main.css += "\ndiv.content {\n position: static!important;\n padding - left: 0\n }\n.stick + div.content {\n padding - left: 238px\n } "; $.r(hijack); } observer = new MutationObserver(mutations => mutations.forEach(mutation => [...mutation.addedNodes].forEach(process))); observer.observe(d, { childList: true, subtree: true }); d.addEventListener(" animationend ", e => { switch(e.animationName) { case " Outlined ": e.target.classList.remove(" outlined "); break; case " nomoreimages ": notification = $.rm(e.target); break; case " menuelement ": Menu.el = $.rm(e.target); break; case " warn ": $.rm(e.target); break; case " progfail ": case " progdone ": Prog.el = $.rm(e.target); } }, passive); w.addEventListener(" keypress ", e => { if (e.key === " Enter " || e.keyCode === 13) { if (slideshow) { Btn.cb(); } else if (e.target.matches(".thumb > a[data - full] ")) { e.preventDefault(); Main.fn(e.target); } } }); w.addEventListener(" wheel ", e => Main.el && $.keyDown({ keyCode: e.deltaY > 0 ? 39 : e.deltaY < 0 ? 37 : 0 }), passive); $.r(Main.ready); }, ready() { var style = $.c(" style "); style.appendChild(d.createTextNode(Main.css)); d.head.appendChild(style); setTimeout(() => { let san_el = $(" a#sc - auto - toggle ")[0]; if (!san_el) return; Main.san_fix = val => (unsafeWindow || window).Sankaku.Pagination.auto_enabled !== val && san_el.click(); }, 500); }, fn(node) { d.dispatchEvent(new CustomEvent(ns, { detail: Main.el ? true : false })); return Main[Main.el ? " off " : " on "](node); }, off(a) { var center; slideshow = !(a = $.current()); Main.el = $.rm(Main.el); d.body.classList.remove(" sliding "); a.classList.add(" outlined "); d.removeEventListener(" keydown ", $.keyDown); if (domain == " sankakucomplex.com ") a = a.firstElementChild; center = a.offsetTop + a.offsetHeight / 2 - w.innerHeight / 2; w.scrollTo(0, center < 0 ? 0 : center); Pos.fn(); Btn.fn(); Hover.fn(); Main.gif = $.rm(Main.gif); Prog.el = $.rm(Prog.el); Main.san_fix(true); }, on(a) { var el; if (Main.san_fix) Main.san_fix(false); d.body.classList.add(" sliding "); for (let a of $(" a.outlined[data - full] ")) a.classList.remove(" outlined "); Main.el = el = $.c(" img "); el.id = " slide "; el.alt = " Loading... "; el.onclick = Main.fn; el.onmouseup = e => e.button === 1 && $.keyDown({keyCode:38, event:e}); d.body.appendChild(el); d.documentElement.scrollIntoView(); Main.gif = el = $.c(" span "); el.innerHTML = '<svg xmlns=" http: //www.w3.org/2000/svg" viewBox="-10 -3 36 22"><path d="M26 16c0 1.6-1.3 3-3 3H-7c-1.7 0-3-1.4-3-3V0c0-1.7 1.3-3 3-3h30c1.7 0 3 1.3 3 3v16z" opacity=".6"/><path fill="#FFF" d="M22-1H-6c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h28c1.1 0 2-.9 2-2V1c0-1.1-.9-2-2-2zM6.3 13.2H4.9l-.2-1.1c-.4.5-.8.9-1.3 1.1-.5.2-1 .3-1.4.3-.8 0-1.5-.1-2.1-.4s-1.1-.6-1.5-1.1-.7-1-1-1.6C-2.9 9.7-3 9-3 8.3c0-.7.1-1.4.3-2.1.2-.6.5-1.2 1-1.7s.9-.8 1.5-1.1C.5 3.2 1.2 3 1.9 3c.5 0 1 .1 1.5.2.5.2.9.4 1.3.7.4.3.7.7 1 1.1.2.5.4 1 .4 1.5H4c-.1-.5-.3-.9-.7-1.2-.4-.3-.8-.4-1.4-.4-.5 0-.9.1-1.2.3-.4.1-.7.4-.9.7-.2.3-.3.7-.4 1.1s-.1.8-.1 1.3c0 .4 0 .8.1 1.2s.3.8.5 1.1c.2.3.5.6.8.8s.8.3 1.3.3c.7 0 1.3-.2 1.7-.6.4-.4.6-.9.7-1.6H2.1V7.8h4.2v5.4zm4 0H8.1v-10h2.2v10zm8.9-8.1h-4.8v2.3h4.2v1.7h-4.2v4.1h-2.2v-10h7v1.9z"/></svg>'; el.classList.add("gif"); Hover.fn(); d.body.appendChild(el); try { Main.slide(a.firstElementChild.src); } catch (err) { console.error(err); } d.addEventListener("keydown", $.keyDown); Pos.fn(); Btn.fn(); $.preload(); }, slide(src) { var data, curr; if (!slideshow) Main.el.src = src; Hover.center(src); Main.el.dataset.src = src; curr = $.current(src); Main.el.dataset.id = curr.dataset.id; data = curr.dataset.full; Main.gif.removeAttribute("style"); /* dirty hack ahead because GIF doesn't want to play as a blob * and doesn't give proper progress info for * GM_xmlhttpRequest for whatever reason */ if (data == "loading") return Main.req(curr); // hack start else if (data.match(Main.r[2])[1].toLowerCase() == "gif") { Main.el.removeAttribute("src"); Main.el.src = data; Main.gif.setAttribute("style", "display: inline-block"); } // hack end else if (curr.dataset.blob) { Main.el.src = curr.dataset.blob; if (Prog.el) Prog.el = $.rm(Prog.el); let el = Prog.progress(); el.style.width = "100%"; el.classList.add("progdone"); } else Prog.fn(data, curr.dataset.id); }, r: [/file_url[=>]"?([^" <]+)"?/i, /sample_url[=>]"?([^" <]+)"?/i, /\.(gif|png|jpe?g)/i, /\b(webm|video|mp4|flash)\b/i, /\d+/, /[a-f0-9]{32}/], req(node) { var process, id, api; if (!node || node.dataset.alreadyLoading || node.dataset.full != "loading") return; switch (domain) { case "e621.net": id = node.parentNode.id.substr(1); api = "/post/show.xml?id="; break; case "sankakucomplex.com": id = node.parentNode.id.substr(1); api = "/post/show/"; break; case "booru.org": id = node.dataset.id; api = "/index.php?page=post&s=view&id="; break; default: id = node.dataset.id; api = "/index.php?page=dapi&s=post&q=index&id="; } process = function (img) { img = img.match((!node.dataset.gif && !toggle) ? Main.r[1] : Main.r[0])[1]; if (!img) throw Error("API error"); node.dataset.full = $.cache(id, img); if (Main.el && ~Main.el.dataset.src.indexOf($.base(img))) { try { Main.slide(img); } catch (err) { console.error(err); } } $("img", node)[0].style.outline = ""; return node.removeAttribute("data-already-loading"); }; node.dataset.alreadyLoading = "true"; return fetch(api + id) .then(x = > x.text()) .then(process) . catch (err = > { Main.warn(); $("img", node)[0].style.outline = "6px solid red"; console.error("Failed HTTP request\nDo you have an internet connection?\n", err); return node.removeAttribute("data-already-loading"); }); }, warn() { var warn = $.c("span"); warn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><style>path.a{fill:red;stroke-width:8px;stroke:black;}</style><path d="M500 673c-17 0-34 4-48 11-24 12-44 33-55 58-5 14-9 28-9 44 0 62 50 113 112 113 63 0 113-50 113-113C613 723 562 673 500 673zM500 843c-32 0-58-26-58-58 0-32 26-58 58-58 32 0 59 26 59 58C558 817 532 843 500 843z" class="a"/><path d="M285 643c4 3 8 5 12 5l132-138c-57 14-109 47-149 94C272 617 273 634 285 643z" class="a"/><path d="M606 522L565 565c43 13 83 39 112 75 5 7 13 10 21 10 6 0 12-2 17-6 11-9 13-27 3-38C689 568 650 539 606 522z" class="a"/><path d="M500 384c16 0 32 1 48 3l46-48c-30-7-61-10-93-10-137 0-265 61-351 167-10 11-8 29 4 38 5 4 11 7 17 7 8 0 15-4 21-10C267 438 379 384 500 384z" class="a"/><path d="M729 393l-38 40c45 24 86 58 119 98 10 12 27 14 39 4 12-9 13-27 4-38C817 454 776 420 729 393z" class="a"/><path d="M685 244l41-43c-70-28-147-42-226-42-188 0-364 84-484 230-9 12-7 29 4 39 5 4 11 6 17 6 8 0 16-3 21-10 109-133 270-210 442-210C564 214 626 224 685 244z" class="a"/><path d="M984 389c-38-48-83-88-133-121l-38 40c49 32 93 71 130 117 9 11 27 13 38 4C991 418 994 401 984 389z" class="a"/><path d="M907 110c-11-10-28-10-38 1L181 828c-10 11-10 28 1 38 5 5 12 8 19 8 7 0 14-3 20-8L908 148C918 138 918 120 907 110z" class="a"/></svg>'; warn.classList.add("warn"); if ($(".sliding>.warn").length === 0) d.body.appendChild(warn); if (slideshow) Main.el.dispatchEvent(new Event("load")); }, front() { var target, method; switch (domain) { case "e621.net": target = "#mascot_artist"; method = "afterend"; break; case "booru.org": case "rule34.xxx": target = "#static-index > div:last-child > p:first-child"; method = "beforeend"; break; default: target = "form:last-of-type + div"; method = "beforeend"; } $("#tags")[0].focus(); $(target)[0].insertAdjacentHTML(method, ` < br > < br > Gelbooru & nbsp; Enhancement: < br > < pre style = "font-size: 11px;text-align: left;display: inline-block;margin-top: 5px;" > -Gelbooru Image Viewer $ { GM_info.script.version } < /pre>`); }, css: ` @keyframes Outlined { 0% { outline: 6px solid orange } 60% { outline: 6px solid orange } 100% { outline: 6px solid transparent } } @keyframes nomoreimages { 0% { opacity: 0 } 20% { opacity: 1 } 100% { opacity: 0 } } @keyframes menuelement { 0% { opacity: 1 } 80% { opacity: 1 } 100% { opacity: 0 } } @keyframes progfail { 0% { opacity: 1 } 80% { opacity: 1 } 100% { opacity: 0 } } @keyframes warn { 0% { opacity: 0; bottom: 5vh } 25% { opacity: 1; bottom: 10vh } 90% { opacity: 1 } 100% { opacity: 0 } } body.sliding > * { display: none } body.sliding > .warn { z-index: 2; display: inline-block; position: absolute; width: 10vw; left: 45vw; bottom: 10vh; animation-duration: 2s; animation-name: warn; pointer-events: none } #slide { position: absolute; z-index: 1; width: 100vw; height: 100vh; object-fit: contain; display: inherit; top: 0; left: 0 } .outlined { outline: 6px solid transparent; animation-duration: 4s; animation-name: Outlined } body.sliding > .nomoreimages { z-index: 4; pointer-events: none; display: block; width: 33vw; height: 100vh; top: 0; position: fixed; animation-duration: 1s; animation-name: nomoreimages } span.thumb { max-width: 180px; max-height: 180px } #menuel { z-index: 3; opacity: 1; position: fixed; display: block; padding: 2px; background: black; width: 139px; height: 44px; animation-duration: 1s } body.sliding > .menuel { animation-name: menuelement } #menuel:hover { animation-name: keepalive } #menuel a { background: #fff; color: #006FFA; display: block; font-size: 16px; font-family: verdana, sans-serif; font-weight: unset } #menuel a:hover { color: #33CFFF } #menuel a:visited { color: #006FFA } body.sliding > .slideshow { z-index: 2; display: block; position: fixed; bottom: 20px; right: 20px; font-size: 16px; font-family: verdana, sans-serif } body.sliding > .progress { z-index: 6; display: block; background-color: rgb(128,200,255); height: 1vh; position: absolute; top: 0; left: 0; box-shadow: 0 .5vh 10px rgba(0,0,0,.7), inset 0 0 .1vh black; transition: ease-in-out .08s width; min-height: 3px; max-width: 100vw; pointer-events: none; will-change: width, opacity } body.sliding > .progfail { background-color: red; width: 100% ! important; animation-name: progfail; animation-duration: 1.5s } body.sliding > .progdone { width: 100% ! important; animation-name: progfail; animation-duration: .6s } .slideshow:hover:not([data-timer]) > div { background: white; color: black; position: fixed; display: block ! important; bottom: 70px; right: 20px } body.sliding > .gif { z-index: 5; pointer-events: none; position: absolute; top: 3vh; right: 2vw; width: 3.5vw; opacity: .7; min-width: 50px; transition: ease .15s margin-top; margin-top: 0; will-change: margin-top } body.sliding { padding: 0; overflow: hidden } body.sliding > .viewpre { display: block } .viewpre > div { display: inherit; z-index: 5; position: absolute; top: 0; left: 0; width: 100%; height: ${200 + paheal * 2}px } .viewpre > .tentcon { transform: translateY(-100%); transition: ease .15s transform; background: linear-gradient(to bottom, black, transparent); will-change: transform } .viewpre:hover > .tentcon { transform: unset } .viewpre .wrapthatshit, .viewpre .wrapthatshit > .listimage { transform: rotateX(180deg); } .viewpre:hover ~ .gif { margin-top: ${200 + paheal * 2}px } .wrapthatshit { height: 100%; width: 100%; overflow-x: auto } .listimage { height: ${180 + paheal}px; -webkit-user-select: none; -moz-user-select: none; user-select: none; margin: 0 auto } .listimage span { height: ${180 + paheal}px; width: ${180 + paheal}px; text-align: center; display: table-cell; vertical-align: middle } .listimage span img { cursor: pointer } .listimage .current { background: linear-gradient(to top, transparent 0%, hsla(204, 100%, 56%, .8) 2%, transparent 30%, transparent 100%) } .listimage .next::after { content: "LOAD\\ANEXT\\APAGE"; font-size: 30px; text-transform: full-width; white-space: pre-wrap; color: white; filter: url(#__dropshadow) } .listimage .next { cursor: pointer } body.sliding > .posel { position: fixed; bottom: 20px; left: 0; display: block; pointer-events: none; z-index: 2; font-size: 16px; font-family: verdana, sans-serif }` }; Main.init(); }(document, window, localStorage));