More Keybinds

Adds some extra keystrokes to Firefox.

目前为 2020-04-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name More Keybinds
  3. // @namespace MK
  4. // @description Adds some extra keystrokes to Firefox.
  5. // @version 1.2.4
  6. // @include *
  7. // @run-at document-start
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. // jQuery might be present
  12. /* eslint-env jquery */
  13.  
  14. // Not all keys fire a keypress event (Chrome 2010), so we use keydown.
  15. document.addEventListener('keydown', keypressListener, false);
  16.  
  17. function keypressListener(evt) {
  18. var code = evt.keyCode || evt.which;
  19.  
  20. /*
  21. var modifierReport = "";
  22. modifierReport += ( evt.ctrlKey ? "Ctrl " : "" );
  23. modifierReport += ( evt.shiftKey ? "Shift " : "" );
  24. modifierReport += ( evt.altKey ? "Alt " : "" );
  25. GM_log("Caught keypress "+code+" with modifiers: "+modifierReport);
  26. */
  27.  
  28. // Do not intercept any of the keys below when the user is focused on an input or textarea.
  29. /*
  30. //var focusedElement = document.activeElement; // document.body if no input is focused
  31. var focusedElement = evt.target || event.srcElement;
  32. if (focusedElement) {
  33. var isInput = focusedElement.nodeName === 'INPUT' || focusedElement.nodeName === 'TEXTAREA';
  34. if (isInput) {
  35. return;
  36. }
  37. }
  38. */
  39. // From next_imageprevious_image.user.js:
  40. if (evt.target.tagName && evt.target.tagName.match(/input|select|textarea/i) || evt.target.getAttribute('contenteditable')==="true") {
  41. return;
  42. }
  43.  
  44. // Actions
  45.  
  46. // Ctrl+Backspace goes Back
  47. if (code == 8 && evt.ctrlKey) {
  48. window.history.back();
  49. }
  50.  
  51. // The Delete key, because sometimes I map Ctrl+Backspace to emit a Delete
  52. if (code == 46) {
  53. window.history.back();
  54. }
  55.  
  56. // Ctrl+Enter goes Forward
  57. if (code == 13 && evt.ctrlKey) {
  58. window.history.forward();
  59. }
  60.  
  61. /* These conflict with selecting words in text!
  62.  
  63. // Ctrl+Shift+Left goes Back
  64. if (code == 37 && evt.ctrlKey && evt.shiftKey) {
  65. window.history.back();
  66. }
  67.  
  68. // Ctrl+Shift+Right goes Forward
  69. if (code == 39 && evt.ctrlKey && evt.shiftKey) {
  70. window.history.forward();
  71. }
  72.  
  73. */
  74.  
  75. // Ctrl+Shift+Up goes up in the URL path (removes the tail leaf)
  76. // Cmd+Alt+Up on macOS also works
  77. if ((code == 38 && evt.ctrlKey && evt.shiftKey) || (evt.code == 'ArrowUp' && evt.altKey && evt.metaKey)) {
  78. var newURL = document.location.href;
  79. if (newURL.slice(-1)=='/') {
  80. newURL = newURL.slice(0,-1);
  81. }
  82. document.location.href = document.location.href.replace(/[#/?][^#/?]*[/]*$/,'');
  83. }
  84.  
  85. if (!evt.ctrlKey && !evt.shiftKey && !evt.metaKey) {
  86. if (document.location.host !== "9gag.com" /* && document.location.host !== "github.com" */) {
  87. if (code === 'K'.charCodeAt(0)) {
  88. bestScrollBy(-getScrollAmount());
  89. }
  90.  
  91. if (code === 'J'.charCodeAt(0)) {
  92. bestScrollBy(+getScrollAmount());
  93. }
  94. }
  95. }
  96.  
  97. }
  98.  
  99. // Try to perform a smooth vertical scroll, but fall back to a jump scroll if neccessary
  100. function bestScrollBy(amount) {
  101. if (typeof window.scrollBy === 'function') {
  102. // If browser has native scrollBy, use that
  103. window.scrollBy({
  104. left: 0,
  105. top: amount,
  106. behavior: 'smooth'
  107. });
  108. } else if (typeof $ !== "undefined" && $.fn && $.fn.animate) {
  109. // Otherwise, if jQuery is present, use that
  110. queue(function(next){
  111. $("html,body").animate({scrollTop: $(document).scrollTop() + amount}, 200, "swing", ifBody(next));
  112. });
  113. } else {
  114. // Otherwise perform a jerky scroll
  115. // Does not do anything in Chrome:
  116. document.body.scrollTop += amount;
  117. // Works in Chrome/Firefox:
  118. document.documentElement.scrollTop += amount;
  119. }
  120. }
  121.  
  122. function getScrollAmount() {
  123. return window.innerHeight / 6;
  124. }
  125.  
  126. function ifBody(fn) {
  127. return function(){
  128. // jQuery calls complete once for each element, and we have two elements. Annoying!
  129. if (this === document.body) {
  130. fn();
  131. }
  132. };
  133. }
  134.  
  135. var actions = [];
  136. var running = false;
  137. function queue(action) {
  138. actions.push(action);
  139. if (!running) {
  140. dequeue();
  141. }
  142. }
  143. function dequeue() {
  144. if (actions.length > 0) {
  145. var nextAction = actions.shift();
  146. running = true;
  147. nextAction(dequeue);
  148. } else {
  149. running = false;
  150. }
  151. }