Adds endless scroll function to Gelbooru
As of
// ==UserScript==
// @id gelbooru-endless-scroll
// @name Gelbooru Endless Scroll
// @version 1.4
// @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?*
// @run-at document-end
// @grant none
// ==/UserScript==
(function(){
"use strict";
var d = document, _on = false, url,
v = ["span.thumb[id^='s']", "div.pagination"],
vis = function(el) {
var rect = el.getBoundingClientRect();
return (
rect.top + rect.height >= 0 &&
( d.documentElement.clientHeight - rect.bottom ) + rect.height >= 0
);
}, target = d.querySelector(v[1]), total,
page = function(doc) {
var images, pageNo = d.createElement`span`, frag = d.createDocumentFragment(), container;
images = [].slice.call(doc.querySelectorAll('post'));
if (images.length === 0)
throw Error("Broken API?");
pageNo.innerHTML = "Page " + url.index + "~<span>out of " + total + "</span>";
pageNo.className = "thumb";
pageNo.style = "display:flex;flex-direction:column;";
frag.appendChild(pageNo);
pageNo.firstElementChild.style = "margin:auto 0 30px";
images.map(a => {
let fn = e => {
e.target.onload = null;
thumb.style.overflow = "visible";
}, thumb = d.createElement("span"),
r = a.getAttribute("rating");
r = r == "s" ? "safe" : r == "q" ? "questionable" : r == "e" ? "explicit" : "unknown";
thumb.id = "s" + a.getAttribute("id");
thumb.className = "thumb";
thumb.insertAdjacentHTML("beforeend", '<a id="p'+a.getAttribute("id")+'" href="index.php?page=post&s=view&id='+a.getAttribute("id")+'"><img src="'+a.getAttribute("preview_url")+'?'+a.getAttribute("id")+'" alt="'+a.getAttribute("tags")+'" title="'+a.getAttribute("tags")+' score:'+a.getAttribute("score")+' rating:'+r+'" class="preview" border="0"></a>');
thumb.style.overflow = "hidden";
thumb.querySelector("img").onload = fn;
frag.appendChild(thumb);
});
container = d.querySelector(v[0]).parentNode;
if (container.lastElementChild.matches`span`) container.appendChild(frag);
else container.insertBefore(frag, container.querySelector`span.thumb:last-of-type + *`);
if (list.length > 0) {
events();
process();
} return;
}, req = _ => fetch(url.href).then(
x => x.text().then(
text => page((new DOMParser()).parseFromString(text, "text/xml").documentElement)
)
).catch(err => {
if (typeof err != "undefined") {
console.error("Something unexpected happened\n", err);
setTimeout(() => req(), 5000);
}
}), process = function() {
if (vis(target)) {
events();
url = list.shift();
return req();
}
}, events = function() {
var val = (_on = !_on) ? "addEventListener" : "removeEventListener";
window[val]("scroll", process, false);
window[val]("resize", process, false);
window[val]("visibilitychange", process, false);
}, list = [];
if (!target || !target.querySelector`a`) return;
{
let p = target.lastElementChild.href,
n = d.querySelectorAll(v[0]).length,
path = window.location.search,
pid = path.match(/pid=([0-9]+)/),
start_index = pid ? pid[1] / n + 1 : 1,
tags = path.match(/(?:\?|&)tags=([^&#]+)/i)[1],
end_index;
if (!p) return;
else {
end_index = p.match(/pid=([0-9]+)/)[1] / n + 1;
do {
list.push({
href: 'http://gelbooru.com/index.php?page=dapi&s=post&q=index&tags=' + tags + '&pid=' + start_index + '&limit=' + n,
index: ++start_index
});
} while(start_index < end_index);
total = end_index;
}
}
d.addEventListener("gelbooru-slide", _ => {
if (list.length > 0)
events();
}, false);
events();
process();
}())