keycodes.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Constant declarations for common key codes.
  16. *
  17. * @author eae@google.com (Emil A Eklund)
  18. * @see ../demos/keyhandler.html
  19. */
  20. goog.provide('goog.events.KeyCodes');
  21. goog.require('goog.userAgent');
  22. goog.forwardDeclare('goog.events.BrowserEvent');
  23. /**
  24. * Key codes for common characters.
  25. *
  26. * This list is not localized and therefore some of the key codes are not
  27. * correct for non US keyboard layouts. See comments below.
  28. *
  29. * @enum {number}
  30. */
  31. goog.events.KeyCodes = {
  32. WIN_KEY_FF_LINUX: 0,
  33. MAC_ENTER: 3,
  34. BACKSPACE: 8,
  35. TAB: 9,
  36. NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac
  37. ENTER: 13,
  38. SHIFT: 16,
  39. CTRL: 17,
  40. ALT: 18,
  41. PAUSE: 19,
  42. CAPS_LOCK: 20,
  43. ESC: 27,
  44. SPACE: 32,
  45. PAGE_UP: 33, // also NUM_NORTH_EAST
  46. PAGE_DOWN: 34, // also NUM_SOUTH_EAST
  47. END: 35, // also NUM_SOUTH_WEST
  48. HOME: 36, // also NUM_NORTH_WEST
  49. LEFT: 37, // also NUM_WEST
  50. UP: 38, // also NUM_NORTH
  51. RIGHT: 39, // also NUM_EAST
  52. DOWN: 40, // also NUM_SOUTH
  53. PLUS_SIGN: 43, // NOT numpad plus
  54. PRINT_SCREEN: 44,
  55. INSERT: 45, // also NUM_INSERT
  56. DELETE: 46, // also NUM_DELETE
  57. ZERO: 48,
  58. ONE: 49,
  59. TWO: 50,
  60. THREE: 51,
  61. FOUR: 52,
  62. FIVE: 53,
  63. SIX: 54,
  64. SEVEN: 55,
  65. EIGHT: 56,
  66. NINE: 57,
  67. FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186
  68. FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187
  69. FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189
  70. QUESTION_MARK: 63, // needs localization
  71. AT_SIGN: 64,
  72. A: 65,
  73. B: 66,
  74. C: 67,
  75. D: 68,
  76. E: 69,
  77. F: 70,
  78. G: 71,
  79. H: 72,
  80. I: 73,
  81. J: 74,
  82. K: 75,
  83. L: 76,
  84. M: 77,
  85. N: 78,
  86. O: 79,
  87. P: 80,
  88. Q: 81,
  89. R: 82,
  90. S: 83,
  91. T: 84,
  92. U: 85,
  93. V: 86,
  94. W: 87,
  95. X: 88,
  96. Y: 89,
  97. Z: 90,
  98. META: 91, // WIN_KEY_LEFT
  99. WIN_KEY_RIGHT: 92,
  100. CONTEXT_MENU: 93,
  101. NUM_ZERO: 96,
  102. NUM_ONE: 97,
  103. NUM_TWO: 98,
  104. NUM_THREE: 99,
  105. NUM_FOUR: 100,
  106. NUM_FIVE: 101,
  107. NUM_SIX: 102,
  108. NUM_SEVEN: 103,
  109. NUM_EIGHT: 104,
  110. NUM_NINE: 105,
  111. NUM_MULTIPLY: 106,
  112. NUM_PLUS: 107,
  113. NUM_MINUS: 109,
  114. NUM_PERIOD: 110,
  115. NUM_DIVISION: 111,
  116. F1: 112,
  117. F2: 113,
  118. F3: 114,
  119. F4: 115,
  120. F5: 116,
  121. F6: 117,
  122. F7: 118,
  123. F8: 119,
  124. F9: 120,
  125. F10: 121,
  126. F11: 122,
  127. F12: 123,
  128. NUMLOCK: 144,
  129. SCROLL_LOCK: 145,
  130. // OS-specific media keys like volume controls and browser controls.
  131. FIRST_MEDIA_KEY: 166,
  132. LAST_MEDIA_KEY: 183,
  133. SEMICOLON: 186, // needs localization
  134. DASH: 189, // needs localization
  135. EQUALS: 187, // needs localization
  136. COMMA: 188, // needs localization
  137. PERIOD: 190, // needs localization
  138. SLASH: 191, // needs localization
  139. APOSTROPHE: 192, // needs localization
  140. TILDE: 192, // needs localization
  141. SINGLE_QUOTE: 222, // needs localization
  142. OPEN_SQUARE_BRACKET: 219, // needs localization
  143. BACKSLASH: 220, // needs localization
  144. CLOSE_SQUARE_BRACKET: 221, // needs localization
  145. WIN_KEY: 224,
  146. MAC_FF_META:
  147. 224, // Firefox (Gecko) fires this for the meta key instead of 91
  148. MAC_WK_CMD_LEFT: 91, // WebKit Left Command key fired, same as META
  149. MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META
  150. WIN_IME: 229,
  151. // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX
  152. // control) fire this as a hacky way to disable screensavers.
  153. VK_NONAME: 252,
  154. // We've seen users whose machines fire this keycode at regular one
  155. // second intervals. The common thread among these users is that
  156. // they're all using Dell Inspiron laptops, so we suspect that this
  157. // indicates a hardware/bios problem.
  158. // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
  159. PHANTOM: 255
  160. };
  161. /**
  162. * Returns false if the event does not contain a text modifying key.
  163. *
  164. * When it returns true, the event might be text modifying. It is infeasible to
  165. * say for sure because of the many different keyboard layouts, so this method
  166. * errs on the side of assuming a key event is text-modifiable if we cannot be
  167. * certain it is not. As an example, it will return true for ctrl+a, though in
  168. * many standard keyboard layouts that key combination would mean "select all",
  169. * and not actually modify the text.
  170. *
  171. * @param {goog.events.BrowserEvent} e A key event.
  172. * @return {boolean} Whether it's a text modifying key.
  173. */
  174. goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
  175. if (e.altKey && !e.ctrlKey || e.metaKey ||
  176. // Function keys don't generate text
  177. e.keyCode >= goog.events.KeyCodes.F1 &&
  178. e.keyCode <= goog.events.KeyCodes.F12) {
  179. return false;
  180. }
  181. // The following keys are quite harmless, even in combination with
  182. // CTRL, ALT or SHIFT.
  183. switch (e.keyCode) {
  184. case goog.events.KeyCodes.ALT:
  185. case goog.events.KeyCodes.CAPS_LOCK:
  186. case goog.events.KeyCodes.CONTEXT_MENU:
  187. case goog.events.KeyCodes.CTRL:
  188. case goog.events.KeyCodes.DOWN:
  189. case goog.events.KeyCodes.END:
  190. case goog.events.KeyCodes.ESC:
  191. case goog.events.KeyCodes.HOME:
  192. case goog.events.KeyCodes.INSERT:
  193. case goog.events.KeyCodes.LEFT:
  194. case goog.events.KeyCodes.MAC_FF_META:
  195. case goog.events.KeyCodes.META:
  196. case goog.events.KeyCodes.NUMLOCK:
  197. case goog.events.KeyCodes.NUM_CENTER:
  198. case goog.events.KeyCodes.PAGE_DOWN:
  199. case goog.events.KeyCodes.PAGE_UP:
  200. case goog.events.KeyCodes.PAUSE:
  201. case goog.events.KeyCodes.PHANTOM:
  202. case goog.events.KeyCodes.PRINT_SCREEN:
  203. case goog.events.KeyCodes.RIGHT:
  204. case goog.events.KeyCodes.SCROLL_LOCK:
  205. case goog.events.KeyCodes.SHIFT:
  206. case goog.events.KeyCodes.UP:
  207. case goog.events.KeyCodes.VK_NONAME:
  208. case goog.events.KeyCodes.WIN_KEY:
  209. case goog.events.KeyCodes.WIN_KEY_RIGHT:
  210. return false;
  211. case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
  212. return !goog.userAgent.GECKO;
  213. default:
  214. return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY ||
  215. e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY;
  216. }
  217. };
  218. /**
  219. * Returns true if the key fires a keypress event in the current browser.
  220. *
  221. * Accoridng to MSDN [1] IE only fires keypress events for the following keys:
  222. * - Letters: A - Z (uppercase and lowercase)
  223. * - Numerals: 0 - 9
  224. * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~
  225. * - System: ESC, SPACEBAR, ENTER
  226. *
  227. * That's not entirely correct though, for instance there's no distinction
  228. * between upper and lower case letters.
  229. *
  230. * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx)
  231. *
  232. * Safari is similar to IE, but does not fire keypress for ESC.
  233. *
  234. * Additionally, IE6 does not fire keydown or keypress events for letters when
  235. * the control or alt keys are held down and the shift key is not. IE7 does
  236. * fire keydown in these cases, though, but not keypress.
  237. *
  238. * @param {number} keyCode A key code.
  239. * @param {number=} opt_heldKeyCode Key code of a currently-held key.
  240. * @param {boolean=} opt_shiftKey Whether the shift key is held down.
  241. * @param {boolean=} opt_ctrlKey Whether the control key is held down.
  242. * @param {boolean=} opt_altKey Whether the alt key is held down.
  243. * @param {boolean=} opt_metaKey Whether the meta key is held down.
  244. * @return {boolean} Whether it's a key that fires a keypress event.
  245. */
  246. goog.events.KeyCodes.firesKeyPressEvent = function(
  247. keyCode, opt_heldKeyCode, opt_shiftKey, opt_ctrlKey, opt_altKey,
  248. opt_metaKey) {
  249. if (!goog.userAgent.IE && !goog.userAgent.EDGE &&
  250. !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
  251. return true;
  252. }
  253. if (goog.userAgent.MAC && opt_altKey) {
  254. return goog.events.KeyCodes.isCharacterKey(keyCode);
  255. }
  256. // Alt but not AltGr which is represented as Alt+Ctrl.
  257. if (opt_altKey && !opt_ctrlKey) {
  258. return false;
  259. }
  260. // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress.
  261. // Non-IE browsers and WebKit prior to 525 won't get this far so no need to
  262. // check the user agent.
  263. if (goog.isNumber(opt_heldKeyCode)) {
  264. opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
  265. }
  266. var heldKeyIsModifier = opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
  267. opt_heldKeyCode == goog.events.KeyCodes.ALT ||
  268. goog.userAgent.MAC && opt_heldKeyCode == goog.events.KeyCodes.META;
  269. // The Shift key blocks keypresses on Mac iff accompanied by another modifier.
  270. var modifiedShiftKey = opt_heldKeyCode == goog.events.KeyCodes.SHIFT &&
  271. (opt_ctrlKey || opt_metaKey);
  272. if ((!opt_shiftKey || goog.userAgent.MAC) && heldKeyIsModifier ||
  273. goog.userAgent.MAC && modifiedShiftKey) {
  274. return false;
  275. }
  276. // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
  277. if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && opt_ctrlKey &&
  278. opt_shiftKey) {
  279. switch (keyCode) {
  280. case goog.events.KeyCodes.BACKSLASH:
  281. case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
  282. case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
  283. case goog.events.KeyCodes.TILDE:
  284. case goog.events.KeyCodes.SEMICOLON:
  285. case goog.events.KeyCodes.DASH:
  286. case goog.events.KeyCodes.EQUALS:
  287. case goog.events.KeyCodes.COMMA:
  288. case goog.events.KeyCodes.PERIOD:
  289. case goog.events.KeyCodes.SLASH:
  290. case goog.events.KeyCodes.APOSTROPHE:
  291. case goog.events.KeyCodes.SINGLE_QUOTE:
  292. return false;
  293. }
  294. }
  295. // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it
  296. // continues to fire keydown events as the event repeats.
  297. if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
  298. return false;
  299. }
  300. switch (keyCode) {
  301. case goog.events.KeyCodes.ENTER:
  302. return true;
  303. case goog.events.KeyCodes.ESC:
  304. return !(goog.userAgent.WEBKIT || goog.userAgent.EDGE);
  305. }
  306. return goog.events.KeyCodes.isCharacterKey(keyCode);
  307. };
  308. /**
  309. * Returns true if the key produces a character.
  310. * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.).
  311. *
  312. * @param {number} keyCode A key code.
  313. * @return {boolean} Whether it's a character key.
  314. */
  315. goog.events.KeyCodes.isCharacterKey = function(keyCode) {
  316. if (keyCode >= goog.events.KeyCodes.ZERO &&
  317. keyCode <= goog.events.KeyCodes.NINE) {
  318. return true;
  319. }
  320. if (keyCode >= goog.events.KeyCodes.NUM_ZERO &&
  321. keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) {
  322. return true;
  323. }
  324. if (keyCode >= goog.events.KeyCodes.A && keyCode <= goog.events.KeyCodes.Z) {
  325. return true;
  326. }
  327. // Safari sends zero key code for non-latin characters.
  328. if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && keyCode == 0) {
  329. return true;
  330. }
  331. switch (keyCode) {
  332. case goog.events.KeyCodes.SPACE:
  333. case goog.events.KeyCodes.PLUS_SIGN:
  334. case goog.events.KeyCodes.QUESTION_MARK:
  335. case goog.events.KeyCodes.AT_SIGN:
  336. case goog.events.KeyCodes.NUM_PLUS:
  337. case goog.events.KeyCodes.NUM_MINUS:
  338. case goog.events.KeyCodes.NUM_PERIOD:
  339. case goog.events.KeyCodes.NUM_DIVISION:
  340. case goog.events.KeyCodes.SEMICOLON:
  341. case goog.events.KeyCodes.FF_SEMICOLON:
  342. case goog.events.KeyCodes.DASH:
  343. case goog.events.KeyCodes.EQUALS:
  344. case goog.events.KeyCodes.FF_EQUALS:
  345. case goog.events.KeyCodes.COMMA:
  346. case goog.events.KeyCodes.PERIOD:
  347. case goog.events.KeyCodes.SLASH:
  348. case goog.events.KeyCodes.APOSTROPHE:
  349. case goog.events.KeyCodes.SINGLE_QUOTE:
  350. case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
  351. case goog.events.KeyCodes.BACKSLASH:
  352. case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
  353. return true;
  354. default:
  355. return false;
  356. }
  357. };
  358. /**
  359. * Normalizes key codes from OS/Browser-specific value to the general one.
  360. * @param {number} keyCode The native key code.
  361. * @return {number} The normalized key code.
  362. */
  363. goog.events.KeyCodes.normalizeKeyCode = function(keyCode) {
  364. if (goog.userAgent.GECKO) {
  365. return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode);
  366. } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) {
  367. return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode);
  368. } else {
  369. return keyCode;
  370. }
  371. };
  372. /**
  373. * Normalizes key codes from their Gecko-specific value to the general one.
  374. * @param {number} keyCode The native key code.
  375. * @return {number} The normalized key code.
  376. */
  377. goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) {
  378. switch (keyCode) {
  379. case goog.events.KeyCodes.FF_EQUALS:
  380. return goog.events.KeyCodes.EQUALS;
  381. case goog.events.KeyCodes.FF_SEMICOLON:
  382. return goog.events.KeyCodes.SEMICOLON;
  383. case goog.events.KeyCodes.FF_DASH:
  384. return goog.events.KeyCodes.DASH;
  385. case goog.events.KeyCodes.MAC_FF_META:
  386. return goog.events.KeyCodes.META;
  387. case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
  388. return goog.events.KeyCodes.WIN_KEY;
  389. default:
  390. return keyCode;
  391. }
  392. };
  393. /**
  394. * Normalizes key codes from their Mac WebKit-specific value to the general one.
  395. * @param {number} keyCode The native key code.
  396. * @return {number} The normalized key code.
  397. */
  398. goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
  399. switch (keyCode) {
  400. case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93
  401. return goog.events.KeyCodes.META; // 91
  402. default:
  403. return keyCode;
  404. }
  405. };