Ended Google

Load fewer results non-automatically and finitely ;) Very rough hack of "Endless Google" by tumpio (https://openuserjs.org/scripts/tumpio/Endless_Google) to BREAK continuous scrolling

  1. // ==UserScript==
  2. // @name Ended Google
  3. // @description Load fewer results non-automatically and finitely ;) Very rough hack of "Endless Google" by tumpio (https://openuserjs.org/scripts/tumpio/Endless_Google) to BREAK continuous scrolling
  4. // @author aHorseSplashes
  5. // @include http://www.google.*
  6. // @include https://www.google.*
  7. // @include https://encrypted.google.*
  8. // @run-at document-start
  9. // @version 0.0.1
  10. // @license MIT
  11. // @noframes
  12. // @namespace https://greasyfork.org/users/1035525
  13. // ==/UserScript==
  14.  
  15. /* Instructions/info:
  16. * The first "more results" page will automatically load as normal. This is so you can read search results near the bottom of the first page.
  17. * To escape continuous scrolling, QUICKLY scroll down to the bottom of the second page. It should reload to the paginated version.
  18. * I'm sure a lot of the original "Endless Google" script is no longer necessary, but eh, good enough.
  19. * Tested on Firefox and Chrome with a US IP address.
  20. * Probably not going to be maintained or updated. WYSIWYG
  21. */
  22.  
  23. if (location.href.indexOf("tbm=isch") !== -1) // NOTE: Don't run on image search
  24. return;
  25. if (window.top !== window.self) // NOTE: Do not run on iframes
  26. return;
  27.  
  28. const centerElement = "#center_col";
  29. const loadWindowSize = 1.6;
  30. const filtersAll = ["#foot", "#bottomads"];
  31. const filtersCol = filtersAll.concat(["#extrares", "#imagebox_bigimages"]);
  32. let msg = "";
  33.  
  34. const css = `
  35. .page-number {
  36. position: relative;
  37. display: flex;
  38. flex-direction: row-reverse;
  39. align-items: center;
  40. margin-bottom: 2em;
  41. color: #808080;
  42. }
  43. .page-number::before {
  44. content: "";
  45. background-color: #ededed;
  46. height: 1px;
  47. width: 100%;
  48. margin: 1em 3em;
  49. }
  50. .endless-msg {
  51. position:fixed;
  52. bottom:0;
  53. left:0;
  54. padding:5px 10px;
  55. background: darkred;
  56. color: white;
  57. font-size: 11px;
  58. display: none;
  59. }
  60. .endless-msg.shown {
  61. display:block;
  62. }
  63. `;
  64.  
  65. let pageNumber = 1;
  66. let prevScrollY = 0;
  67. let nextPageLoading = false;
  68.  
  69. function requestNextPage() {
  70. nextPageLoading = true;
  71. let nextPage = new URL(location.href);
  72. if (!nextPage.searchParams.has("q") || (nextPage.searchParams.has("start") && !nextPage.searchParams.has("start=0"))) return;
  73.  
  74. nextPage.searchParams.set("start", 10);
  75. if(pageNumber > 1) window.location.assign(nextPage);
  76. !msg.classList.contains("shown") && msg.classList.add("shown");
  77. fetch(nextPage.href)
  78. .then(response => response.text())
  79. .then(text => {
  80. let parser = new DOMParser();
  81. let htmlDocument = parser.parseFromString(text, "text/html");
  82. let docElement = htmlDocument.documentElement;
  83. let content = docElement.querySelector(centerElement);
  84.  
  85. content.id = "col_" + 0;
  86. filter(content, filtersCol);
  87.  
  88. content.style.marginLeft = '0';
  89.  
  90. let pageMarker = document.createElement("div");
  91. pageMarker.textContent = String(pageNumber);
  92. pageMarker.className = "page-number";
  93.  
  94. let col = document.createElement("div");
  95. col.className = "next-col";
  96. col.appendChild(pageMarker);
  97.  
  98. // Set images source address
  99. try {
  100. let thumbnails = text.match(/google\.ldi=({.+?})/);
  101. let thumbnailsObj = JSON.parse(thumbnails && thumbnails[1]);
  102. for (let id in thumbnailsObj) {
  103. docElement.querySelector("#"+id).src = unescapeHex(thumbnailsObj[id]);
  104. }
  105. } catch(e) {}
  106.  
  107. function setImagesSrc({id}) {
  108. let pattern = new RegExp("var\\ss='(\\S+)';var\\sii=\\[[a-z0-9_',]*?'"+id+"'[a-z0-9_',]*?\\];");
  109. let imageSource = text.match(pattern);
  110. if (imageSource != null && imageSource[1]) {
  111. docElement.querySelector("#"+id).src = unescapeHex(imageSource[1]);
  112. }
  113. }
  114. docElement.querySelectorAll('g-img > img[id]').forEach(setImagesSrc);
  115. docElement.querySelectorAll('div > img[id^=dimg_]').forEach(setImagesSrc);
  116.  
  117. docElement.querySelectorAll('img[data-src]').forEach((img) => {
  118. img.src = img.dataset.src;
  119. img.style.visibility = 'visible';
  120. });
  121.  
  122. col.appendChild(content);
  123. document.querySelector(centerElement).appendChild(col);
  124.  
  125. if (!content.querySelector("#rso")) {
  126. // end of results
  127. window.removeEventListener("scroll", onScrollDocumentEnd);
  128. nextPageLoading = false;
  129. msg.classList.contains("shown") && msg.classList.remove("shown");
  130. return;
  131. }
  132.  
  133. if (pageNumber = 1) pageNumber++;
  134. nextPageLoading = false;
  135. msg.classList.contains("shown") && msg.classList.remove("shown");
  136. });
  137. }
  138.  
  139. function unescapeHex(hex) {
  140. if (typeof hex != "string") { return ""; }
  141. return hex.replace(/\\x([0-9a-f]{2})/ig, function(_, chunk) {
  142. return String.fromCharCode(parseInt(chunk, 16));
  143. });
  144. }
  145.  
  146. function onScrollDocumentEnd() {
  147. let y = window.scrollY;
  148. let delta = y - prevScrollY;
  149. if (!nextPageLoading && delta > 0 && isDocumentEnd(y)) {
  150. requestNextPage();
  151. }
  152. prevScrollY = y;
  153. }
  154.  
  155. function isDocumentEnd(y) {
  156. return y + window.innerHeight * loadWindowSize >= document.body.clientHeight;
  157. }
  158.  
  159. function filter(node, filters) {
  160. for (let filter of filters) {
  161. let child = node.querySelector(filter);
  162. if (child) {
  163. child.parentNode.removeChild(child);
  164. }
  165. }
  166. }
  167.  
  168. function init() {
  169. prevScrollY = window.scrollY;
  170. window.addEventListener("scroll", onScrollDocumentEnd);
  171. filter(document, filtersAll);
  172. let style = document.createElement("style");
  173. style.type = "text/css";
  174. style.appendChild(document.createTextNode(css));
  175. document.head.appendChild(style);
  176. msg = document.createElement("div");
  177. msg.setAttribute("class", "endless-msg");
  178. msg.innerText = "Loading next page...";
  179. document.body.appendChild(msg);
  180. }
  181.  
  182. document.addEventListener("DOMContentLoaded", init);