Keyboard navigator

Keyboard navigation

目前為 2019-01-21 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Keyboard navigator
  3. // @version 1.0
  4. // @description Keyboard navigation
  5. // @author badook
  6. // @include http*://*
  7. // @grant GM_openInTab
  8. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js
  9. // @namespace https://greasyfork.org/users/240988
  10. // ==/UserScript==
  11.  
  12. 'use strict';
  13.  
  14. var jq = $.noConflict();
  15.  
  16. var bgcolor = "#EBF2FF";
  17.  
  18. var util = {
  19. q: function(query, context) {
  20. return (context || document).querySelector(query);
  21. },
  22. qq: function(query, context) {
  23. return [].slice.call((context || document).querySelectorAll(query));
  24. }
  25. };
  26.  
  27. var i = 0;
  28.  
  29.  
  30. var isGoogleSearch = /^(http|https):\/\/(www.)?google.(com|co.uk|it)\/search\?/.test(location.href);
  31. var isPageScrollEnabled = true;
  32.  
  33.  
  34. if ( isGoogleSearch ) {
  35. var searchBox = jq('input[name="q"]').first();
  36. //var searchBox = document.getElementById("lst-ib");
  37. var prevPage = document.getElementById("pnprev");
  38. var nextPage = document.getElementById("pnnext");
  39. var results = util.qq('div.g', document.body);
  40.  
  41. results[i].style.backgroundColor = bgcolor;
  42.  
  43. jq(results).click(function() {
  44. results[i].style.backgroundColor = "transparent";
  45. i = results.indexOf(jq(this).get(0));
  46. jq(this).get(0).style.backgroundColor = bgcolor;
  47. });
  48. }
  49.  
  50.  
  51. document.onkeypress = function(e) {
  52. console.log(e.keyCode);
  53.  
  54. if ( !shouldScroll(e) ) {
  55. return;
  56. }
  57.  
  58. switch(e.keyCode) {
  59. case 97: // a
  60. setTimeout(function(){ // Dont put current letter in input
  61. searchBox.focus();
  62. searchBox.value = searchBox.value; // Cursor to end
  63. }, 0);
  64. return;
  65. case 13: // enter
  66. case 100: // d
  67. var url = jq('a',jq(results[i])).attr('href');
  68. console.log(url);
  69. GM_openInTab(url, true);
  70. return;
  71. case 68: // D
  72. GM_openInTab(util.q('a', results[i]).href, false);
  73. return;
  74. case 113: // q
  75. prevPage.click();
  76. return;
  77. case 101: // e
  78. nextPage.click();
  79. return;
  80. case 87: // W
  81. // if (isPageScrollEnabled)
  82. window.scrollBy(0, -100);
  83. return;
  84. case 83: // S
  85. // if (isPageScrollEnabled)
  86. console.log("scroll")
  87. window.scrollBy(0, 100);
  88. return;
  89. case 119: // w
  90. if(i > 0)
  91. results[i--].style.backgroundColor = "transparent";
  92. break;
  93. case 115: // s
  94. if(i < results.length - 1)
  95. results[i++].style.backgroundColor = "transparent";
  96. break;
  97. default:
  98. return;
  99. }
  100. results[i].style.backgroundColor = bgcolor;
  101. scrollToElement(results[i]);
  102. };
  103.  
  104.  
  105. function scrollToElement(el) {
  106. var elOffset = jq(el).offset().top;
  107. var elHeight = jq(el).height();
  108. var windowHeight = jq(window).height();
  109. var offset;
  110. if (elHeight < windowHeight)
  111. offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
  112. else
  113. offset = elOffset;
  114. jq('html, body').animate({scrollTop:offset}, 0);
  115. }
  116.  
  117.  
  118. function shouldScroll(event, direction) {
  119. if (event.target.isContentEditable) {
  120. return false;
  121. }
  122. if (event.target.type === 'application/x-shockwave-flash') {
  123. return false;
  124. }
  125. if (event.defaultPrevented) {
  126. return false;
  127. }
  128. if (/button|input|textarea|select|embed|object/i.test(event.target.nodeName)) {
  129. return false;
  130. }
  131. if (event.metaKey === true) {
  132. return false;
  133. }
  134. if (!document.hasFocus()) {
  135. return false;
  136. }
  137. if (document.domain === 'mail.google.com') {
  138. if (window.location.hash.indexOf('/') === -1) {
  139. return false;
  140. } else if (!(event.keyCode in keyMaps.arrows)) {
  141. return false;
  142. }
  143. }
  144. if (!window.scrollTargetY) {
  145. findScrollTargets(event, 'y');
  146. if (!window.scrollTargetY) {
  147. return false;
  148. }
  149. }
  150. if (!scrollable(window.scrollTargetY, 'y')) {
  151. return false;
  152. }
  153. return true;
  154. };
  155.  
  156.  
  157. findScrollTargets = function(event, axis) {
  158. var scrollableParentX, scrollableParentY, target;
  159. if (event == null) {
  160. event = null;
  161. }
  162. if (axis == null) {
  163. axis = 'both';
  164. }
  165. if (!event || document.activeElement === !document.body) {
  166. target = document.activeElement;
  167. } else {
  168. target = event.target || event.srcElement;
  169. target = target.nodeType === 1 ? target : target.parentNode;
  170. }
  171. if (axis === 'y' || axis === 'both') {
  172. scrollableParentY = findScrollableParent(target, 'y');
  173. if (scrollableParentY) {
  174. window.scrollTargetY = scrollableParentY;
  175. }
  176. }
  177. if (axis === 'x' || axis === 'both') {
  178. scrollableParentX = findScrollableParent(target, 'x');
  179. if (scrollableParentX) {
  180. return window.scrollTargetX = scrollableParentX;
  181. }
  182. }
  183. };
  184.  
  185.  
  186. findScrollableParent = function(element, axis) {
  187. while (true) {
  188. if (scrollable(element, axis)) {
  189. return element;
  190. } else {
  191. element = element.parentElement;
  192. }
  193. }
  194. };
  195.  
  196.  
  197. scrollable = function(element, axis) {
  198. var initialPosition, scrollAxis, scrollVariation;
  199. scrollAxis = axis === 'y' ? 'scrollTop' : 'scrollLeft';
  200. if (!element) {
  201. return true;
  202. } else if (/button|input|textarea|select|embed|object/i.test(element.nodeName)) {
  203. return false;
  204. } else if (element[scrollAxis] > 10) {
  205. return true;
  206. } else {
  207. initialPosition = element[scrollAxis];
  208. element[scrollAxis] = 10;
  209. scrollVariation = element[scrollAxis];
  210. element[scrollAxis] = initialPosition;
  211. if (scrollVariation >= 10) {
  212. return true;
  213. }
  214. }
  215. return false;
  216. };