// Copyright 2006 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @fileoverview Constant declarations for common key codes. * * @author eae@google.com (Emil A Eklund) * @see ../demos/keyhandler.html */ goog.provide('goog.events.KeyCodes'); goog.require('goog.userAgent'); goog.forwardDeclare('goog.events.BrowserEvent'); /** * Key codes for common characters. * * This list is not localized and therefore some of the key codes are not * correct for non US keyboard layouts. See comments below. * * @enum {number} */ goog.events.KeyCodes = { WIN_KEY_FF_LINUX: 0, MAC_ENTER: 3, BACKSPACE: 8, TAB: 9, NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, PAUSE: 19, CAPS_LOCK: 20, ESC: 27, SPACE: 32, PAGE_UP: 33, // also NUM_NORTH_EAST PAGE_DOWN: 34, // also NUM_SOUTH_EAST END: 35, // also NUM_SOUTH_WEST HOME: 36, // also NUM_NORTH_WEST LEFT: 37, // also NUM_WEST UP: 38, // also NUM_NORTH RIGHT: 39, // also NUM_EAST DOWN: 40, // also NUM_SOUTH PLUS_SIGN: 43, // NOT numpad plus PRINT_SCREEN: 44, INSERT: 45, // also NUM_INSERT DELETE: 46, // also NUM_DELETE ZERO: 48, ONE: 49, TWO: 50, THREE: 51, FOUR: 52, FIVE: 53, SIX: 54, SEVEN: 55, EIGHT: 56, NINE: 57, FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186 FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187 FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189 QUESTION_MARK: 63, // needs localization AT_SIGN: 64, A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77, N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86, W: 87, X: 88, Y: 89, Z: 90, META: 91, // WIN_KEY_LEFT WIN_KEY_RIGHT: 92, CONTEXT_MENU: 93, NUM_ZERO: 96, NUM_ONE: 97, NUM_TWO: 98, NUM_THREE: 99, NUM_FOUR: 100, NUM_FIVE: 101, NUM_SIX: 102, NUM_SEVEN: 103, NUM_EIGHT: 104, NUM_NINE: 105, NUM_MULTIPLY: 106, NUM_PLUS: 107, NUM_MINUS: 109, NUM_PERIOD: 110, NUM_DIVISION: 111, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, F7: 118, F8: 119, F9: 120, F10: 121, F11: 122, F12: 123, NUMLOCK: 144, SCROLL_LOCK: 145, // OS-specific media keys like volume controls and browser controls. FIRST_MEDIA_KEY: 166, LAST_MEDIA_KEY: 183, SEMICOLON: 186, // needs localization DASH: 189, // needs localization EQUALS: 187, // needs localization COMMA: 188, // needs localization PERIOD: 190, // needs localization SLASH: 191, // needs localization APOSTROPHE: 192, // needs localization TILDE: 192, // needs localization SINGLE_QUOTE: 222, // needs localization OPEN_SQUARE_BRACKET: 219, // needs localization BACKSLASH: 220, // needs localization CLOSE_SQUARE_BRACKET: 221, // needs localization WIN_KEY: 224, MAC_FF_META: 224, // Firefox (Gecko) fires this for the meta key instead of 91 MAC_WK_CMD_LEFT: 91, // WebKit Left Command key fired, same as META MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META WIN_IME: 229, // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX // control) fire this as a hacky way to disable screensavers. VK_NONAME: 252, // We've seen users whose machines fire this keycode at regular one // second intervals. The common thread among these users is that // they're all using Dell Inspiron laptops, so we suspect that this // indicates a hardware/bios problem. // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx PHANTOM: 255 }; /** * Returns false if the event does not contain a text modifying key. * * When it returns true, the event might be text modifying. It is infeasible to * say for sure because of the many different keyboard layouts, so this method * errs on the side of assuming a key event is text-modifiable if we cannot be * certain it is not. As an example, it will return true for ctrl+a, though in * many standard keyboard layouts that key combination would mean "select all", * and not actually modify the text. * * @param {goog.events.BrowserEvent} e A key event. * @return {boolean} Whether it's a text modifying key. */ goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) { if (e.altKey && !e.ctrlKey || e.metaKey || // Function keys don't generate text e.keyCode >= goog.events.KeyCodes.F1 && e.keyCode <= goog.events.KeyCodes.F12) { return false; } // The following keys are quite harmless, even in combination with // CTRL, ALT or SHIFT. switch (e.keyCode) { case goog.events.KeyCodes.ALT: case goog.events.KeyCodes.CAPS_LOCK: case goog.events.KeyCodes.CONTEXT_MENU: case goog.events.KeyCodes.CTRL: case goog.events.KeyCodes.DOWN: case goog.events.KeyCodes.END: case goog.events.KeyCodes.ESC: case goog.events.KeyCodes.HOME: case goog.events.KeyCodes.INSERT: case goog.events.KeyCodes.LEFT: case goog.events.KeyCodes.MAC_FF_META: case goog.events.KeyCodes.META: case goog.events.KeyCodes.NUMLOCK: case goog.events.KeyCodes.NUM_CENTER: case goog.events.KeyCodes.PAGE_DOWN: case goog.events.KeyCodes.PAGE_UP: case goog.events.KeyCodes.PAUSE: case goog.events.KeyCodes.PHANTOM: case goog.events.KeyCodes.PRINT_SCREEN: case goog.events.KeyCodes.RIGHT: case goog.events.KeyCodes.SCROLL_LOCK: case goog.events.KeyCodes.SHIFT: case goog.events.KeyCodes.UP: case goog.events.KeyCodes.VK_NONAME: case goog.events.KeyCodes.WIN_KEY: case goog.events.KeyCodes.WIN_KEY_RIGHT: return false; case goog.events.KeyCodes.WIN_KEY_FF_LINUX: return !goog.userAgent.GECKO; default: return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY || e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY; } }; /** * Returns true if the key fires a keypress event in the current browser. * * Accoridng to MSDN [1] IE only fires keypress events for the following keys: * - Letters: A - Z (uppercase and lowercase) * - Numerals: 0 - 9 * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~ * - System: ESC, SPACEBAR, ENTER * * That's not entirely correct though, for instance there's no distinction * between upper and lower case letters. * * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx) * * Safari is similar to IE, but does not fire keypress for ESC. * * Additionally, IE6 does not fire keydown or keypress events for letters when * the control or alt keys are held down and the shift key is not. IE7 does * fire keydown in these cases, though, but not keypress. * * @param {number} keyCode A key code. * @param {number=} opt_heldKeyCode Key code of a currently-held key. * @param {boolean=} opt_shiftKey Whether the shift key is held down. * @param {boolean=} opt_ctrlKey Whether the control key is held down. * @param {boolean=} opt_altKey Whether the alt key is held down. * @param {boolean=} opt_metaKey Whether the meta key is held down. * @return {boolean} Whether it's a key that fires a keypress event. */ goog.events.KeyCodes.firesKeyPressEvent = function( keyCode, opt_heldKeyCode, opt_shiftKey, opt_ctrlKey, opt_altKey, opt_metaKey) { if (!goog.userAgent.IE && !goog.userAgent.EDGE && !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) { return true; } if (goog.userAgent.MAC && opt_altKey) { return goog.events.KeyCodes.isCharacterKey(keyCode); } // Alt but not AltGr which is represented as Alt+Ctrl. if (opt_altKey && !opt_ctrlKey) { return false; } // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress. // Non-IE browsers and WebKit prior to 525 won't get this far so no need to // check the user agent. if (goog.isNumber(opt_heldKeyCode)) { opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode); } var heldKeyIsModifier = opt_heldKeyCode == goog.events.KeyCodes.CTRL || opt_heldKeyCode == goog.events.KeyCodes.ALT || goog.userAgent.MAC && opt_heldKeyCode == goog.events.KeyCodes.META; // The Shift key blocks keypresses on Mac iff accompanied by another modifier. var modifiedShiftKey = opt_heldKeyCode == goog.events.KeyCodes.SHIFT && (opt_ctrlKey || opt_metaKey); if ((!opt_shiftKey || goog.userAgent.MAC) && heldKeyIsModifier || goog.userAgent.MAC && modifiedShiftKey) { return false; } // Some keys with Ctrl/Shift do not issue keypress in WEBKIT. if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && opt_ctrlKey && opt_shiftKey) { switch (keyCode) { case goog.events.KeyCodes.BACKSLASH: case goog.events.KeyCodes.OPEN_SQUARE_BRACKET: case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET: case goog.events.KeyCodes.TILDE: case goog.events.KeyCodes.SEMICOLON: case goog.events.KeyCodes.DASH: case goog.events.KeyCodes.EQUALS: case goog.events.KeyCodes.COMMA: case goog.events.KeyCodes.PERIOD: case goog.events.KeyCodes.SLASH: case goog.events.KeyCodes.APOSTROPHE: case goog.events.KeyCodes.SINGLE_QUOTE: return false; } } // When Ctrl+ is held in IE, it only fires a keypress once, but it // continues to fire keydown events as the event repeats. if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) { return false; } switch (keyCode) { case goog.events.KeyCodes.ENTER: return true; case goog.events.KeyCodes.ESC: return !(goog.userAgent.WEBKIT || goog.userAgent.EDGE); } return goog.events.KeyCodes.isCharacterKey(keyCode); }; /** * Returns true if the key produces a character. * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.). * * @param {number} keyCode A key code. * @return {boolean} Whether it's a character key. */ goog.events.KeyCodes.isCharacterKey = function(keyCode) { if (keyCode >= goog.events.KeyCodes.ZERO && keyCode <= goog.events.KeyCodes.NINE) { return true; } if (keyCode >= goog.events.KeyCodes.NUM_ZERO && keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) { return true; } if (keyCode >= goog.events.KeyCodes.A && keyCode <= goog.events.KeyCodes.Z) { return true; } // Safari sends zero key code for non-latin characters. if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && keyCode == 0) { return true; } switch (keyCode) { case goog.events.KeyCodes.SPACE: case goog.events.KeyCodes.PLUS_SIGN: case goog.events.KeyCodes.QUESTION_MARK: case goog.events.KeyCodes.AT_SIGN: case goog.events.KeyCodes.NUM_PLUS: case goog.events.KeyCodes.NUM_MINUS: case goog.events.KeyCodes.NUM_PERIOD: case goog.events.KeyCodes.NUM_DIVISION: case goog.events.KeyCodes.SEMICOLON: case goog.events.KeyCodes.FF_SEMICOLON: case goog.events.KeyCodes.DASH: case goog.events.KeyCodes.EQUALS: case goog.events.KeyCodes.FF_EQUALS: case goog.events.KeyCodes.COMMA: case goog.events.KeyCodes.PERIOD: case goog.events.KeyCodes.SLASH: case goog.events.KeyCodes.APOSTROPHE: case goog.events.KeyCodes.SINGLE_QUOTE: case goog.events.KeyCodes.OPEN_SQUARE_BRACKET: case goog.events.KeyCodes.BACKSLASH: case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET: return true; default: return false; } }; /** * Normalizes key codes from OS/Browser-specific value to the general one. * @param {number} keyCode The native key code. * @return {number} The normalized key code. */ goog.events.KeyCodes.normalizeKeyCode = function(keyCode) { if (goog.userAgent.GECKO) { return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode); } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) { return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode); } else { return keyCode; } }; /** * Normalizes key codes from their Gecko-specific value to the general one. * @param {number} keyCode The native key code. * @return {number} The normalized key code. */ goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) { switch (keyCode) { case goog.events.KeyCodes.FF_EQUALS: return goog.events.KeyCodes.EQUALS; case goog.events.KeyCodes.FF_SEMICOLON: return goog.events.KeyCodes.SEMICOLON; case goog.events.KeyCodes.FF_DASH: return goog.events.KeyCodes.DASH; case goog.events.KeyCodes.MAC_FF_META: return goog.events.KeyCodes.META; case goog.events.KeyCodes.WIN_KEY_FF_LINUX: return goog.events.KeyCodes.WIN_KEY; default: return keyCode; } }; /** * Normalizes key codes from their Mac WebKit-specific value to the general one. * @param {number} keyCode The native key code. * @return {number} The normalized key code. */ goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) { switch (keyCode) { case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93 return goog.events.KeyCodes.META; // 91 default: return keyCode; } };