Gelbooru Endless Scroll

Adds endless scroll function to Gelbooru

2017-06-03 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

// ==UserScript==
// @id             gelbooru-endless-scroll
// @name           Gelbooru Endless Scroll
// @version        1.6.6
// @namespace      intermission
// @author         intermission
// @license        WTFPL; http://www.wtfpl.net/about/
// @description    Adds endless scroll function to Gelbooru
// @include        http://gelbooru.com/index.php?*
// @include        https://gelbooru.com/index.php?*
// @include        http://rule34.xxx/index.php?*
// @include        https://rule34.xxx/index.php?*
// @include        http://*.booru.org/index.php?*
// @include        https://*.booru.org/index.php?*
// @include        http://e621.net/post/index/*
// @include        https://e621.net/post/index/*
// @include        http://rule34.paheal.net/post/list/*
// @include        https://rule34.paheal.net/post/list/*
// @run-at         document-end
// @grant          none
// ==/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. */

(function () {
    "use strict";
    var d = document,
        url, v = ".thumb",
        vis = function () {
            var rect = target().getBoundingClientRect();
            return rect.x === 0 && rect.y === 0 ? false : rect.top + rect.height >= 0 && document.documentElement.clientHeight - rect.bottom + rect.height >= 0;
        }, total,
        page = function (doc) {
            var images, pageNo = d.createElement("paheal.net" === host ? "div" : "span"),
                frag = d.createDocumentFragment(),
                container,
                fn = (e) = > {
                    e.target.onload = null;
                    (e = e.target.parentNode.parentNode).style.overflow = "";
                    if (!e.getAttribute("style")) e.removeAttribute("style");
                }, base = a = > a.match(r2);
            images = [...doc.querySelectorAll(v)];
            if (images.length === 0) throw Error("API error");
            pageNo.innerHTML = '<span style="height:' + ("paheal.net" === host ? "180px" : "inherit") + ';display:flex;flex-direction:column;">Page ' + url.index + '~<span style="margin:auto 0 30px">out of ' + total + "</span></span>";
            pageNo.className = "thumb";
            if ("paheal.net" === host) pageNo.setAttribute("style", "transform: translateY(-180px); margin-bottom: -180px");
            frag.appendChild(pageNo);
            for (let a of images) {
                let img = a.querySelector("img");
                if (d.querySelector("img[src*='" + base(img.src) + "']")) continue;
                a.style.overflow = "hidden";
                img.onload = fn;
                frag.appendChild(a);
            }
            container = d.querySelector(v).parentNode;
            if (container.lastElementChild.matches("span")) container.appendChild(frag);
            else container.insertBefore(frag, container.querySelector(".thumb:last-of-type + *"));
            for (let el of d.querySelectorAll(".loadingu")) el.classList.remove("loadingu");
            if (paginator.go) paginator();
            if (list.length > 0) {
                events(true);
                process();
            }
            return;
        }, req = _ = > fetch(url.href).then(
        x = > x.text().then(
        text = > page((new DOMParser()).parseFromString(text, "text/html")))).
        catch (err = > {
            for (let el of d.querySelectorAll(".loadingu")) el.classList.remove("loadingu");
            if (typeof err !== "undefined") {
                if (_.attempt < 10) {
                    ++_.attempt;
                    console.error("An error occured, retrying\n", err.message, err.stack);
                    setTimeout(req, 5000, _);
                } else console.error("Maximum number of retries reached\n", err.message, err.stack);
            }
        }),
        process = function (_override) {
            if (vis() || (typeof _override === "boolean" ? _override : false)) {
                target().classList.add("loadingu");
                events();
                url = list.shift();
                return req({
                    attempt: 0
                });
            }
        }, events = function (_on) {
            var name = _on ? "addEventListener" : "removeEventListener",
                obj = {
                    passive: true
                };
            ["scroll", "resize", "visibilitychange"].forEach(evt = > window[name](evt, process, obj));
        }, list = [],
        r = /(pid=|index\/)([0-9]+)|(list\/(?:[^\/]+\/)?)([0-9]+)$/,
        r2 = /[a-f0-9]{32}/,
        paginator = function () {
            var el = target(),
                rect1 = d.querySelector(".thumb:last-of-type"),
                el2 = d.querySelector(".sidebar"),
                rect2;
            if (el.classList.contains("pagination")) el = el.parentNode;
            rect1 = rect1.offsetTop + rect1.offsetHeight;
            rect2 = el2.offsetTop + el2.offsetHeight - 9;
            if (rect2 >= rect1) {
                el.style.position = "absolute";
                el.style.top = rect1 + "px";
                el.style.left = "calc(50vw + " + el2.getBoundingClientRect().width / 2 + "px)";
                el.style.transform = 'translateX(-50%)';
            } else {
                el.style.position = "";
                el.style.top = "";
                el.style.left = "";
                el.style.transform = "";
                paginator.go = false;
            }
        }, host = location.hostname.match(/[^\.]+\.[^\.]+$/)[0];
    const target = () = > d.querySelector("div.pagination") || d.querySelector("div#paginator") || d.querySelector("section#paginator"); {
        let style = d.createElement("style");
        style.appendChild(d.createTextNode(`.loadingu {
            position: relative;
        }.loadingu::after {
            content: ""!important;
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            width: 100 % ;
            height: 100 % ;
            min - width: 34px;
            min - height: 34px;
            background: rgba(0, 0, 0, .5) no - repeat center center url(data: image / svg + xml, % 3Csvg % 20width % 3D % 2234px % 22 % 20height % 3D % 2234px % 22 % 20xmlns % 3D % 22http % 3A % 2F % 2Fwww.w3.org % 2F2000 % 2Fsvg % 22 % 20viewBox % 3D % 220 % 200 % 20100 % 20100 % 22 % 20preserveAspectRatio % 3D % 22xMidYMid % 22 % 20class % 3D % 22uil - ring - alt % 22 % 3E % 3Crect % 20x % 3D % 220 % 22 % 20y % 3D % 220 % 22 % 20width % 3D % 22100 % 22 % 20height % 3D % 22100 % 22 % 20fill % 3D % 22none % 22 % 20class % 3D % 22bk % 22 % 3E % 3C % 2Frect % 3E % 3Ccircle % 20cx % 3D % 2250 % 22 % 20cy % 3D % 2250 % 22 % 20r % 3D % 2240 % 22 % 20stroke % 3D % 22 % 23b4b197 % 22 % 20fill % 3D % 22none % 22 % 20stroke - width % 3D % 2210 % 22 % 20stroke - linecap % 3D % 22round % 22 % 3E % 3C % 2Fcircle % 3E % 3Ccircle % 20cx % 3D % 2250 % 22 % 20cy % 3D % 2250 % 22 % 20r % 3D % 2240 % 22 % 20stroke % 3D % 22 % 23f4efcc % 22 % 20fill % 3D % 22none % 22 % 20stroke - width % 3D % 226 % 22 % 20stroke - linecap % 3D % 22round % 22 % 3E % 3Canimate % 20attributeName % 3D % 22stroke - dashoffset % 22 % 20dur % 3D % 221s % 22 % 20repeatCount % 3D % 22indefinite % 22 % 20from % 3D % 220 % 22 % 20to % 3D % 22502 % 22 % 3E % 3C % 2Fanimate % 3E % 3Canimate % 20attributeName % 3D % 22stroke - dasharray % 22 % 20dur % 3D % 221s % 22 % 20repeatCount % 3D % 22indefinite % 22 % 20values % 3D % 22150.6 % 20100.4 % 3B1 % 20250 % 3B150.6 % 20100.4 % 22 % 3E % 3C % 2Fanimate % 3E % 3C % 2Fcircle % 3E % 3C % 2Fsvg % 3E);
        }`));
        d.head.appendChild(style);
    }
    if (target() && /\/post\/|page=post/.test(location.href)) {
        let pid = location.href.match(r),
        p = (pid && pid[1] === "index/" ? target().lastElementChild.previousElementSibling : target().lastElementChild).href,
        n = d.querySelectorAll(v).length,
        start_index, end_index, increment, index = 1;
        if (host === "paheal.net") {
            let ayy = [...target().children[0].children];
            p = ayy[ayy.indexOf(ayy.find(el = > !! ~el.textContent.indexOf("Random"))) + 2].href;
        }
        if (!p) return;
        switch (host) {
            case "gelbooru.com":
            case "rule34.xxx":
                start_index = pid ? pid[2] / n : 0;
                increment = n;
                end_index = p.match(r)[2] / n;
                paginator.go = true;
                break;
            case "booru.org":
                start_index = pid ? pid[2] / n : 0;
                increment = n;
                end_index = p.match(r)[2] / n;
                break;
            case "e621.net":
                start_index = pid ? +pid[2] : 2;
                increment = 1;
                index = 0;
                end_index = +p.match(r)[2];
                break;
            case "paheal.net":
                start_index = pid ? +pid[4] : 1;
                increment = 1;
                index = 0;
                end_index = +p.match(r)[4];
                break;
        }
        while (start_index < end_index)
        list.push({
            href: p.replace(r, (host === "paheal.net" ? "$3" : "$1") + ++start_index * increment),
            index: start_index + index
        });
        total = end_index + index;
    }
    if (paginator.go) paginator();
    d.addEventListener("gelbooru-slide", e = > {
        console.log(e);
        if (list.length > 0) events(e.detail);
    }, false);
    d.addEventListener("gelbooru-slide-next", e = > {
        if (list.length > 0) {
            clearTimeout(e.detail);
            process(true);
        }
    }, false);
    events(true);
    if (vis()) process();
}());