shortcuts.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Sanity-check the conversion and remove this comment.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS102: Remove unnecessary code created because of implicit returns
  6. * DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining
  7. * DS205: Consider reworking code to avoid use of IIFEs
  8. * DS206: Consider reworking classes to avoid initClass
  9. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  10. */
  11. const Cls = (app.Shortcuts = class Shortcuts {
  12. static initClass() {
  13. $.extend(this.prototype, Events);
  14. }
  15. constructor() {
  16. this.onKeydown = this.onKeydown.bind(this);
  17. this.onKeypress = this.onKeypress.bind(this);
  18. this.isMac = $.isMac();
  19. this.start();
  20. }
  21. start() {
  22. $.on(document, 'keydown', this.onKeydown);
  23. $.on(document, 'keypress', this.onKeypress);
  24. }
  25. stop() {
  26. $.off(document, 'keydown', this.onKeydown);
  27. $.off(document, 'keypress', this.onKeypress);
  28. }
  29. swapArrowKeysBehavior() {
  30. return app.settings.get('arrowScroll');
  31. }
  32. spaceScroll() {
  33. return app.settings.get('spaceScroll');
  34. }
  35. showTip() {
  36. app.showTip('KeyNav');
  37. return this.showTip = null;
  38. }
  39. spaceTimeout() {
  40. return app.settings.get('spaceTimeout');
  41. }
  42. onKeydown(event) {
  43. if (this.buggyEvent(event)) { return; }
  44. const result = (() => {
  45. if (event.ctrlKey || event.metaKey) {
  46. if (!event.altKey && !event.shiftKey) { return this.handleKeydownSuperEvent(event); }
  47. } else if (event.shiftKey) {
  48. if (!event.altKey) { return this.handleKeydownShiftEvent(event); }
  49. } else if (event.altKey) {
  50. return this.handleKeydownAltEvent(event);
  51. } else {
  52. return this.handleKeydownEvent(event);
  53. }
  54. })();
  55. if (result === false) { event.preventDefault(); }
  56. }
  57. onKeypress(event) {
  58. if (this.buggyEvent(event) || ((event.charCode === 63) && (document.activeElement.tagName === 'INPUT'))) { return; }
  59. if (!event.ctrlKey && !event.metaKey) {
  60. const result = this.handleKeypressEvent(event);
  61. if (result === false) { event.preventDefault(); }
  62. }
  63. }
  64. handleKeydownEvent(event, _force) {
  65. if (!_force && [37, 38, 39, 40].includes(event.which) && this.swapArrowKeysBehavior()) { return this.handleKeydownAltEvent(event, true); }
  66. if (!event.target.form && ((48 <= event.which && event.which <= 57) || (65 <= event.which && event.which <= 90))) {
  67. this.trigger('typing');
  68. return;
  69. }
  70. switch (event.which) {
  71. case 8:
  72. if (!event.target.form) { return this.trigger('typing'); }
  73. break;
  74. case 13:
  75. return this.trigger('enter');
  76. case 27:
  77. this.trigger('escape');
  78. return false;
  79. case 32:
  80. if ((event.target.type === 'search') && this.spaceScroll() && (!this.lastKeypress || (this.lastKeypress < (Date.now() - (this.spaceTimeout() * 1000))))) {
  81. this.trigger('pageDown');
  82. return false;
  83. }
  84. break;
  85. case 33:
  86. return this.trigger('pageUp');
  87. case 34:
  88. return this.trigger('pageDown');
  89. case 35:
  90. if (!event.target.form) { return this.trigger('pageBottom'); }
  91. break;
  92. case 36:
  93. if (!event.target.form) { return this.trigger('pageTop'); }
  94. break;
  95. case 37:
  96. if (!event.target.value) { return this.trigger('left'); }
  97. break;
  98. case 38:
  99. this.trigger('up');
  100. if (typeof this.showTip === 'function') {
  101. this.showTip();
  102. }
  103. return false;
  104. case 39:
  105. if (!event.target.value) { return this.trigger('right'); }
  106. break;
  107. case 40:
  108. this.trigger('down');
  109. if (typeof this.showTip === 'function') {
  110. this.showTip();
  111. }
  112. return false;
  113. case 191:
  114. if (!event.target.form) {
  115. this.trigger('typing');
  116. return false;
  117. }
  118. break;
  119. }
  120. }
  121. handleKeydownSuperEvent(event) {
  122. switch (event.which) {
  123. case 13:
  124. return this.trigger('superEnter');
  125. case 37:
  126. if (this.isMac) {
  127. this.trigger('superLeft');
  128. return false;
  129. }
  130. break;
  131. case 38:
  132. this.trigger('pageTop');
  133. return false;
  134. case 39:
  135. if (this.isMac) {
  136. this.trigger('superRight');
  137. return false;
  138. }
  139. break;
  140. case 40:
  141. this.trigger('pageBottom');
  142. return false;
  143. case 188:
  144. this.trigger('preferences');
  145. return false;
  146. }
  147. }
  148. handleKeydownShiftEvent(event, _force) {
  149. if (!_force && [37, 38, 39, 40].includes(event.which) && this.swapArrowKeysBehavior()) { return this.handleKeydownEvent(event, true); }
  150. if (!event.target.form && (65 <= event.which && event.which <= 90)) {
  151. this.trigger('typing');
  152. return;
  153. }
  154. switch (event.which) {
  155. case 32:
  156. this.trigger('pageUp');
  157. return false;
  158. case 38:
  159. if (!__guard__(getSelection(), x => x.toString())) {
  160. this.trigger('altUp');
  161. return false;
  162. }
  163. break;
  164. case 40:
  165. if (!__guard__(getSelection(), x1 => x1.toString())) {
  166. this.trigger('altDown');
  167. return false;
  168. }
  169. break;
  170. }
  171. }
  172. handleKeydownAltEvent(event, _force) {
  173. if (!_force && [37, 38, 39, 40].includes(event.which) && this.swapArrowKeysBehavior()) { return this.handleKeydownEvent(event, true); }
  174. switch (event.which) {
  175. case 9:
  176. return this.trigger('altRight', event);
  177. case 37:
  178. if (!this.isMac) {
  179. this.trigger('superLeft');
  180. return false;
  181. }
  182. break;
  183. case 38:
  184. this.trigger('altUp');
  185. return false;
  186. case 39:
  187. if (!this.isMac) {
  188. this.trigger('superRight');
  189. return false;
  190. }
  191. break;
  192. case 40:
  193. this.trigger('altDown');
  194. return false;
  195. case 67:
  196. this.trigger('altC');
  197. return false;
  198. case 68:
  199. this.trigger('altD');
  200. return false;
  201. case 70:
  202. return this.trigger('altF', event);
  203. case 71:
  204. this.trigger('altG');
  205. return false;
  206. case 79:
  207. this.trigger('altO');
  208. return false;
  209. case 82:
  210. this.trigger('altR');
  211. return false;
  212. case 83:
  213. this.trigger('altS');
  214. return false;
  215. }
  216. }
  217. handleKeypressEvent(event) {
  218. if ((event.which === 63) && !event.target.value) {
  219. this.trigger('help');
  220. return false;
  221. } else {
  222. return this.lastKeypress = Date.now();
  223. }
  224. }
  225. buggyEvent(event) {
  226. try {
  227. event.target;
  228. event.ctrlKey;
  229. event.which;
  230. return false;
  231. } catch (error) {
  232. return true;
  233. }
  234. }
  235. });
  236. Cls.initClass();
  237. function __guard__(value, transform) {
  238. return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
  239. }