shortcuts.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  9. */
  10. app.Shortcuts = class Shortcuts extends Events {
  11. constructor() {
  12. super();
  13. this.onKeydown = this.onKeydown.bind(this);
  14. this.onKeypress = this.onKeypress.bind(this);
  15. this.isMac = $.isMac();
  16. this.start();
  17. }
  18. start() {
  19. $.on(document, "keydown", this.onKeydown);
  20. $.on(document, "keypress", this.onKeypress);
  21. }
  22. stop() {
  23. $.off(document, "keydown", this.onKeydown);
  24. $.off(document, "keypress", this.onKeypress);
  25. }
  26. swapArrowKeysBehavior() {
  27. return app.settings.get("arrowScroll");
  28. }
  29. spaceScroll() {
  30. return app.settings.get("spaceScroll");
  31. }
  32. showTip() {
  33. app.showTip("KeyNav");
  34. return (this.showTip = null);
  35. }
  36. spaceTimeout() {
  37. return app.settings.get("spaceTimeout");
  38. }
  39. onKeydown(event) {
  40. if (this.buggyEvent(event)) {
  41. return;
  42. }
  43. const result = (() => {
  44. if (event.ctrlKey || event.metaKey) {
  45. if (!event.altKey && !event.shiftKey) {
  46. return this.handleKeydownSuperEvent(event);
  47. }
  48. } else if (event.shiftKey) {
  49. if (!event.altKey) {
  50. return this.handleKeydownShiftEvent(event);
  51. }
  52. } else if (event.altKey) {
  53. return this.handleKeydownAltEvent(event);
  54. } else {
  55. return this.handleKeydownEvent(event);
  56. }
  57. })();
  58. if (result === false) {
  59. event.preventDefault();
  60. }
  61. }
  62. onKeypress(event) {
  63. if (
  64. this.buggyEvent(event) ||
  65. (event.charCode === 63 && document.activeElement.tagName === "INPUT")
  66. ) {
  67. return;
  68. }
  69. if (!event.ctrlKey && !event.metaKey) {
  70. const result = this.handleKeypressEvent(event);
  71. if (result === false) {
  72. event.preventDefault();
  73. }
  74. }
  75. }
  76. handleKeydownEvent(event, _force) {
  77. if (
  78. !_force &&
  79. [37, 38, 39, 40].includes(event.which) &&
  80. this.swapArrowKeysBehavior()
  81. ) {
  82. return this.handleKeydownAltEvent(event, true);
  83. }
  84. if (
  85. !event.target.form &&
  86. ((48 <= event.which && event.which <= 57) ||
  87. (65 <= event.which && event.which <= 90))
  88. ) {
  89. this.trigger("typing");
  90. return;
  91. }
  92. switch (event.which) {
  93. case 8:
  94. if (!event.target.form) {
  95. return this.trigger("typing");
  96. }
  97. break;
  98. case 13:
  99. return this.trigger("enter");
  100. case 27:
  101. this.trigger("escape");
  102. return false;
  103. case 32:
  104. if (
  105. event.target.type === "search" &&
  106. this.spaceScroll() &&
  107. (!this.lastKeypress ||
  108. this.lastKeypress < Date.now() - this.spaceTimeout() * 1000)
  109. ) {
  110. this.trigger("pageDown");
  111. return false;
  112. }
  113. break;
  114. case 33:
  115. return this.trigger("pageUp");
  116. case 34:
  117. return this.trigger("pageDown");
  118. case 35:
  119. if (!event.target.form) {
  120. return this.trigger("pageBottom");
  121. }
  122. break;
  123. case 36:
  124. if (!event.target.form) {
  125. return this.trigger("pageTop");
  126. }
  127. break;
  128. case 37:
  129. if (!event.target.value) {
  130. return this.trigger("left");
  131. }
  132. break;
  133. case 38:
  134. this.trigger("up");
  135. if (typeof this.showTip === "function") {
  136. this.showTip();
  137. }
  138. return false;
  139. case 39:
  140. if (!event.target.value) {
  141. return this.trigger("right");
  142. }
  143. break;
  144. case 40:
  145. this.trigger("down");
  146. if (typeof this.showTip === "function") {
  147. this.showTip();
  148. }
  149. return false;
  150. case 191:
  151. if (!event.target.form) {
  152. this.trigger("typing");
  153. return false;
  154. }
  155. break;
  156. }
  157. }
  158. handleKeydownSuperEvent(event) {
  159. switch (event.which) {
  160. case 13:
  161. return this.trigger("superEnter");
  162. case 37:
  163. if (this.isMac) {
  164. this.trigger("superLeft");
  165. return false;
  166. }
  167. break;
  168. case 38:
  169. this.trigger("pageTop");
  170. return false;
  171. case 39:
  172. if (this.isMac) {
  173. this.trigger("superRight");
  174. return false;
  175. }
  176. break;
  177. case 40:
  178. this.trigger("pageBottom");
  179. return false;
  180. case 188:
  181. this.trigger("preferences");
  182. return false;
  183. }
  184. }
  185. handleKeydownShiftEvent(event, _force) {
  186. if (
  187. !_force &&
  188. [37, 38, 39, 40].includes(event.which) &&
  189. this.swapArrowKeysBehavior()
  190. ) {
  191. return this.handleKeydownEvent(event, true);
  192. }
  193. if (!event.target.form && 65 <= event.which && event.which <= 90) {
  194. this.trigger("typing");
  195. return;
  196. }
  197. switch (event.which) {
  198. case 32:
  199. this.trigger("pageUp");
  200. return false;
  201. case 38:
  202. if (!__guard__(getSelection(), (x) => x.toString())) {
  203. this.trigger("altUp");
  204. return false;
  205. }
  206. break;
  207. case 40:
  208. if (!__guard__(getSelection(), (x1) => x1.toString())) {
  209. this.trigger("altDown");
  210. return false;
  211. }
  212. break;
  213. }
  214. }
  215. handleKeydownAltEvent(event, _force) {
  216. if (
  217. !_force &&
  218. [37, 38, 39, 40].includes(event.which) &&
  219. this.swapArrowKeysBehavior()
  220. ) {
  221. return this.handleKeydownEvent(event, true);
  222. }
  223. switch (event.which) {
  224. case 9:
  225. return this.trigger("altRight", event);
  226. case 37:
  227. if (!this.isMac) {
  228. this.trigger("superLeft");
  229. return false;
  230. }
  231. break;
  232. case 38:
  233. this.trigger("altUp");
  234. return false;
  235. case 39:
  236. if (!this.isMac) {
  237. this.trigger("superRight");
  238. return false;
  239. }
  240. break;
  241. case 40:
  242. this.trigger("altDown");
  243. return false;
  244. case 67:
  245. this.trigger("altC");
  246. return false;
  247. case 68:
  248. this.trigger("altD");
  249. return false;
  250. case 70:
  251. return this.trigger("altF", event);
  252. case 71:
  253. this.trigger("altG");
  254. return false;
  255. case 79:
  256. this.trigger("altO");
  257. return false;
  258. case 82:
  259. this.trigger("altR");
  260. return false;
  261. case 83:
  262. this.trigger("altS");
  263. return false;
  264. }
  265. }
  266. handleKeypressEvent(event) {
  267. if (event.which === 63 && !event.target.value) {
  268. this.trigger("help");
  269. return false;
  270. } else {
  271. return (this.lastKeypress = Date.now());
  272. }
  273. }
  274. buggyEvent(event) {
  275. try {
  276. event.target;
  277. event.ctrlKey;
  278. event.which;
  279. return false;
  280. } catch (error) {
  281. return true;
  282. }
  283. }
  284. };
  285. function __guard__(value, transform) {
  286. return typeof value !== "undefined" && value !== null
  287. ? transform(value)
  288. : undefined;
  289. }