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 // We've seen users whose machines fire this keycode at regular one
156 // second intervals. The common thread among these users is that
157 // they're all using Dell Inspiron laptops, so we suspect that this
158 // indicates a hardware/bios problem.
159 // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
160 PHANTOM: 255
161};
162
163
164/**
165 * Returns true if the event contains a text modifying key.
166 * @param {goog.events.BrowserEvent} e A key event.
167 * @return {boolean} Whether it's a text modifying key.
168 */
169goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
170 if (e.altKey && !e.ctrlKey ||
171 e.metaKey ||
172 // Function keys don't generate text
173 e.keyCode >= goog.events.KeyCodes.F1 &&
174 e.keyCode <= goog.events.KeyCodes.F12) {
175 return false;
176 }
177
178 // The following keys are quite harmless, even in combination with
179 // CTRL, ALT or SHIFT.
180 switch (e.keyCode) {
181 case goog.events.KeyCodes.ALT:
182 case goog.events.KeyCodes.CAPS_LOCK:
183 case goog.events.KeyCodes.CONTEXT_MENU:
184 case goog.events.KeyCodes.CTRL:
185 case goog.events.KeyCodes.DOWN:
186 case goog.events.KeyCodes.END:
187 case goog.events.KeyCodes.ESC:
188 case goog.events.KeyCodes.HOME:
189 case goog.events.KeyCodes.INSERT:
190 case goog.events.KeyCodes.LEFT:
191 case goog.events.KeyCodes.MAC_FF_META:
192 case goog.events.KeyCodes.META:
193 case goog.events.KeyCodes.NUMLOCK:
194 case goog.events.KeyCodes.NUM_CENTER:
195 case goog.events.KeyCodes.PAGE_DOWN:
196 case goog.events.KeyCodes.PAGE_UP:
197 case goog.events.KeyCodes.PAUSE:
198 case goog.events.KeyCodes.PHANTOM:
199 case goog.events.KeyCodes.PRINT_SCREEN:
200 case goog.events.KeyCodes.RIGHT:
201 case goog.events.KeyCodes.SCROLL_LOCK:
202 case goog.events.KeyCodes.SHIFT:
203 case goog.events.KeyCodes.UP:
204 case goog.events.KeyCodes.WIN_KEY:
205 case goog.events.KeyCodes.WIN_KEY_RIGHT:
206 return false;
207 case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
208 return !goog.userAgent.GECKO;
209 default:
210 return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY ||
211 e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY;
212 }
213};
214
215
216/**
217 * Returns true if the key fires a keypress event in the current browser.
218 *
219 * Accoridng to MSDN [1] IE only fires keypress events for the following keys:
220 * - Letters: A - Z (uppercase and lowercase)
221 * - Numerals: 0 - 9
222 * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~
223 * - System: ESC, SPACEBAR, ENTER
224 *
225 * That's not entirely correct though, for instance there's no distinction
226 * between upper and lower case letters.
227 *
228 * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx)
229 *
230 * Safari is similar to IE, but does not fire keypress for ESC.
231 *
232 * Additionally, IE6 does not fire keydown or keypress events for letters when
233 * the control or alt keys are held down and the shift key is not. IE7 does
234 * fire keydown in these cases, though, but not keypress.
235 *
236 * @param {number} keyCode A key code.
237 * @param {number=} opt_heldKeyCode Key code of a currently-held key.
238 * @param {boolean=} opt_shiftKey Whether the shift key is held down.
239 * @param {boolean=} opt_ctrlKey Whether the control key is held down.
240 * @param {boolean=} opt_altKey Whether the alt key is held down.
241 * @return {boolean} Whether it's a key that fires a keypress event.
242 */
243goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
244 opt_shiftKey, opt_ctrlKey, opt_altKey) {
245 if (!goog.userAgent.IE &&
246 !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
247 return true;
248 }
249
250 if (goog.userAgent.MAC && opt_altKey) {
251 return goog.events.KeyCodes.isCharacterKey(keyCode);
252 }
253
254 // Alt but not AltGr which is represented as Alt+Ctrl.
255 if (opt_altKey && !opt_ctrlKey) {
256 return false;
257 }
258
259 // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress.
260 // Non-IE browsers and WebKit prior to 525 won't get this far so no need to
261 // check the user agent.
262 if (goog.isNumber(opt_heldKeyCode)) {
263 opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
264 }
265 if (!opt_shiftKey &&
266 (opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
267 opt_heldKeyCode == goog.events.KeyCodes.ALT ||
268 goog.userAgent.MAC &&
269 opt_heldKeyCode == goog.events.KeyCodes.META)) {
270 return false;
271 }
272
273 // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
274 if (goog.userAgent.WEBKIT && opt_ctrlKey && opt_shiftKey) {
275 switch (keyCode) {
276 case goog.events.KeyCodes.BACKSLASH:
277 case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
278 case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
279 case goog.events.KeyCodes.TILDE:
280 case goog.events.KeyCodes.SEMICOLON:
281 case goog.events.KeyCodes.DASH:
282 case goog.events.KeyCodes.EQUALS:
283 case goog.events.KeyCodes.COMMA:
284 case goog.events.KeyCodes.PERIOD:
285 case goog.events.KeyCodes.SLASH:
286 case goog.events.KeyCodes.APOSTROPHE:
287 case goog.events.KeyCodes.SINGLE_QUOTE:
288 return false;
289 }
290 }
291
292 // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it
293 // continues to fire keydown events as the event repeats.
294 if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
295 return false;
296 }
297
298 switch (keyCode) {
299 case goog.events.KeyCodes.ENTER:
300 return true;
301 case goog.events.KeyCodes.ESC:
302 return !goog.userAgent.WEBKIT;
303 }
304
305 return goog.events.KeyCodes.isCharacterKey(keyCode);
306};
307
308
309/**
310 * Returns true if the key produces a character.
311 * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.).
312 *
313 * @param {number} keyCode A key code.
314 * @return {boolean} Whether it's a character key.
315 */
316goog.events.KeyCodes.isCharacterKey = function(keyCode) {
317 if (keyCode >= goog.events.KeyCodes.ZERO &&
318 keyCode <= goog.events.KeyCodes.NINE) {
319 return true;
320 }
321
322 if (keyCode >= goog.events.KeyCodes.NUM_ZERO &&
323 keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) {
324 return true;
325 }
326
327 if (keyCode >= goog.events.KeyCodes.A &&
328 keyCode <= goog.events.KeyCodes.Z) {
329 return true;
330 }
331
332 // Safari sends zero key code for non-latin characters.
333 if (goog.userAgent.WEBKIT && keyCode == 0) {
334 return true;
335 }
336
337 switch (keyCode) {
338 case goog.events.KeyCodes.SPACE:
339 case goog.events.KeyCodes.QUESTION_MARK:
340 case goog.events.KeyCodes.NUM_PLUS:
341 case goog.events.KeyCodes.NUM_MINUS:
342 case goog.events.KeyCodes.NUM_PERIOD:
343 case goog.events.KeyCodes.NUM_DIVISION:
344 case goog.events.KeyCodes.SEMICOLON:
345 case goog.events.KeyCodes.FF_SEMICOLON:
346 case goog.events.KeyCodes.DASH:
347 case goog.events.KeyCodes.EQUALS:
348 case goog.events.KeyCodes.FF_EQUALS:
349 case goog.events.KeyCodes.COMMA:
350 case goog.events.KeyCodes.PERIOD:
351 case goog.events.KeyCodes.SLASH:
352 case goog.events.KeyCodes.APOSTROPHE:
353 case goog.events.KeyCodes.SINGLE_QUOTE:
354 case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
355 case goog.events.KeyCodes.BACKSLASH:
356 case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
357 return true;
358 default:
359 return false;
360 }
361};
362
363
364/**
365 * Normalizes key codes from OS/Browser-specific value to the general one.
366 * @param {number} keyCode The native key code.
367 * @return {number} The normalized key code.
368 */
369goog.events.KeyCodes.normalizeKeyCode = function(keyCode) {
370 if (goog.userAgent.GECKO) {
371 return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode);
372 } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) {
373 return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode);
374 } else {
375 return keyCode;
376 }
377};
378
379
380/**
381 * Normalizes key codes from their Gecko-specific value to the general one.
382 * @param {number} keyCode The native key code.
383 * @return {number} The normalized key code.
384 */
385goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) {
386 switch (keyCode) {
387 case goog.events.KeyCodes.FF_EQUALS:
388 return goog.events.KeyCodes.EQUALS;
389 case goog.events.KeyCodes.FF_SEMICOLON:
390 return goog.events.KeyCodes.SEMICOLON;
391 case goog.events.KeyCodes.FF_DASH:
392 return goog.events.KeyCodes.DASH;
393 case goog.events.KeyCodes.MAC_FF_META:
394 return goog.events.KeyCodes.META;
395 case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
396 return goog.events.KeyCodes.WIN_KEY;
397 default:
398 return keyCode;
399 }
400};
401
402
403/**
404 * Normalizes key codes from their Mac WebKit-specific value to the general one.
405 * @param {number} keyCode The native key code.
406 * @return {number} The normalized key code.
407 */
408goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
409 switch (keyCode) {
410 case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93
411 return goog.events.KeyCodes.META; // 91
412 default:
413 return keyCode;
414 }
415};