Endless Google

Load more results automatically and endlessly.

目前为 2018-04-27 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Endless Google
  3. // @description Load more results automatically and endlessly.
  4. // @author tumpio
  5. // @oujs:author tumpio
  6. // @license MIT
  7. // @namespace tumpio@sci.fi
  8. // @homepageURL https://openuserjs.org/scripts/tumpio/tumpiosci.fi/Endless_Google
  9. // @supportURL https://github.com/tumpio/gmscripts
  10. // @icon https://github.com/tumpio/gmscripts/raw/master/Endless_Google/large.png
  11. // @include http://www.google.*
  12. // @include https://www.google.*
  13. // @include https://encrypted.google.*
  14. // @run-at document-start
  15. // @grant GM_xmlhttpRequest
  16. // @grant GM_addStyle
  17. // @version 0.0.4-joey3
  18. // ==/UserScript==
  19.  
  20. // TODO: on page refresh:
  21. // 2: load only the last scrolled page (on refresh, load last requested page) (could be a good default, needs scroll up support)
  22. // beforeunload -> store last requested page with GM_setVariable() and reload it instead
  23. // TODO: onerror, onabort: show to user "page loading failed", button to retry
  24.  
  25. // FIXME: bug: Suggested images don't show up on new requested pages
  26. // case: https://www.google.fi/webhp?tab=ww&ei=e0UjU9ynEKqkyAO46YD4DQ&ved=0CBEQ1S4#q=tetsaus
  27. // workaround, hiding now
  28.  
  29. // FUTURE: Options dialog
  30. // FUTURE: Replace footer with page #no info UI
  31. // FUTURE: Add page up/down and back to top/bottom controls UI + (go to the page #n)?
  32. // FUTURE: Add columns support
  33. // FUTURE: show page loading icon
  34. // FUTURE: show page fav-icons for results
  35. // FUTURE: number results
  36. // FUTURE: option to load static google css
  37. // FUTURE: support scroll up
  38.  
  39. if (location.href.indexOf("tbm=isch") !== -1) // NOTE: Don't run on image search
  40. return;
  41. if (window.top !== window.self) // NOTE: Do not run on iframes
  42. return;
  43.  
  44. document.addEventListener('DOMContentLoaded', function () {
  45.  
  46. // NOTE: Options
  47. var request_pct = 1.50; // percentage of window height left on document to request next page, value must be between 0-1
  48. var event_type = "scroll"; // or "wheel"
  49. var on_page_refresh = 1;
  50. // 0: reload all previous pages requested
  51. // 1: load only the first page (prevent restoring the scroll position)
  52. // 2: load only the last page requested
  53. var main = document.getElementById("main");
  54. var rcnt = document.getElementById("rcnt");
  55. var input = document.getElementById("lst-ib");
  56. var input_value = input.value;
  57. var old_scrollY = 0;
  58. var scroll_events = 0;
  59. var next_link = null;
  60. var cols = [];
  61. var request_offsetHeight = 0;
  62. var stop_events = false;
  63.  
  64. input.addEventListener("blur", reset, false); // NOTE: listens for new search input to reset state
  65. window.addEventListener(event_type, onScroll, false);
  66.  
  67. // Disabled by Joey because it is mildly annoying when clicking a link, and I'm not sure what its benefit is
  68. //window.addEventListener("beforeunload", function () {
  69. // window.scrollTo(0, 0);
  70. //}, false);
  71.  
  72. function requestNextPage(link) {
  73. console.log("request next");
  74. console.log(link);
  75. GM_xmlhttpRequest({
  76. method: "GET",
  77. url: link,
  78. onload: function (response) {
  79. var el = document.getElementById('navcnt');
  80. el.parentNode.removeChild(el); //Deletes the navigation box
  81. var holder = document.createElement("div");
  82. holder.innerHTML = response.responseText;
  83. next_link = holder.querySelector("#pnnext").href;
  84.  
  85. var next_col = document.createElement("div");
  86. next_col.className = "EG_col";
  87. next_col.appendChild(holder.querySelector("#center_col"));
  88.  
  89. var rel_search = next_col.querySelector("#extrares");
  90. var rel_images = next_col.querySelector("#imagebox_bigimages");
  91. var rel_ads = next_col.querySelector("#tads");
  92. if (rel_search)
  93. rel_search.style.display = "none"; // NOTE: Hides repeating "related searches"
  94. if (rel_images)
  95. rel_images.style.display = "none"; // NOTE: Hides related images, that are broken (bug)
  96. if (rel_ads)
  97. rel_ads.style.display = "none"; // NOTE: Hides repeating "search results ad"
  98.  
  99. cols.push(next_col);
  100. console.log("Page no: " + cols.length);
  101. next_col.id = next_col.className + "_" + (cols.length - 1); // NOTE: add unique id for every new col
  102.  
  103. if (!rcnt || cols.length === 1) // NOTE: needs to be rechecked on a state reset too, and late insertation of element on google instant
  104. rcnt = document.getElementById("rcnt");
  105. rcnt.appendChild(next_col);
  106. stop_events = false;
  107. window.addEventListener(event_type, onScroll, false);
  108. }
  109. });
  110.  
  111. }
  112.  
  113. function onScroll(e) {
  114. var y = window.scrollY;
  115. // if (scroll_events === 0) old_scrollY = y; // stops only if scroll position was on 2. page
  116. var delta = e.deltaY || y - old_scrollY; // NOTE: e.deltaY for "wheel" event
  117. if (delta > 0 && (window.innerHeight + y) >= (document.body.clientHeight - (window.innerHeight * request_pct))) {
  118. console.log("scroll end");
  119. window.removeEventListener(event_type, onScroll, false);
  120.  
  121. try {
  122. if(!stop_events){
  123. stop_events = true;
  124. requestNextPage(next_link || document.getElementById("pnnext").href);
  125. }
  126. } catch (err) {
  127. console.error(err.name + ": " + err.message);
  128. // NOTE: recovery unnecessary, input event handles it with reset on new search
  129. }
  130. }
  131. old_scrollY = y;
  132. scroll_events += 1;
  133. }
  134.  
  135. // NOTE: Resets the script state on a new search
  136. function reset() {
  137. if (input.value !== input_value) {
  138. input_value = input.value;
  139. window.scrollTo(0, 0);
  140. for (var i = 0; i < cols.length; i++)
  141. rcnt.removeChild(cols[i]);
  142. cols = [];
  143. next_link = null;
  144. old_scrollY = 0;
  145. scroll_events = 0;
  146. console.log("RESET");
  147. }
  148. }
  149.  
  150. console.log("egoogle.js initialized");
  151. });
  152. console.log("egoogle.js loaded");
  153.  
  154. // The related searches are a bit jarring because they mix in with the search results.
  155. // So we give them a light grey background, so are visually distinguishable
  156. GM_addStyle("#extrares { border: 1px solid #ececec; border-radius: 5px; background: #fafafa; margin-bottom: 24px; });
  157. // Lets also reduce the rather large top and bottom padding on this box
  158. GM_addStyle("#brs { margin-bottom: 20px }");
  159. GM_addStyle("#brs > * { margin-top: 26px }");