/**
* @license
* Copyright The Closure Library Authors.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Constant declarations for common key codes.
*
* @see ../demos/keyhandler.html
*/
goog.provide('goog.events.KeyCodes');
goog.require('goog.userAgent');
goog.requireType('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
// Firefox (Gecko) fires this for # on UK keyboards, rather than
// Shift+SINGLE_QUOTE.
FF_HASH: 163,
// Firefox (Gecko) fires this for ' (:) on JP keyboards, rather than
// SINGLE_QUOTE (US keyboard layout) or SEMICOLON (JP keyboard layout in
// chrome)
FF_JP_QUOTE: 58,
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) {
'use strict';
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;
}
if (goog.events.KeyCodes.isCharacterKey(e.keyCode)) {
return true;
}
switch (e.keyCode) {
// The following keys are quite harmless, even in combination with
// CTRL, ALT or SHIFT.
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) {
'use strict';
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.
// WebKit prior to 525 won't get this far so no need to check the user agent.
// Gecko doesn't need to use the held key for modifiers, it just checks the
// ctrl/meta/alt/shiftKey fields.
if (!goog.userAgent.GECKO) {
if (typeof opt_heldKeyCode === 'number') {
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+<somekey> 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:
if (goog.userAgent.GECKO) {
// Only Enter, Shift + Enter, Ctrl + Enter causes keypress event on
// Firefox.
if (opt_metaKey || opt_altKey) {
return false;
}
return !(opt_shiftKey && opt_ctrlKey);
} else {
return true;
}
case goog.events.KeyCodes.ESC:
return !(
goog.userAgent.WEBKIT || goog.userAgent.EDGE || goog.userAgent.GECKO);
}
// Gecko won't fire a keypress event even when the key is a character key if
// ctrl, meta or alt are pressed. In all other cases, a keypress event is
// only fired when the key is a character.
if (goog.userAgent.GECKO && (opt_ctrlKey || opt_altKey || opt_metaKey)) {
return false;
} else {
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) {
'use strict';
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:
case goog.events.KeyCodes.FF_HASH:
case goog.events.KeyCodes.FF_JP_QUOTE:
return true;
case goog.events.KeyCodes.FF_DASH:
return goog.userAgent.GECKO;
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) {
'use strict';
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) {
'use strict';
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) {
'use strict';
switch (keyCode) {
case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93
return goog.events.KeyCodes.META; // 91
default:
return keyCode;
}
};