Everlasting Juick

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

  1. // ==UserScript==
  2. // @name Everlasting Juick
  3. // @namespace http://dluciv.name/
  4. // @description Everlasting Juick scrolling / Бесконечный скроллинг Жуйка
  5. // @author dluciv
  6. // @copyright 2014+, Dmitry V. Luciv
  7. // @license WTFPLv2; http://wtfpl.net
  8. // @license MIT; http://opensource.org/licenses/MIT
  9. // @version 0.0.3.7
  10. // @icon https://raw.githubusercontent.com/dluciv/UserScripts/master/juick.com/everlasting-juick.png
  11. // @homepage https://github.com/dluciv/UserScripts/tree/master/juick.com
  12. //
  13. // @grant GM_info
  14. //
  15. // @require http://code.jquery.com/jquery-2.1.1.min.js
  16. // @include http://juick.com/*
  17.  
  18. // ==/UserScript==
  19. // Generated by CoffeeScript 1.9.0
  20.  
  21. /*
  22. * For some legal issues, this source code is licensed dually:
  23. * 1. under WTFPLv2 license (http://wtfpl.net)
  24. * 2. under MIT license (http://opensource.org/licenses/MIT) / Copyright (c) 2014, Dmitry V. Luciv /
  25. */
  26.  
  27.  
  28. /*
  29. * unsafeWindow goes away
  30. */
  31.  
  32. (function() {
  33. window.addEventListener('load', function() {
  34. var addClickHandlers, bodyborder, bottomScrollArea, contentborder, doNotLoadNext, e, hash, initialbefore, loadNextPage, locWithoutHash, locWithoutHashSearch, newer_page, prevpage, scrollto, scrolly, search;
  35. bottomScrollArea = 350;
  36. doNotLoadNext = false;
  37. locWithoutHashSearch = function(loc) {
  38. return loc.protocol + '//' + loc.hostname + (loc.port ? ":" + loc.port : "") + loc.pathname;
  39. };
  40. locWithoutHash = function(loc) {
  41. return loc.protocol + '//' + loc.hostname + (loc.port ? ":" + loc.port : "") + loc.pathname + (loc.search || "");
  42. };
  43. addClickHandlers = function(selector) {
  44. return selector.click(function(e) {
  45. var elt, loadedfrom, msg, msgy, pageid, query, where2return;
  46. elt = $(e.target);
  47. msg = elt.closest('article');
  48. pageid = msg.closest('div.everlasting-div').attr('id');
  49. query = '';
  50. loadedfrom = pageid.match(/loaded_from_(\d+)/);
  51. if (loadedfrom && +loadedfrom[1]) {
  52. query = '?before=' + loadedfrom[1];
  53. }
  54. msgy = msg.offset().top - $(window).scrollTop();
  55. where2return = locWithoutHashSearch(window.location) + query + "#" + msg.attr('data-mid') + '@' + msgy;
  56. window.history.replaceState({}, window.title, where2return);
  57. return console.log("Will return to " + where2return);
  58. });
  59. };
  60. prevpage = '';
  61. loadNextPage = function() {
  62. var oldprevpage, prevpagenum;
  63. doNotLoadNext = true;
  64. oldprevpage = prevpage;
  65. prevpage = $('p.page:last a').attr('href');
  66. $('p.page:last').remove();
  67. if (prevpage) {
  68. prevpagenum = prevpage.match(/.*\?before=(\d+).*/)[1];
  69. console.log("Loading new page: " + prevpage + " (# " + prevpagenum + ")...");
  70.  
  71. /*
  72. * $.ajax then parse HTML fails for Juick, so playing dirty.
  73. * Seems like browser sets innerHTML and then repairs markup,
  74. * so below approach works.
  75. */
  76. $('body > section#content > div.everlasting-div:last').after("<div class=\"everlasting-div\" id=\"loaded_from_" + prevpagenum + "\"></div>");
  77. return $("div#loaded_from_" + prevpagenum).load(prevpage + ' #content', function(data, status, req) {
  78. var newer_pages;
  79. console.log("Status: " + status);
  80. if (status === 'success') {
  81. $("div#loaded_from_" + prevpagenum + " article.ads").remove();
  82. $("div#loaded_from_" + prevpagenum + " div[id^=\"yandex_ad_\"]").remove();
  83. $("div#loaded_from_" + prevpagenum + " form").remove();
  84. $("div#loaded_from_" + prevpagenum + " article").unwrap();
  85. addClickHandlers($("div#loaded_from_" + prevpagenum + " > article a"));
  86. newer_pages = JSON.parse(sessionStorage["newer_pages"] || "{}");
  87. newer_pages[prevpagenum] = oldprevpage;
  88. sessionStorage["newer_pages"] = JSON.stringify(newer_pages);
  89. return setTimeout(function() {
  90. return doNotLoadNext = false;
  91. }, 500);
  92. }
  93. });
  94. } else {
  95. return console.log("Likely reached the very bottom!..");
  96. }
  97. };
  98. if (!window.location.pathname.match(/[a-zA-Z0-9]+\/[0-9]+/)) {
  99. $('html body div#footer').css({
  100. position: "fixed",
  101. bottom: "5px",
  102. 'background-color': "#f7f7f7",
  103. opacity: "0.8",
  104. padding: "5px",
  105. 'border-radius': "5px"
  106. });
  107. $('section#content').after('<div style="height: 40px;"/>');
  108. }
  109. $('article.ads, div#footer-left, div[id^="yandex_ad_"]').remove();
  110. bodyborder = 50;
  111. contentborder = 296;
  112. $('body, body > header, body > div#footer').css('width', "calc(100% - " + bodyborder + "px)");
  113. $('body > section#content').css('width', "calc(100% - " + (bodyborder + contentborder) + "px)");
  114. initialbefore = window.location.search.match(/\?before=(\d+).*/);
  115. initialbefore = initialbefore && initialbefore[1] || "0";
  116. console.log("Initial before = " + initialbefore);
  117. $('body section#content > article').wrapAll("<div class=\"everlasting-div\" id=\"loaded_from_" + initialbefore + "\"></div>");
  118. hash = window.location.hash.match(/(\d+)@(\d+)/);
  119. if (hash) {
  120. scrollto = hash[1];
  121. scrolly = hash[2];
  122. $(window).scrollTop($("article[data-mid=\"" + scrollto + "\"]").offset().top - (+scrolly));
  123. }
  124. addClickHandlers($("div#loaded_from_" + initialbefore + " > article a"));
  125. if (search = window.location.search.match(/\?before=(\d+)/)) {
  126. if (newer_page = JSON.parse(sessionStorage["newer_pages"] || "{}")[search[1]]) {
  127. $("section#content").prepend("<p><a href=\"" + newer_page + "\">&lt;&lt; Newer</a></p>");
  128. }
  129. }
  130. $(window).scroll(function(evt) {
  131. if (!doNotLoadNext && $(window).innerHeight() + $(window).scrollTop() >= $("body").height() - bottomScrollArea) {
  132. return loadNextPage();
  133. }
  134. });
  135. try {
  136. console.log("Auto-update: " + GM_info.scriptWillUpdate);
  137. } catch (_error) {
  138. e = _error;
  139. console.log("GM_info trouble");
  140. }
  141. });
  142.  
  143. }).call(this);