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 | }; |