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