By ttfn
—
Last update
Jun 30, 2008
—
Installed
1,750 times.
// ==UserScript==
// @name Endless Danbooru Pages
// @namespace namespace-20071209
// @description Makes danbooru pages infinitely long instead of limited to 16 posts per page by loading more when you scroll to near the bottom of the page.
// @author ttfn
// @include http://danbooru.donmai.us/post*
// ==/UserScript==
// Version 7
var mainTable = null;
var nextPage = null; // the number of the next page
var lastPage = null;
var tagSearch = null; // tags being searched for
var danbooruURL = "http://" + window.location.host + "/post";
var danbooruQuery = "/index.json?";
var pending = false;
var danbooruLogin = document.cookie.search("login=(.+?)(;|$)") != -1 ? document.cookie.match("login=(.+?)(;|$)")[1] : "";
var danbooruPasswordHash = document.cookie.search("pass_hash=(.+?)(;|$)") != -1 ? document.cookie.match("pass_hash=(.+?)(;|$)")[1] : "";
var crlf = String.fromCharCode(10) + String.fromCharCode(13);
if (danbooruLogin && danbooruPasswordHash) {
window.addEventListener("load", init, false);
// Check the scroll position on a timer because we can't use onscroll (bug 189308).
// If we do switch to onscroll, remember to call testScrollPosition after changing the page.
// setInterval(testScrollPosition, 100);
window.addEventListener("scroll", testScrollPosition, false);
}
function init() {
mainTable = findMainTable(document);
tagSearch = document.getElementById("tags").value;
// structure of paginator is -
// previous
// first
// text node elipsis
// page -2
// page -1
// text node current page
// page +1
// page +2
// text node elipsis
// last
// next
if (document.evaluate("//div[@id='paginator']/div[@class='pagination']/a[text()='>>']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue) {
// if the paginator has a '>>' "next page" element then get the current page number and the last page number.
nextPage = Number(document.evaluate("//div[@id='paginator']/div[@class='pagination']/span[@class='current']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent) + 1;
// element before >> contains the last page number
lastPage = Number(document.evaluate("//div[@id='paginator']/div[@class='pagination']/a[text()='>>']/preceding-sibling::*[1]", document, null, XPathResult.STRING_TYPE, null).stringValue.replace(",","","g"));
}
testScrollPosition();
}
function testScrollPosition() {
if ((!pending) && ((nextPage <= lastPage) && (window.innerHeight + window.scrollMaxY) - window.pageYOffset < 2.5 * window.innerHeight)) {
// We're near the bottom of the page; one press of pgdn could get close to the bottom of the page.
// (At about 1.9 * window.innerHeight, one press of pgdn would actually hit the bottom of the page.)
pullMore();
}
}
function pullMore() {
GM_xmlhttpRequest ({
method: "GET",
url: danbooruURL + danbooruQuery + ((tagSearch != "") ? "tags=" + escape(tagSearch) + "&" : "") + "page=" + nextPage + "&login=" + danbooruLogin + "&password_hash=" + danbooruPasswordHash,
onload: function(responseDetails) {
var result = eval("(" + responseDetails.responseText+ ")");
pending = false;
if (result["success"]==false) {
console.debug(result["reason"]);
return;
}
var arLen = result.length;
for ( var i=0; i<arLen; ++i ) {
// check thumb isn't already displayed
if (!document.getElementById("p" + String( result[i]["id"] ))) {
var imgTag=null, aTag=null, spanTag=null;
imgTag = document.createElement("img");
imgTag.src = result[i]["preview_url"];
imgTag.title = result[i]["tags"];
switch (result[i]["rating"]) {
case "s":
imgTag.title += " Rating: Safe";
break;
case "q":
imgTag.title += " Rating: Questionable";
break;
case "e":
imgTag.title += " Rating: Explicit";
break;
default:
break;
}
imgTag.title += " Score: " + result[i]["score"];
imgTag.alt = imgTag.title;
switch (result[i]["status"]) {
case "flagged":
imgTag.className = "preview flagged"
break;
case "pending":
imgTag.className = "preview pending"
break;
case "deleted":
imgTag.className = "preview deleted"
break;
default:
imgTag.className = "preview"
break;
}
if (result[i]["has_children"] === true) {
imgTag.className += " has-children";
}
if (result[i]["parent_id"] !== null) {
imgTag.className += " has-parent";
}
if (result[i]["preview_height"]) {
imgTag.height = result[i]["preview_height"];
}
if (result[i]["preview_width"]) {
imgTag.width = result[i]["preview_width"];
}
aTag = document.createElement("a");
aTag.href = danbooruURL + "/show/" + result[i]["id"];
aTag.setAttribute("onclick", "return PostModeMenu.click(" + result[i]["id"] + ")" );
spanTag = document.createElement("span");
spanTag.className = "thumb rating-" + result[i]["rating"];
spanTag.id = "p" + result[i]["id"];
aTag.appendChild(imgTag);
spanTag.appendChild(aTag);
mainTable.appendChild(spanTag);
// add details to existing danbooru data structures and rerun blacklist
unsafeWindow.Post.register( result[i] );
}
}
unsafeWindow.Post.init_blacklisted();
// add a HR and page number every 160 thumbs (10 pages)
if (((nextPage % 10) == 0) && (nextPage+1 <= lastPage) ) {
var hrTag = null, hTag = null, a2Tag = null;
hrTag = document.createElement("hr");
hrTag.style.clear = "both";
hTag = document.createElement("h2");
a2Tag = document.createElement("a");
a2Tag.href = danbooruURL + "?" + ((tagSearch != "") ? "tags=" + escape(tagSearch) + "&" : "") + "page=" + nextPage;
a2Tag.textContent = "Page " + String(nextPage);
mainTable.appendChild(hrTag);
hTag.appendChild(a2Tag)
mainTable.appendChild(hTag);
}
// call testScrollPosition again in case one page's worth of thumbs are not enough.
testScrollPosition();
},
onreadtstatechange: function(responseDetails) {
},
onerror: function(responseDetails) {
pending = false;
console.debug(responseDetails);
}
});
pending = true;
nextPage += 1;
}
function findMainTable(doc) {
return doc.evaluate("//div[@id='post-list']/div[@class='content']/div[span[@class='thumb']]", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
}