Everlasting Juick

Everlasting Juick scrolling / Бесконечный скроллинг Жуйка

// ==UserScript==
// @name          Everlasting Juick
// @namespace     http://dluciv.name/
// @description   Everlasting Juick scrolling / Бесконечный скроллинг Жуйка
// @author        dluciv
// @copyright     2014+, Dmitry V. Luciv
// @license       WTFPLv2; http://wtfpl.net
// @license       MIT; http://opensource.org/licenses/MIT
// @version       0.0.3.7
// @icon          https://raw.githubusercontent.com/dluciv/UserScripts/master/juick.com/everlasting-juick.png
// @homepage      https://github.com/dluciv/UserScripts/tree/master/juick.com
//
// @grant         GM_info
//
// @require       http://code.jquery.com/jquery-2.1.1.min.js
// @include       http://juick.com/*

// ==/UserScript==
// Generated by CoffeeScript 1.9.0

/*
 * For some legal issues, this source code is licensed dually:
 * 1. under WTFPLv2 license (http://wtfpl.net)
 * 2. under MIT license (http://opensource.org/licenses/MIT) / Copyright (c) 2014, Dmitry V. Luciv /
 */


/*
 * unsafeWindow goes away
 */

(function() {
  window.addEventListener('load', function() {
    var addClickHandlers, bodyborder, bottomScrollArea, contentborder, doNotLoadNext, e, hash, initialbefore, loadNextPage, locWithoutHash, locWithoutHashSearch, newer_page, prevpage, scrollto, scrolly, search;
    bottomScrollArea = 350;
    doNotLoadNext = false;
    locWithoutHashSearch = function(loc) {
      return loc.protocol + '//' + loc.hostname + (loc.port ? ":" + loc.port : "") + loc.pathname;
    };
    locWithoutHash = function(loc) {
      return loc.protocol + '//' + loc.hostname + (loc.port ? ":" + loc.port : "") + loc.pathname + (loc.search || "");
    };
    addClickHandlers = function(selector) {
      return selector.click(function(e) {
        var elt, loadedfrom, msg, msgy, pageid, query, where2return;
        elt = $(e.target);
        msg = elt.closest('article');
        pageid = msg.closest('div.everlasting-div').attr('id');
        query = '';
        loadedfrom = pageid.match(/loaded_from_(\d+)/);
        if (loadedfrom && +loadedfrom[1]) {
          query = '?before=' + loadedfrom[1];
        }
        msgy = msg.offset().top - $(window).scrollTop();
        where2return = locWithoutHashSearch(window.location) + query + "#" + msg.attr('data-mid') + '@' + msgy;
        window.history.replaceState({}, window.title, where2return);
        return console.log("Will return to " + where2return);
      });
    };
    prevpage = '';
    loadNextPage = function() {
      var oldprevpage, prevpagenum;
      doNotLoadNext = true;
      oldprevpage = prevpage;
      prevpage = $('p.page:last a').attr('href');
      $('p.page:last').remove();
      if (prevpage) {
        prevpagenum = prevpage.match(/.*\?before=(\d+).*/)[1];
        console.log("Loading new page: " + prevpage + " (# " + prevpagenum + ")...");

        /*
         * $.ajax then parse HTML fails for Juick, so playing dirty.
         * Seems like browser sets innerHTML and then repairs markup,
         * so below approach works.
         */
        $('body > section#content > div.everlasting-div:last').after("<div class=\"everlasting-div\" id=\"loaded_from_" + prevpagenum + "\"></div>");
        return $("div#loaded_from_" + prevpagenum).load(prevpage + ' #content', function(data, status, req) {
          var newer_pages;
          console.log("Status: " + status);
          if (status === 'success') {
            $("div#loaded_from_" + prevpagenum + " article.ads").remove();
            $("div#loaded_from_" + prevpagenum + " div[id^=\"yandex_ad_\"]").remove();
            $("div#loaded_from_" + prevpagenum + " form").remove();
            $("div#loaded_from_" + prevpagenum + " article").unwrap();
            addClickHandlers($("div#loaded_from_" + prevpagenum + " > article a"));
            newer_pages = JSON.parse(sessionStorage["newer_pages"] || "{}");
            newer_pages[prevpagenum] = oldprevpage;
            sessionStorage["newer_pages"] = JSON.stringify(newer_pages);
            return setTimeout(function() {
              return doNotLoadNext = false;
            }, 500);
          }
        });
      } else {
        return console.log("Likely reached the very bottom!..");
      }
    };
    if (!window.location.pathname.match(/[a-zA-Z0-9]+\/[0-9]+/)) {
      $('html body div#footer').css({
        position: "fixed",
        bottom: "5px",
        'background-color': "#f7f7f7",
        opacity: "0.8",
        padding: "5px",
        'border-radius': "5px"
      });
      $('section#content').after('<div style="height: 40px;"/>');
    }
    $('article.ads, div#footer-left,  div[id^="yandex_ad_"]').remove();
    bodyborder = 50;
    contentborder = 296;
    $('body, body > header, body > div#footer').css('width', "calc(100% - " + bodyborder + "px)");
    $('body > section#content').css('width', "calc(100% - " + (bodyborder + contentborder) + "px)");
    initialbefore = window.location.search.match(/\?before=(\d+).*/);
    initialbefore = initialbefore && initialbefore[1] || "0";
    console.log("Initial before = " + initialbefore);
    $('body section#content > article').wrapAll("<div class=\"everlasting-div\" id=\"loaded_from_" + initialbefore + "\"></div>");
    hash = window.location.hash.match(/(\d+)@(\d+)/);
    if (hash) {
      scrollto = hash[1];
      scrolly = hash[2];
      $(window).scrollTop($("article[data-mid=\"" + scrollto + "\"]").offset().top - (+scrolly));
    }
    addClickHandlers($("div#loaded_from_" + initialbefore + " > article a"));
    if (search = window.location.search.match(/\?before=(\d+)/)) {
      if (newer_page = JSON.parse(sessionStorage["newer_pages"] || "{}")[search[1]]) {
        $("section#content").prepend("<p><a href=\"" + newer_page + "\">&lt;&lt; Newer</a></p>");
      }
    }
    $(window).scroll(function(evt) {
      if (!doNotLoadNext && $(window).innerHeight() + $(window).scrollTop() >= $("body").height() - bottomScrollArea) {
        return loadNextPage();
      }
    });
    try {
      console.log("Auto-update: " + GM_info.scriptWillUpdate);
    } catch (_error) {
      e = _error;
      console.log("GM_info trouble");
    }
  });

}).call(this);