Better Google

Add 'quick search' input and 'go to top' button for Google. Also highlight search terms.

  1. // ==UserScript==
  2. // @name Better Google
  3. // @namespace feifeihang.info
  4. // @description Add 'quick search' input and 'go to top' button for Google. Also highlight search terms.
  5. // @include https://www.google.*
  6. // @include http://www.google.*
  7. // @version 5.1.3
  8. // @grant GM_registerMenuCommand
  9. // ==/UserScript==
  10. var shouldHighlight = true;
  11. var COLORS = [
  12. '#FFFF00',
  13. '#CCCCFF',
  14. '#00CCFF',
  15. '#33CCCC',
  16. '#FF8080',
  17. '#FFCC00',
  18. '#008000',
  19. '#FFFF99',
  20. '#808000',
  21. '#FFFFCC'
  22. ];
  23. // highlight search terms.
  24. var urlBuffer,
  25. resultBuffer;
  26. function highlight() {
  27. console.log('1');
  28. // first, find all 'em's.
  29. var ems = document.querySelectorAll('em');
  30. // if there is no 'em's, do nothing.
  31. if (ems.length === 0) {
  32. return false;
  33. }
  34. // convert ems into an array.
  35.  
  36. ems = Array.prototype.slice.apply(ems);
  37. var counter = 0;
  38. var styles = {
  39. };
  40. // iterate through all the keywords in search result,
  41. // and map the predefined color to them.
  42. ems.forEach(function (em) {
  43. var text = em.textContent.toUpperCase().trim();
  44. var bg = styles[text];
  45. if (!bg) {
  46. bg = styles[text] = COLORS[counter++];
  47. if (counter === COLORS.length) {
  48. counter = 0;
  49. }
  50. }
  51. em.style.background = bg;
  52. em.style.color = '#000';
  53. em.style.fontWeight = 'bold';
  54. });
  55. }
  56. function toggleHighlight() {
  57. if (!shouldHighlight) {
  58. shouldHighlight = true;
  59. highlight();
  60. }
  61. else {
  62. shouldHighlight = false;
  63. var ems = document.querySelectorAll('em');
  64. if (ems.length === 0) {
  65. return false;
  66. }
  67. ems = Array.prototype.slice.apply(ems);
  68. ems.map(function (em) {
  69. em.style.background = '#fff';
  70. });
  71. }
  72. }
  73. GM_registerMenuCommand('Toggle Highlight', toggleHighlight);
  74. setInterval(function () {
  75. // if it's not google's landing page.
  76. if (urlBuffer !== window.location.href &&
  77. !document.querySelector('#hplogo')) {
  78. var resultContainer = document.querySelector('#search');
  79. if (resultContainer && resultContainer.textContent !== resultBuffer) {
  80. // update buffer.
  81. resultBuffer = resultContainer.textContent;
  82. if (!shouldHighlight) {
  83. return;
  84. }
  85. // first, find all 'em's.
  86.  
  87. var ems = document.querySelectorAll('em');
  88. // if there is no 'em's, do nothing.
  89. if (ems.length === 0) {
  90. return false;
  91. }
  92. // convert ems into an array.
  93.  
  94. ems = Array.prototype.slice.apply(ems);
  95. var counter = 0;
  96. var styles = {
  97. };
  98. // iterate through all the keywords in search result,
  99. // and map the predefined color to them.
  100. ems.forEach(function (em) {
  101. var text = em.textContent.toUpperCase().trim();
  102. var bg = styles[text];
  103. if (!bg) {
  104. bg = styles[text] = COLORS[counter++];
  105. if (counter === COLORS.length) {
  106. counter = 0;
  107. }
  108. }
  109. em.style.background = bg;
  110. em.style.color = '#000';
  111. em.style.fontWeight = 'bold';
  112. });
  113. urlBuffer = window.location.href;
  114. }
  115. }
  116. }, 200);
  117. var container = document.createElement('div');
  118. container.style = 'display: none; position: fixed; bottom: 20px;' +
  119. 'right: 5px; text-align: right;' +
  120. 'width: 280px; height: 60px; z-index: 999999999;' +
  121. 'opacity: 0.8;';
  122. container.addEventListener('mouseenter', function () {
  123. this.style.opacity = '1';
  124. }, true);
  125. container.addEventListener('mouseout', function () {
  126. this.style.opacity = '0.8';
  127. }, true);
  128. // create quick query input.
  129. var input = document.createElement('input');
  130. input.tyle = 'text';
  131. input.value = document.querySelector('#lst-ib').value;
  132. input.setAttribute('placeholder', 'Search...');
  133. input.style = 'border: none; border-left: solid #EA4335 5px; flex: 1; display: inline-block; outline: none; height: 40px;' +
  134. 'font-size: 15px; margin-top: 10px; margin-bottom: 10px; padding: 0; ' +
  135. 'padding-left: 10px; padding-right: 10px; box-shadow: 0 1px 3px #999999;';
  136. container.appendChild(input);
  137. // bind keypress-enter event.
  138. input.addEventListener('keypress', function (evt) {
  139. if (evt.keyCode === 13) {
  140. var value = input.value.trim() || '';
  141. if (value !== '') {
  142. document.querySelector('#lst-ib').value = value;
  143. document.querySelector('.lsb').click();
  144. window.scrollTo(0, 0);
  145. document.querySelector('#lst-ib').focus();
  146. }
  147. }
  148. }, false);
  149. // create the goto-top button.
  150. var btn = document.createElement('div');
  151. btn.id = 'goto-top-btn';
  152. btn.innerHTML = 'TOP';
  153. btn.onclick = gotoTop;
  154. // set button CSS style.
  155. btn.style = 'display: inline-block; position: relative; left: -7px; color: #fff; line-height: 60px; text-align: center;' +
  156. 'width: 60px; height: 60px; background: #4285F4; box-shadow: 0 2px 3px #999999;' +
  157. 'cursor: pointer; font-weight: bolder; border-radius: 100%;';
  158. // append the go-to-top to search form to successfully attach to the UI.
  159. container.appendChild(btn);
  160. var form = document.querySelector('#searchform');
  161. form.appendChild(container);
  162. window.onload = function () {
  163. var doc = document.documentElement;
  164. var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  165. if (top !== 0) {
  166. container.style.display = 'flex';
  167. }
  168. }
  169. // bind button hiden/show event.
  170.  
  171. window.onscroll = function () {
  172. var doc = document.documentElement;
  173. var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  174. if (top === 0) {
  175. container.style.display = 'none';
  176. } else {
  177. container.style.display = 'flex';
  178. }
  179. }
  180. function gotoTop() {
  181. goto(Math.floor(window.pageYOffset / 5));
  182. }
  183. function goto(step) {
  184. setTimeout(function () {
  185. window.scrollTo(0, window.pageYOffset - step);
  186. if (window.pageYOffset <= 0) return;
  187. goto(step);
  188. }, 100);
  189. }