Pixiv hover zoom

hover zoom for Pixiv

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

/* global window, document, jQuery */

// ==UserScript==
// @name         Pixiv hover zoom
// @namespace    https://github.com/rplus
// @version      1.1.2
// @description  hover zoom for Pixiv
// @author       Rplus
// @include      http://www.pixiv.net/*
// @grant        none
// ==/UserScript==

;(function(window, document, $) {
  'use strict';

  var phzw = $('#pixiv-hz-wrap');
  var phzwPos = [];
  var phzwPattern = /member_illust\.php\?mode=medium&illust_id=(\d+)/;
  var phzwAPI = '//www.pixiv.net/rpc/index.php?mode=get_illust_detail_by_ids&illust_ids=';
  var phzwAPICache = {};
  var imgSize = 'm'; // size: '240mw', m', 'big'
  var body = document.body;
  var isAutoLoadNextPage = true;
  var pager = {};

  var phzwToggle = function(_switch) {
    if (_switch) {
      phzw.css({
        'top': phzwPos[0],
        'left': phzwPos[1],
        'opacity': 1,
        'visibility': 'visible',
        'transform': 'translateX(' + phzwPos[2] + '%)'
      });
    } else {
      if ('0' !== phzw[0].style.opacity) {
        phzw.css({
          'visibility': 'hidden',
          'opacity': 0
        });
      }
    }
  };

  var getAllId = function() {
    var ids = [];

    $.each($('#wrapper').find('a'), function() {
      var _href = $(this).attr('href');
      var _match = _href && _href.match(phzwPattern);
      if (_match) {
        ids.push(_match.pop());
      }
    });

    return ids;
  };

  var pullIdsData = function(idsArr) {
    var deferred = $.Deferred();

    $.getJSON(phzwAPI + idsArr.join())
      .done(function(data) {

        if (!data.error) {
          for (var _item in data.body) {
            if (data.body.hasOwnProperty(_item)) {
              phzwAPICache[_item] = data.body[_item];
            }
          }
          deferred.resolve(); //update state
        } else {
          deferred.reject();
        }

      })
      .fail(function() {
        deferred.reject();
      });

    return deferred.promise();
  };

  var render = function(_id) {
    var data = phzwAPICache[_id];
    if (!data) { return; }

    if (_id !== phzw.data('id')) {
      var tpl = '<a href="/member_illust.php?mode=medium&illust_id=' + _id + '"><img src="' + data.url[imgSize] + '" title="' + data.illust_title + '"></a>';
      phzw.html(tpl);

      phzw.data('id', _id);
    }

    phzwToggle(true);
  };

  var updatePos = function(ele) {
    var eleRect = ele.getBoundingClientRect();
    phzwPos = [eleRect.top + body.scrollTop + eleRect.height, eleRect.left, -100 * eleRect.left / body.scrollWidth];
  };

  $(function() {

    // phzw init
    if (!phzw.length) {
      $(body).append('<div id="pixiv-hz-wrap" />');
      phzw = $('#pixiv-hz-wrap').css({
        'position': 'absolute',
        'visibility': 'hidden',
        'opacity': 0,
        'box-shadow': '0 0 0 3px #fff, 0 0 3px 3px',
        'transition': 'all .3s',
        'z-index': '1000'
      });

      phzw.on('mouseenter', function() {
        phzw.one('mouseleave', function() {
          phzwToggle(false);
        });
      });
    }

    // delay pre-load data in page
    setTimeout(function() {
      pullIdsData(getAllId());
    }, 1000);

    $('#wrapper').on('mouseenter.phzw', 'a', function(e) {
      var _match = $(this).attr('href').match(phzwPattern);

      if (!_match) { return; }

      var _id = _match.pop();

      e.stopPropagation();
      updatePos(this);

      if (phzwAPICache[_id]) {
        render(_id);
      } else {
        $.when(pullIdsData([_id]))
          .then(function() {
            render(_id);
          });
      }
    });

    $(document).on('click.phzw', function() {
      phzwToggle(false);
    });

    if (isAutoLoadNextPage) {
      pager.container = $('.pager-container').eq(0);

      if (!pager.container.length) { return; }

      pager.current = pager.container.find('li.current').text();
      pager.baseHref = pager.container.find('a')[0].href.replace(/&p=\d+/, '');
      pager.parent = $('._image-items').eq(0).parent();

      var autoLoadNextPage = function() {
        var nextPage = pager.current * 1 + 1;
        var nextPageHref = pager.baseHref + '&p=' + nextPage;
        var separator = '<hr style="border: 1px dashed #ccc" /><a href="' + nextPageHref + '">::: page: ' + nextPage + '</a>';

        if (nextPage > pager.max) {
          $(window).off('scroll.autoLoadNextPage');
          return;
        }

        // prepare a div container for ajax lond next-page content
        $('<div />').appendTo( pager.parent.append(separator) )
          .load(nextPageHref + ' ._image-items', function(_html) {
            pager.current = nextPage;
            pager.loading = false;

            // check for max page
            var nextPagerLists = _html.match(/pager-container.+?(<ul .+?<\/ul>)/).pop();
            pager.max = $(nextPagerLists).find('li').last().text() * 1;
          });
      };

      $(window).on('scroll.autoLoadNextPage', function() {
        if (!pager.loading && (pager.parent[0].getBoundingClientRect().bottom < document.documentElement.clientHeight * .3)) {
          pager.loading = true;
          autoLoadNextPage();
        }
      });
    }

    $('.link-item').eq(0).prepend('<button>-♥ preload all ♥-</button>').find('button').on('click', function(e) {
      e.preventDefault();

      $.when(pullIdsData(getAllId()))
        .then(function() {
          $.each(phzwAPICache, function(key, val) {
            // forcedly preload
            $('<img src="' + val.url[imgSize] + '">');
          });
        });

    });
  });

})(window, document, jQuery, undefined);