Endless Danbooru Pages

By ttfn Last update Jan 24, 2010 — Installed 5,171 times.

There are 1 previous version of this script.

// ==UserScript==
// @name          Endless Danbooru Pages
// @namespace     namespace-20071209
// @description   Makes danbooru pages infinitely long instead of limited to 20 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 8

var mainTable = null;

var before_id = null;
var page_count = 0; 

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] : "";

if (danbooruLogin && danbooruPasswordHash) {
  window.addEventListener("load", init, false);

  // check the scroll position when the window is scrolled
  window.addEventListener("scroll", testScrollPosition, false);

  // check position every 5 seconds
  setInterval(testScrollPosition, 5000);
}

function init() {
  mainTable = findMainTable(document);
  tagSearch = document.getElementById("tags").value;

  // paginator after 1000 pages becomes 
  //   « Previous Next »  
  // and switches to using the before_id= syntax (you give it an id number and
  // it gives you the twenty posts before that one, not including the id
  // number specified.

  // check for the presence of a next paginator (either ">>" or "Next »"
  // If it's there find the id of the last post on the page

  if ((document.evaluate("//div[@id='paginator']/div[@class='pagination']/a[text()='>>']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue)
      || (document.evaluate("//div[@id='paginator']/a[text()='Next »']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue)) {
      before_id = Number(document.evaluate("//span[@class='thumb'][last()]", document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue.id.replace(/^p/,""));
  }

  testScrollPosition();
}

function testScrollPosition() {
  if ((!pending) && ((window.innerHeight + window.scrollMaxY) - window.pageYOffset < 3.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) + "&" : "") + "before_id=" + before_id + "&login=" + danbooruLogin + "&password_hash=" + danbooruPasswordHash,
    onload: function(responseDetails) {
      var result = eval("(" + responseDetails.responseText+ ")");

      if (result["success"]==false) {
        console.debug(result["reason"]);
        return;
      }

      // if a query returns 0 results we leave pending set to true, to stop any more requests going to the server.
      if (result.length > 0) {
        pending = false;
        page_count += 1;
      }

      for ( var i = 0; i<result.length; ++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);

          // before_id will be the id of the last thumb added to the page.
          before_id = result[i]["id"];

          // add details to existing danbooru data structures and rerun blacklist
          unsafeWindow.Post.register( result[i] );
        }
      }
      // apply blacklists
      unsafeWindow.Post.apply_blacklists();

      // add a HR and page number every 200 thumbs (10 pages)
      if ((page_count % 10) == 0) {
        console.log("hr");
        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) + "&" : "") + "before_id=" + before_id;
        a2Tag.textContent = "Page " + String(page_count);

        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;
}