lib/goog/events/keycodes.js

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