# 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 |
22 | goog.provide('goog.events.KeyCodes');
23 |
24 | goog.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 | */
35 | goog.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 | */
169 | goog.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 | */
243 | goog.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 | */
316 | goog.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 | */
369 | goog.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 | */
385 | goog.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 | */
408 | goog.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 | };