/* eslint-disable */ /** * mapping of special keycodes to their corresponding keys * * everything in this dictionary cannot use keypress events * so it has to be here to map to the correct keycodes for * keyup/keydown events * * @type {Object} */ var _MAP = { '8': 'backspace', '9': 'tab', '13': 'enter', '16': 'shift', '17': 'ctrl', '18': 'alt', '20': 'capslock', '27': 'esc', '32': 'space', '33': 'pageup', '34': 'pagedown', '35': 'end', '36': 'home', '37': 'left', '38': 'up', '39': 'right', '40': 'down', '45': 'ins', '46': 'del', '91': 'meta', '93': 'meta', '224': 'meta' }; /** * mapping for special characters so they can support * * this dictionary is only used incase you want to bind a * keyup or keydown event to one of these keys * * @type {Object} */ var _KEYCODE_MAP = { '106': '*', '107': '+', '109': '-', '110': '.', '111' : '/', '186': ';', '187': '=', '188': ',', '189': '-', '190': '.', '191': '/', '192': '`', '219': '[', '220': '\\', '221': ']', '222': '\'' }; /** * this is a mapping of keys that require shift on a US keypad * back to the non shift equivelents * * this is so you can use keyup events with these keys * * note that this will only work reliably on US keyboards * * @type {Object} */ var _SHIFT_MAP = { '~': '`', '!': '1', '@': '2', '#': '3', '$': '4', '%': '5', '^': '6', '&': '7', '*': '8', '(': '9', ')': '0', '_': '-', '+': '=', ':': ';', '\"': '\'', '<': ',', '>': '.', '?': '/', '|': '\\' }; /** * this is a list of special strings you can use to map * to modifier keys when you specify your keyboard shortcuts * * @type {Object} */ var _SPECIAL_ALIASES = { 'option': 'alt', 'command': 'meta', 'return': 'enter', 'escape': 'esc', 'plus': '+', 'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl' }; /** * variable to store the flipped version of _MAP from above * needed to check if we should use keypress or not when no action * is specified * * @type {Object|undefined} */ var _REVERSE_SHIFT_MAP = {}; for (var key of Object.keys(_SHIFT_MAP)) { _REVERSE_SHIFT_MAP[_SHIFT_MAP[key]] = key; } /** * loop through the f keys, f1 to f19 and add them to the map * programatically */ for (var i = 1; i < 20; ++i) { _MAP[111 + i] = 'f' + i; } /** * loop through to map numbers on the numeric keypad */ for (i = 0; i <= 9; ++i) { _MAP[i + 96] = i; } function characterFromEvent(e) { // for keypress events we should return the character as is if (e.type == 'keypress') { var character = String.fromCharCode(e.which); // if the shift key is not pressed then it is safe to assume // that we want the character to be lowercase. this means if // you accidentally have caps lock on then your key bindings // will continue to work // // the only side effect that might not be desired is if you // bind something like 'A' cause you want to trigger an // event when capital A is pressed caps lock will no longer // trigger the event. shift+a will though. if (!e.shiftKey) { character = character.toLowerCase(); } return character; } // for non keypress events the special maps are needed if (_MAP[e.which]) { return _MAP[e.which]; } if (_KEYCODE_MAP[`${e.which}`]) { return _KEYCODE_MAP[`${e.which}`]; } // if it is not in the special map // with keydown and keyup events the character seems to always // come in as an uppercase character whether you are pressing shift // or not. we should make sure it is always lowercase for comparisons return String.fromCharCode(e.which).toLowerCase(); } /** * takes a key event and figures out what the modifiers are * * @param {Event} e * @returns {Array} */ function eventModifiers(e) { var modifiers = []; if (e.shiftKey) { modifiers.push('shift'); } if (e.altKey) { modifiers.push('alt'); } if (e.ctrlKey) { modifiers.push('ctrl'); } if (e.metaKey) { modifiers.push('meta'); } return modifiers; } function keyAndModifiersForEvent(e) { var eventKey = characterFromEvent(e); var eventMods = eventModifiers(e); if (_REVERSE_SHIFT_MAP[eventKey] && (eventMods.indexOf('shift') !== -1)) { eventKey = _REVERSE_SHIFT_MAP[eventKey]; eventMods = eventMods.filter((k) => k !== 'shift'); } return [eventKey, eventMods]; } module.exports = {characterFromEvent, eventModifiers, keyAndModifiersForEvent};