Danbooru hover preview

hover over pics to preview them à la 4chan X

目前为 2022-03-20 提交的版本,查看 最新版本

// ==UserScript==
// @name        Danbooru hover preview
// @namespace   makamys
// @description hover over pics to preview them à la 4chan X
// @match       *://*.donmai.us/*
// @version     5
// @grant       none
// @license     Unlicense
// ==/UserScript==

// from http://greasemonkey.win-start.de/patterns/add-css.html
function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}

addGlobalStyle(`
#ihover {
  position: fixed;
  max-height: 100%;
  z-index: 10000;
  pointer-events: none;
}
`);

function main(){
  let ihover = null;
  let urlCache = {};
  
  let debug = false;
  
  $("body").prepend(`
<div id="hoverUI"></div>
`);
  
  function installListener(thumbs){
    
    function getFirstExistingURL(elems){
      let good_url = null;

      for(url of elems){
        $.ajax({
          type: "HEAD",
          async: false,
          url: url,
        }).done(function(){
            good_url = url;
        });
        if(good_url != null) break;
      }

      return good_url;
    }

    thumbs.mouseenter(function(event){
      $("#hoverUI").append(`<img id="ihover"></img>`);
      ihover = $("#ihover");

      let article = $(this).closest("article");
      let id = article.attr("data-id");
      let elem = $(article).find(".post-preview-image")[0];

      let url = $(elem).attr("src");
      let lastSlash1 = url.lastIndexOf("/");
      let lastSlash2 = url.lastIndexOf("/", lastSlash1 - 1);
      let lastSlash3 = url.lastIndexOf("/", lastSlash2 - 1);
      let lastSlash4 = url.lastIndexOf("/", lastSlash3 - 1);

      urlSampleJPG = url.slice(0, lastSlash4) + "/sample/" + url.slice(lastSlash3 + 1, lastSlash1 + 1) + "sample-" + url.slice(lastSlash1 + 1);
      urlOriginalJPG = url.slice(0, lastSlash4) + "/original/" + url.slice(lastSlash3 + 1, lastSlash1 + 1) + "" + url.slice(lastSlash1 + 1);
      urlSamplePNG = urlSampleJPG.slice(0, -4) + ".png"
      urlOriginalPNG = urlOriginalJPG.slice(0, -4) + ".png"

      let useAPI = true; // guessing the preview image's URL is significantly faster on average than asking the API according to my testing, but it also causes bugs for some reason

      let previewURL = urlCache[id];

      if(!previewURL){
        let t0 = debug ? new Date() : null;
        if(!useAPI){
            previewURL = getFirstExistingURL([urlSampleJPG, urlOriginalJPG, urlOriginalPNG]);
        } else {
          $.ajax({
            dataType: "json",
            async: false,
            url: "https://danbooru.donmai.us/posts/" + id + ".json",
            success: function(data) {
              previewURL = data["large_file_url"];
            }
          });
        }
        if(debug){
          let t1 = new Date();
          console.log((t1-t0) + "ms (id: " + id + ", url:" + previewURL + ", urlSampleJPG: " + urlSampleJPG + " event: " + $(event.target).attr("src") + ")");
        }
        urlCache[id] = previewURL;
      }

      ihover.attr("src", previewURL);
    });

    thumbs.mouseleave(function(event){
      $("#hoverUI").empty();
    });
  }
  
  installListener($("article img"));
  
  new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      installListener($(mutation.addedNodes).filter("article").find("img"));
    });
  }).observe(document.querySelector('.posts-container'), {childList: true});
  
//TODO
//  thumbs.mousemove(function(event){
//    console.log(ihover.width());
//  
//    let x = event.pageX + (event.pageX > $(window).width() / 2 ? -0 : 0);
//  
//    ihover.css({left: x});
//  });
}

// Inject our main script (workaround for Greasemonkey not finding the page's jQuery instance otherwise)
var script = document.createElement('script');
script.type = "text/javascript";
script.textContent = '(' + main.toString() + ')();';
document.body.appendChild(script);