From acf7e7a298dd7bd91fce90dedda35bf2ba4f8cab Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Sat, 4 May 2019 01:27:48 +0800 Subject: [PATCH] released v3.6.4 --- dist/hotkeys.common.js | 250 +++++++++++++++++++----------------- dist/hotkeys.common.min.js | 4 +- dist/hotkeys.esm.js | 250 +++++++++++++++++++----------------- dist/hotkeys.js | 256 ++++++++++++++++++++----------------- dist/hotkeys.min.js | 4 +- 5 files changed, 409 insertions(+), 355 deletions(-) diff --git a/dist/hotkeys.common.js b/dist/hotkeys.common.js index d710bc0..b43aca9 100644 --- a/dist/hotkeys.common.js +++ b/dist/hotkeys.common.js @@ -1,5 +1,5 @@ /*! - * hotkeys-js v3.6.3 + * hotkeys-js v3.6.4 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies. * * Copyright (c) 2019 kenny wong @@ -10,36 +10,38 @@ 'use strict'; -var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; +var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; // 绑定事件 -// 绑定事件 function addEvent(object, event, method) { if (object.addEventListener) { object.addEventListener(event, method, false); } else if (object.attachEvent) { - object.attachEvent('on' + event, function () { + object.attachEvent("on".concat(event), function () { method(window.event); }); } -} +} // 修饰键转换成对应的键码 + -// 修饰键转换成对应的键码 function getMods(modifier, key) { var mods = key.slice(0, key.length - 1); + for (var i = 0; i < mods.length; i++) { mods[i] = modifier[mods[i].toLowerCase()]; - }return mods; -} + } + + return mods; +} // 处理传的key字符串转换成数组 + -// 处理传的key字符串转换成数组 function getKeys(key) { if (!key) key = ''; - key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等 + var keys = key.split(','); // 同时设置多个快捷键,以','分割 - var index = keys.lastIndexOf(''); - // 快捷键可能包含',',需特殊处理 + var index = keys.lastIndexOf(''); // 快捷键可能包含',',需特殊处理 + for (; index >= 0;) { keys[index - 1] += ','; keys.splice(index, 1); @@ -47,9 +49,9 @@ function getKeys(key) { } return keys; -} +} // 比较修饰键的数组 + -// 比较修饰键的数组 function compareArray(a1, a2) { var arr1 = a1.length >= a2.length ? a1 : a2; var arr2 = a1.length >= a2.length ? a2 : a1; @@ -58,15 +60,17 @@ function compareArray(a1, a2) { for (var i = 0; i < arr1.length; i++) { if (arr2.indexOf(arr1[i]) === -1) isIndex = false; } + return isIndex; } -var _keyMap = { // 特殊键 +var _keyMap = { + // 特殊键 backspace: 8, tab: 9, clear: 12, enter: 13, - return: 13, + "return": 13, esc: 27, escape: 27, space: 32, @@ -75,7 +79,7 @@ var _keyMap = { // 特殊键 right: 39, down: 40, del: 46, - delete: 46, + "delete": 46, ins: 45, insert: 45, home: 36, @@ -96,8 +100,8 @@ var _keyMap = { // 特殊键 ']': 221, '\\': 220 }; - -var _modifier = { // 修饰键 +var _modifier = { + // 修饰键 '⇧': 16, shift: 16, '⌥': 18, @@ -111,116 +115,125 @@ var _modifier = { // 修饰键 command: isff ? 224 : 91 }; var _downKeys = []; // 记录摁下的绑定键 + var modifierMap = { 16: 'shiftKey', 18: 'altKey', 17: 'ctrlKey' }; -var _mods = { 16: false, 18: false, 17: false }; -var _handlers = {}; +var _mods = { + 16: false, + 18: false, + 17: false +}; +var _handlers = {}; // F1~F12 特殊键 -// F1~F12 特殊键 for (var k = 1; k < 20; k++) { - _keyMap['f' + k] = 111 + k; -} + _keyMap["f".concat(k)] = 111 + k; +} // 兼容Firefox处理 + -// 兼容Firefox处理 modifierMap[isff ? 224 : 91] = 'metaKey'; _mods[isff ? 224 : 91] = false; var _scope = 'all'; // 默认热键范围 -var isBindElement = false; // 是否绑定节点 +var isBindElement = false; // 是否绑定节点 // 返回键码 + var code = function code(x) { return _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); -}; +}; // 设置获取当前范围(默认为'所有') + -// 设置获取当前范围(默认为'所有') function setScope(scope) { _scope = scope || 'all'; -} -// 获取当前范围 +} // 获取当前范围 + + function getScope() { return _scope || 'all'; -} -// 获取摁下绑定键的键值 +} // 获取摁下绑定键的键值 + + function getPressedKeyCodes() { return _downKeys.slice(0); -} +} // 表单控件控件判断 返回 Boolean + -// 表单控件控件判断 返回 Boolean function filter(event) { var target = event.target || event.srcElement; - var tagName = target.tagName; - // 忽略这些情况下快捷键无效 + var tagName = target.tagName; // 忽略这些情况下快捷键无效 return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || target.isContentEditable); -} +} // 判断摁下的键是否为某个键,返回true或者false + -// 判断摁下的键是否为某个键,返回true或者false function isPressed(keyCode) { if (typeof keyCode === 'string') { keyCode = code(keyCode); // 转换成键码 } + return _downKeys.indexOf(keyCode) !== -1; -} +} // 循环删除handlers中的所有 scope(范围) + -// 循环删除handlers中的所有 scope(范围) function deleteScope(scope, newScope) { - var handlers = void 0; - var i = void 0; + var handlers; + var i; // 没有指定scope,获取scope - // 没有指定scope,获取scope if (!scope) scope = getScope(); for (var key in _handlers) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; + for (i = 0; i < handlers.length;) { if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; } } - } + } // 如果scope被删除,将scope重置为all + - // 如果scope被删除,将scope重置为all if (getScope() === scope) setScope(newScope || 'all'); -} +} // 清除修饰键 + -// 清除修饰键 function clearModifier(event) { var key = event.keyCode || event.which || event.charCode; - var i = _downKeys.indexOf(key); - // 从列表中清除按压过的键 + var i = _downKeys.indexOf(key); // 从列表中清除按压过的键 + + if (i >= 0) { _downKeys.splice(i, 1); - } - // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + } // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + + if (event.key && event.key.toLowerCase() === 'meta') { _downKeys.splice(0, _downKeys.length); - } + } // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 + - // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 if (key === 93 || key === 224) key = 91; + if (key in _mods) { - _mods[key] = false; + _mods[key] = false; // 将修饰键重置为false - // 将修饰键重置为false for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = false; } } -} +} // 解除绑定某个范围的快捷键 + -// 解除绑定某个范围的快捷键 function unbind(key, scope, method) { var multipleKeys = getKeys(key); - var keys = void 0; + var keys; var mods = []; - var obj = void 0; - // 通过函数判断,是否解除绑定 + var obj; // 通过函数判断,是否解除绑定 // https://github.com/jaywcjlove/hotkeys/issues/44 + if (typeof scope === 'function') { method = scope; scope = 'all'; @@ -228,41 +241,34 @@ function unbind(key, scope, method) { for (var i = 0; i < multipleKeys.length; i++) { // 将组合快捷键拆分为数组 - keys = multipleKeys[i].split('+'); + keys = multipleKeys[i].split('+'); // 记录每个组合键中的修饰键的键码 返回数组 - // 记录每个组合键中的修饰键的键码 返回数组 - if (keys.length > 1) mods = getMods(_modifier, keys); + if (keys.length > 1) mods = getMods(_modifier, keys); // 获取除修饰键外的键值key - // 获取除修饰键外的键值key key = keys[keys.length - 1]; - key = key === '*' ? '*' : code(key); + key = key === '*' ? '*' : code(key); // 判断是否传入范围,没有就获取范围 - // 判断是否传入范围,没有就获取范围 - if (!scope) scope = getScope(); + if (!scope) scope = getScope(); // 如何key不在 _handlers 中返回不做处理 - // 如何key不在 _handlers 中返回不做处理 - if (!_handlers[key]) return; - - // 清空 handlers 中数据, + if (!_handlers[key]) return; // 清空 handlers 中数据, // 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的 + for (var r = 0; r < _handlers[key].length; r++) { - obj = _handlers[key][r]; - // 通过函数判断,是否解除绑定,函数相等直接返回 - var isMatchingMethod = method ? obj.method === method : true; + obj = _handlers[key][r]; // 通过函数判断,是否解除绑定,函数相等直接返回 + + var isMatchingMethod = method ? obj.method === method : true; // 判断是否在范围内并且键值相同 - // 判断是否在范围内并且键值相同 if (isMatchingMethod && obj.scope === scope && compareArray(obj.mods, mods)) { _handlers[key][r] = {}; } } } -} +} // 对监听对应快捷键的回调函数进行处理 + -// 对监听对应快捷键的回调函数进行处理 function eventHandler(event, handler, scope) { - var modifiersMatch = void 0; + var modifiersMatch; // 看它是否在当前范围 - // 看它是否在当前范围 if (handler.scope === scope || handler.scope === 'all') { // 检查是否匹配修饰符(如果有返回true) modifiersMatch = handler.mods.length > 0; @@ -271,9 +277,9 @@ function eventHandler(event, handler, scope) { if (Object.prototype.hasOwnProperty.call(_mods, y)) { if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) modifiersMatch = false; } - } + } // 调用处理程序,如果是修饰键不做处理 + - // 调用处理程序,如果是修饰键不做处理 if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') { if (handler.method(event, handler) === false) { if (event.preventDefault) event.preventDefault();else event.returnValue = false; @@ -282,64 +288,64 @@ function eventHandler(event, handler, scope) { } } } -} +} // 处理keydown事件 + -// 处理keydown事件 function dispatch(event) { var asterisk = _handlers['*']; - var key = event.keyCode || event.which || event.charCode; - - // 搜集绑定的键 - if (_downKeys.indexOf(key) === -1) _downKeys.push(key); + var key = event.keyCode || event.which || event.charCode; // 搜集绑定的键 - // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 + if (_downKeys.indexOf(key) === -1) _downKeys.push(key); // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 // Webkit左右command键值不一样 + if (key === 93 || key === 224) key = 91; if (key in _mods) { - _mods[key] = true; + _mods[key] = true; // 将特殊字符的key注册到 hotkeys 上 - // 将特殊字符的key注册到 hotkeys 上 for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = true; } if (!asterisk) return; - } + } // 将modifierMap里面的修饰键绑定到event中 + - // 将modifierMap里面的修饰键绑定到event中 for (var e in _mods) { if (Object.prototype.hasOwnProperty.call(_mods, e)) { _mods[e] = event[modifierMap[e]]; } - } + } // 表单控件过滤 默认表单控件不触发快捷键 + - // 表单控件过滤 默认表单控件不触发快捷键 - if (!hotkeys.filter.call(this, event)) return; + if (!hotkeys.filter.call(this, event)) return; // 获取范围 默认为all - // 获取范围 默认为all - var scope = getScope(); + var scope = getScope(); // 对任何快捷键都需要做的处理 - // 对任何快捷键都需要做的处理 if (asterisk) { for (var i = 0; i < asterisk.length; i++) { if (asterisk[i].scope === scope && (event.type === 'keydown' && !asterisk[i].keyup || event.type === 'keyup' && asterisk[i].keyup)) { eventHandler(event, asterisk[i], scope); } } - } - // key 不在_handlers中返回 + } // key 不在_handlers中返回 + + if (!(key in _handlers)) return; for (var _i = 0; _i < _handlers[key].length; _i++) { if (event.type === 'keydown' && _handlers[key][_i].keydown || event.type === 'keyup' && _handlers[key][_i].keyup) { if (_handlers[key][_i].key) { var keyShortcut = _handlers[key][_i].key.split('+'); + var _downKeysCurrent = []; // 记录当前按键键值 + for (var a = 0; a < keyShortcut.length; a++) { _downKeysCurrent.push(code(keyShortcut[a])); } + _downKeysCurrent = _downKeysCurrent.sort(); + if (_downKeysCurrent.join('') === _downKeys.sort().join('')) { // 找到处理内容 eventHandler(event, _handlers[key][_i], scope); @@ -351,41 +357,45 @@ function dispatch(event) { function hotkeys(key, option, method) { var keys = getKeys(key); // 需要处理的快捷键列表 + var mods = []; var scope = 'all'; // scope默认为all,所有范围都有效 + var element = document; // 快捷键事件绑定节点 + var i = 0; var keyup = false; - var keydown = true; + var keydown = true; // 对为设定范围的判断 - // 对为设定范围的判断 if (method === undefined && typeof option === 'function') { method = option; } if (Object.prototype.toString.call(option) === '[object Object]') { if (option.scope) scope = option.scope; // eslint-disable-line + if (option.element) element = option.element; // eslint-disable-line + if (option.keyup) keyup = option.keyup; // eslint-disable-line + if (option.keydown) keydown = option.keydown; // eslint-disable-line } - if (typeof option === 'string') scope = option; + if (typeof option === 'string') scope = option; // 对于每个快捷键进行处理 - // 对于每个快捷键进行处理 for (; i < keys.length; i++) { key = keys[i].split('+'); // 按键列表 - mods = []; - // 如果是组合快捷键取得组合快捷键 - if (key.length > 1) mods = getMods(_modifier, key); + mods = []; // 如果是组合快捷键取得组合快捷键 + + if (key.length > 1) mods = getMods(_modifier, key); // 将非修饰键转化为键码 - // 将非修饰键转化为键码 key = key[key.length - 1]; key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键 - // 判断key是否在_handlers中,不在就赋一个空数组 + if (!(key in _handlers)) _handlers[key] = []; + _handlers[key].push({ keyup: keyup, keydown: keydown, @@ -395,21 +405,25 @@ function hotkeys(key, option, method) { method: method, key: keys[i] }); - } - // 在全局document上设置快捷键 + } // 在全局document上设置快捷键 + + if (typeof element !== 'undefined' && !isBindElement) { isBindElement = true; + if (keydown) { addEvent(element, 'keydown', function (e) { dispatch(e); }); } - if (keyup) { - addEvent(element, 'keyup', function (e) { + + addEvent(element, 'keyup', function (e) { + if (keyup) { dispatch(e); - clearModifier(e); - }); - } + } + + clearModifier(e); + }); } } @@ -422,6 +436,7 @@ var _api = { filter: filter, unbind: unbind }; + for (var a in _api) { if (Object.prototype.hasOwnProperty.call(_api, a)) { hotkeys[a] = _api[a]; @@ -430,12 +445,15 @@ for (var a in _api) { if (typeof window !== 'undefined') { var _hotkeys = window.hotkeys; + hotkeys.noConflict = function (deep) { if (deep && window.hotkeys === hotkeys) { window.hotkeys = _hotkeys; } + return hotkeys; }; + window.hotkeys = hotkeys; } diff --git a/dist/hotkeys.common.min.js b/dist/hotkeys.common.min.js index 2836871..1a1904e 100644 --- a/dist/hotkeys.common.min.js +++ b/dist/hotkeys.common.min.js @@ -1,2 +1,2 @@ -/*! hotkeys-js v3.6.3 | MIT (c) 2019 kenny wong | http://jaywcjlove.github.io/hotkeys */ -"use strict";var isff="undefined"!=typeof navigator&&0 | http://jaywcjlove.github.io/hotkeys */ +"use strict";var isff="undefined"!=typeof navigator&&0 @@ -8,36 +8,38 @@ * Licensed under the MIT license. */ -var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; +var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; // 绑定事件 -// 绑定事件 function addEvent(object, event, method) { if (object.addEventListener) { object.addEventListener(event, method, false); } else if (object.attachEvent) { - object.attachEvent('on' + event, function () { + object.attachEvent("on".concat(event), function () { method(window.event); }); } -} +} // 修饰键转换成对应的键码 + -// 修饰键转换成对应的键码 function getMods(modifier, key) { var mods = key.slice(0, key.length - 1); + for (var i = 0; i < mods.length; i++) { mods[i] = modifier[mods[i].toLowerCase()]; - }return mods; -} + } + + return mods; +} // 处理传的key字符串转换成数组 + -// 处理传的key字符串转换成数组 function getKeys(key) { if (!key) key = ''; - key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等 + var keys = key.split(','); // 同时设置多个快捷键,以','分割 - var index = keys.lastIndexOf(''); - // 快捷键可能包含',',需特殊处理 + var index = keys.lastIndexOf(''); // 快捷键可能包含',',需特殊处理 + for (; index >= 0;) { keys[index - 1] += ','; keys.splice(index, 1); @@ -45,9 +47,9 @@ function getKeys(key) { } return keys; -} +} // 比较修饰键的数组 + -// 比较修饰键的数组 function compareArray(a1, a2) { var arr1 = a1.length >= a2.length ? a1 : a2; var arr2 = a1.length >= a2.length ? a2 : a1; @@ -56,15 +58,17 @@ function compareArray(a1, a2) { for (var i = 0; i < arr1.length; i++) { if (arr2.indexOf(arr1[i]) === -1) isIndex = false; } + return isIndex; } -var _keyMap = { // 特殊键 +var _keyMap = { + // 特殊键 backspace: 8, tab: 9, clear: 12, enter: 13, - return: 13, + "return": 13, esc: 27, escape: 27, space: 32, @@ -73,7 +77,7 @@ var _keyMap = { // 特殊键 right: 39, down: 40, del: 46, - delete: 46, + "delete": 46, ins: 45, insert: 45, home: 36, @@ -94,8 +98,8 @@ var _keyMap = { // 特殊键 ']': 221, '\\': 220 }; - -var _modifier = { // 修饰键 +var _modifier = { + // 修饰键 '⇧': 16, shift: 16, '⌥': 18, @@ -109,116 +113,125 @@ var _modifier = { // 修饰键 command: isff ? 224 : 91 }; var _downKeys = []; // 记录摁下的绑定键 + var modifierMap = { 16: 'shiftKey', 18: 'altKey', 17: 'ctrlKey' }; -var _mods = { 16: false, 18: false, 17: false }; -var _handlers = {}; +var _mods = { + 16: false, + 18: false, + 17: false +}; +var _handlers = {}; // F1~F12 特殊键 -// F1~F12 特殊键 for (var k = 1; k < 20; k++) { - _keyMap['f' + k] = 111 + k; -} + _keyMap["f".concat(k)] = 111 + k; +} // 兼容Firefox处理 + -// 兼容Firefox处理 modifierMap[isff ? 224 : 91] = 'metaKey'; _mods[isff ? 224 : 91] = false; var _scope = 'all'; // 默认热键范围 -var isBindElement = false; // 是否绑定节点 +var isBindElement = false; // 是否绑定节点 // 返回键码 + var code = function code(x) { return _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); -}; +}; // 设置获取当前范围(默认为'所有') + -// 设置获取当前范围(默认为'所有') function setScope(scope) { _scope = scope || 'all'; -} -// 获取当前范围 +} // 获取当前范围 + + function getScope() { return _scope || 'all'; -} -// 获取摁下绑定键的键值 +} // 获取摁下绑定键的键值 + + function getPressedKeyCodes() { return _downKeys.slice(0); -} +} // 表单控件控件判断 返回 Boolean + -// 表单控件控件判断 返回 Boolean function filter(event) { var target = event.target || event.srcElement; - var tagName = target.tagName; - // 忽略这些情况下快捷键无效 + var tagName = target.tagName; // 忽略这些情况下快捷键无效 return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || target.isContentEditable); -} +} // 判断摁下的键是否为某个键,返回true或者false + -// 判断摁下的键是否为某个键,返回true或者false function isPressed(keyCode) { if (typeof keyCode === 'string') { keyCode = code(keyCode); // 转换成键码 } + return _downKeys.indexOf(keyCode) !== -1; -} +} // 循环删除handlers中的所有 scope(范围) + -// 循环删除handlers中的所有 scope(范围) function deleteScope(scope, newScope) { - var handlers = void 0; - var i = void 0; + var handlers; + var i; // 没有指定scope,获取scope - // 没有指定scope,获取scope if (!scope) scope = getScope(); for (var key in _handlers) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; + for (i = 0; i < handlers.length;) { if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; } } - } + } // 如果scope被删除,将scope重置为all + - // 如果scope被删除,将scope重置为all if (getScope() === scope) setScope(newScope || 'all'); -} +} // 清除修饰键 + -// 清除修饰键 function clearModifier(event) { var key = event.keyCode || event.which || event.charCode; - var i = _downKeys.indexOf(key); - // 从列表中清除按压过的键 + var i = _downKeys.indexOf(key); // 从列表中清除按压过的键 + + if (i >= 0) { _downKeys.splice(i, 1); - } - // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + } // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + + if (event.key && event.key.toLowerCase() === 'meta') { _downKeys.splice(0, _downKeys.length); - } + } // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 + - // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 if (key === 93 || key === 224) key = 91; + if (key in _mods) { - _mods[key] = false; + _mods[key] = false; // 将修饰键重置为false - // 将修饰键重置为false for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = false; } } -} +} // 解除绑定某个范围的快捷键 + -// 解除绑定某个范围的快捷键 function unbind(key, scope, method) { var multipleKeys = getKeys(key); - var keys = void 0; + var keys; var mods = []; - var obj = void 0; - // 通过函数判断,是否解除绑定 + var obj; // 通过函数判断,是否解除绑定 // https://github.com/jaywcjlove/hotkeys/issues/44 + if (typeof scope === 'function') { method = scope; scope = 'all'; @@ -226,41 +239,34 @@ function unbind(key, scope, method) { for (var i = 0; i < multipleKeys.length; i++) { // 将组合快捷键拆分为数组 - keys = multipleKeys[i].split('+'); + keys = multipleKeys[i].split('+'); // 记录每个组合键中的修饰键的键码 返回数组 - // 记录每个组合键中的修饰键的键码 返回数组 - if (keys.length > 1) mods = getMods(_modifier, keys); + if (keys.length > 1) mods = getMods(_modifier, keys); // 获取除修饰键外的键值key - // 获取除修饰键外的键值key key = keys[keys.length - 1]; - key = key === '*' ? '*' : code(key); + key = key === '*' ? '*' : code(key); // 判断是否传入范围,没有就获取范围 - // 判断是否传入范围,没有就获取范围 - if (!scope) scope = getScope(); + if (!scope) scope = getScope(); // 如何key不在 _handlers 中返回不做处理 - // 如何key不在 _handlers 中返回不做处理 - if (!_handlers[key]) return; - - // 清空 handlers 中数据, + if (!_handlers[key]) return; // 清空 handlers 中数据, // 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的 + for (var r = 0; r < _handlers[key].length; r++) { - obj = _handlers[key][r]; - // 通过函数判断,是否解除绑定,函数相等直接返回 - var isMatchingMethod = method ? obj.method === method : true; + obj = _handlers[key][r]; // 通过函数判断,是否解除绑定,函数相等直接返回 + + var isMatchingMethod = method ? obj.method === method : true; // 判断是否在范围内并且键值相同 - // 判断是否在范围内并且键值相同 if (isMatchingMethod && obj.scope === scope && compareArray(obj.mods, mods)) { _handlers[key][r] = {}; } } } -} +} // 对监听对应快捷键的回调函数进行处理 + -// 对监听对应快捷键的回调函数进行处理 function eventHandler(event, handler, scope) { - var modifiersMatch = void 0; + var modifiersMatch; // 看它是否在当前范围 - // 看它是否在当前范围 if (handler.scope === scope || handler.scope === 'all') { // 检查是否匹配修饰符(如果有返回true) modifiersMatch = handler.mods.length > 0; @@ -269,9 +275,9 @@ function eventHandler(event, handler, scope) { if (Object.prototype.hasOwnProperty.call(_mods, y)) { if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) modifiersMatch = false; } - } + } // 调用处理程序,如果是修饰键不做处理 + - // 调用处理程序,如果是修饰键不做处理 if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') { if (handler.method(event, handler) === false) { if (event.preventDefault) event.preventDefault();else event.returnValue = false; @@ -280,64 +286,64 @@ function eventHandler(event, handler, scope) { } } } -} +} // 处理keydown事件 + -// 处理keydown事件 function dispatch(event) { var asterisk = _handlers['*']; - var key = event.keyCode || event.which || event.charCode; - - // 搜集绑定的键 - if (_downKeys.indexOf(key) === -1) _downKeys.push(key); + var key = event.keyCode || event.which || event.charCode; // 搜集绑定的键 - // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 + if (_downKeys.indexOf(key) === -1) _downKeys.push(key); // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 // Webkit左右command键值不一样 + if (key === 93 || key === 224) key = 91; if (key in _mods) { - _mods[key] = true; + _mods[key] = true; // 将特殊字符的key注册到 hotkeys 上 - // 将特殊字符的key注册到 hotkeys 上 for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = true; } if (!asterisk) return; - } + } // 将modifierMap里面的修饰键绑定到event中 + - // 将modifierMap里面的修饰键绑定到event中 for (var e in _mods) { if (Object.prototype.hasOwnProperty.call(_mods, e)) { _mods[e] = event[modifierMap[e]]; } - } + } // 表单控件过滤 默认表单控件不触发快捷键 + - // 表单控件过滤 默认表单控件不触发快捷键 - if (!hotkeys.filter.call(this, event)) return; + if (!hotkeys.filter.call(this, event)) return; // 获取范围 默认为all - // 获取范围 默认为all - var scope = getScope(); + var scope = getScope(); // 对任何快捷键都需要做的处理 - // 对任何快捷键都需要做的处理 if (asterisk) { for (var i = 0; i < asterisk.length; i++) { if (asterisk[i].scope === scope && (event.type === 'keydown' && !asterisk[i].keyup || event.type === 'keyup' && asterisk[i].keyup)) { eventHandler(event, asterisk[i], scope); } } - } - // key 不在_handlers中返回 + } // key 不在_handlers中返回 + + if (!(key in _handlers)) return; for (var _i = 0; _i < _handlers[key].length; _i++) { if (event.type === 'keydown' && _handlers[key][_i].keydown || event.type === 'keyup' && _handlers[key][_i].keyup) { if (_handlers[key][_i].key) { var keyShortcut = _handlers[key][_i].key.split('+'); + var _downKeysCurrent = []; // 记录当前按键键值 + for (var a = 0; a < keyShortcut.length; a++) { _downKeysCurrent.push(code(keyShortcut[a])); } + _downKeysCurrent = _downKeysCurrent.sort(); + if (_downKeysCurrent.join('') === _downKeys.sort().join('')) { // 找到处理内容 eventHandler(event, _handlers[key][_i], scope); @@ -349,41 +355,45 @@ function dispatch(event) { function hotkeys(key, option, method) { var keys = getKeys(key); // 需要处理的快捷键列表 + var mods = []; var scope = 'all'; // scope默认为all,所有范围都有效 + var element = document; // 快捷键事件绑定节点 + var i = 0; var keyup = false; - var keydown = true; + var keydown = true; // 对为设定范围的判断 - // 对为设定范围的判断 if (method === undefined && typeof option === 'function') { method = option; } if (Object.prototype.toString.call(option) === '[object Object]') { if (option.scope) scope = option.scope; // eslint-disable-line + if (option.element) element = option.element; // eslint-disable-line + if (option.keyup) keyup = option.keyup; // eslint-disable-line + if (option.keydown) keydown = option.keydown; // eslint-disable-line } - if (typeof option === 'string') scope = option; + if (typeof option === 'string') scope = option; // 对于每个快捷键进行处理 - // 对于每个快捷键进行处理 for (; i < keys.length; i++) { key = keys[i].split('+'); // 按键列表 - mods = []; - // 如果是组合快捷键取得组合快捷键 - if (key.length > 1) mods = getMods(_modifier, key); + mods = []; // 如果是组合快捷键取得组合快捷键 + + if (key.length > 1) mods = getMods(_modifier, key); // 将非修饰键转化为键码 - // 将非修饰键转化为键码 key = key[key.length - 1]; key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键 - // 判断key是否在_handlers中,不在就赋一个空数组 + if (!(key in _handlers)) _handlers[key] = []; + _handlers[key].push({ keyup: keyup, keydown: keydown, @@ -393,21 +403,25 @@ function hotkeys(key, option, method) { method: method, key: keys[i] }); - } - // 在全局document上设置快捷键 + } // 在全局document上设置快捷键 + + if (typeof element !== 'undefined' && !isBindElement) { isBindElement = true; + if (keydown) { addEvent(element, 'keydown', function (e) { dispatch(e); }); } - if (keyup) { - addEvent(element, 'keyup', function (e) { + + addEvent(element, 'keyup', function (e) { + if (keyup) { dispatch(e); - clearModifier(e); - }); - } + } + + clearModifier(e); + }); } } @@ -420,6 +434,7 @@ var _api = { filter: filter, unbind: unbind }; + for (var a in _api) { if (Object.prototype.hasOwnProperty.call(_api, a)) { hotkeys[a] = _api[a]; @@ -428,12 +443,15 @@ for (var a in _api) { if (typeof window !== 'undefined') { var _hotkeys = window.hotkeys; + hotkeys.noConflict = function (deep) { if (deep && window.hotkeys === hotkeys) { window.hotkeys = _hotkeys; } + return hotkeys; }; + window.hotkeys = hotkeys; } diff --git a/dist/hotkeys.js b/dist/hotkeys.js index 0ae3277..a3dbe84 100644 --- a/dist/hotkeys.js +++ b/dist/hotkeys.js @@ -1,5 +1,5 @@ /*! - * hotkeys-js v3.6.3 + * hotkeys-js v3.6.4 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies. * * Copyright (c) 2019 kenny wong @@ -11,39 +11,41 @@ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : - (global.hotkeys = factory()); -}(this, (function () { 'use strict'; + (global = global || self, global.hotkeys = factory()); +}(this, function () { 'use strict'; - var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; + var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; // 绑定事件 - // 绑定事件 function addEvent(object, event, method) { if (object.addEventListener) { object.addEventListener(event, method, false); } else if (object.attachEvent) { - object.attachEvent('on' + event, function () { + object.attachEvent("on".concat(event), function () { method(window.event); }); } - } + } // 修饰键转换成对应的键码 + - // 修饰键转换成对应的键码 function getMods(modifier, key) { var mods = key.slice(0, key.length - 1); + for (var i = 0; i < mods.length; i++) { mods[i] = modifier[mods[i].toLowerCase()]; - }return mods; - } + } + + return mods; + } // 处理传的key字符串转换成数组 + - // 处理传的key字符串转换成数组 function getKeys(key) { if (!key) key = ''; - key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等 + var keys = key.split(','); // 同时设置多个快捷键,以','分割 - var index = keys.lastIndexOf(''); - // 快捷键可能包含',',需特殊处理 + var index = keys.lastIndexOf(''); // 快捷键可能包含',',需特殊处理 + for (; index >= 0;) { keys[index - 1] += ','; keys.splice(index, 1); @@ -51,9 +53,9 @@ } return keys; - } + } // 比较修饰键的数组 + - // 比较修饰键的数组 function compareArray(a1, a2) { var arr1 = a1.length >= a2.length ? a1 : a2; var arr2 = a1.length >= a2.length ? a2 : a1; @@ -62,15 +64,17 @@ for (var i = 0; i < arr1.length; i++) { if (arr2.indexOf(arr1[i]) === -1) isIndex = false; } + return isIndex; } - var _keyMap = { // 特殊键 + var _keyMap = { + // 特殊键 backspace: 8, tab: 9, clear: 12, enter: 13, - return: 13, + "return": 13, esc: 27, escape: 27, space: 32, @@ -79,7 +83,7 @@ right: 39, down: 40, del: 46, - delete: 46, + "delete": 46, ins: 45, insert: 45, home: 36, @@ -100,8 +104,8 @@ ']': 221, '\\': 220 }; - - var _modifier = { // 修饰键 + var _modifier = { + // 修饰键 '⇧': 16, shift: 16, '⌥': 18, @@ -115,116 +119,125 @@ command: isff ? 224 : 91 }; var _downKeys = []; // 记录摁下的绑定键 + var modifierMap = { 16: 'shiftKey', 18: 'altKey', 17: 'ctrlKey' }; - var _mods = { 16: false, 18: false, 17: false }; - var _handlers = {}; + var _mods = { + 16: false, + 18: false, + 17: false + }; + var _handlers = {}; // F1~F12 特殊键 - // F1~F12 特殊键 for (var k = 1; k < 20; k++) { - _keyMap['f' + k] = 111 + k; - } + _keyMap["f".concat(k)] = 111 + k; + } // 兼容Firefox处理 + - // 兼容Firefox处理 modifierMap[isff ? 224 : 91] = 'metaKey'; _mods[isff ? 224 : 91] = false; var _scope = 'all'; // 默认热键范围 - var isBindElement = false; // 是否绑定节点 + var isBindElement = false; // 是否绑定节点 // 返回键码 + var code = function code(x) { return _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); - }; + }; // 设置获取当前范围(默认为'所有') + - // 设置获取当前范围(默认为'所有') function setScope(scope) { _scope = scope || 'all'; - } - // 获取当前范围 + } // 获取当前范围 + + function getScope() { return _scope || 'all'; - } - // 获取摁下绑定键的键值 + } // 获取摁下绑定键的键值 + + function getPressedKeyCodes() { return _downKeys.slice(0); - } + } // 表单控件控件判断 返回 Boolean + - // 表单控件控件判断 返回 Boolean function filter(event) { var target = event.target || event.srcElement; - var tagName = target.tagName; - // 忽略这些情况下快捷键无效 + var tagName = target.tagName; // 忽略这些情况下快捷键无效 return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || target.isContentEditable); - } + } // 判断摁下的键是否为某个键,返回true或者false + - // 判断摁下的键是否为某个键,返回true或者false function isPressed(keyCode) { if (typeof keyCode === 'string') { keyCode = code(keyCode); // 转换成键码 } + return _downKeys.indexOf(keyCode) !== -1; - } + } // 循环删除handlers中的所有 scope(范围) + - // 循环删除handlers中的所有 scope(范围) function deleteScope(scope, newScope) { - var handlers = void 0; - var i = void 0; + var handlers; + var i; // 没有指定scope,获取scope - // 没有指定scope,获取scope if (!scope) scope = getScope(); for (var key in _handlers) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; + for (i = 0; i < handlers.length;) { if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; } } - } + } // 如果scope被删除,将scope重置为all + - // 如果scope被删除,将scope重置为all if (getScope() === scope) setScope(newScope || 'all'); - } + } // 清除修饰键 + - // 清除修饰键 function clearModifier(event) { var key = event.keyCode || event.which || event.charCode; - var i = _downKeys.indexOf(key); - // 从列表中清除按压过的键 + var i = _downKeys.indexOf(key); // 从列表中清除按压过的键 + + if (i >= 0) { _downKeys.splice(i, 1); - } - // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + } // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题 + + if (event.key && event.key.toLowerCase() === 'meta') { _downKeys.splice(0, _downKeys.length); - } + } // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 + - // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除 if (key === 93 || key === 224) key = 91; + if (key in _mods) { - _mods[key] = false; + _mods[key] = false; // 将修饰键重置为false - // 将修饰键重置为false for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = false; } } - } + } // 解除绑定某个范围的快捷键 + - // 解除绑定某个范围的快捷键 function unbind(key, scope, method) { var multipleKeys = getKeys(key); - var keys = void 0; + var keys; var mods = []; - var obj = void 0; - // 通过函数判断,是否解除绑定 + var obj; // 通过函数判断,是否解除绑定 // https://github.com/jaywcjlove/hotkeys/issues/44 + if (typeof scope === 'function') { method = scope; scope = 'all'; @@ -232,41 +245,34 @@ for (var i = 0; i < multipleKeys.length; i++) { // 将组合快捷键拆分为数组 - keys = multipleKeys[i].split('+'); + keys = multipleKeys[i].split('+'); // 记录每个组合键中的修饰键的键码 返回数组 - // 记录每个组合键中的修饰键的键码 返回数组 - if (keys.length > 1) mods = getMods(_modifier, keys); + if (keys.length > 1) mods = getMods(_modifier, keys); // 获取除修饰键外的键值key - // 获取除修饰键外的键值key key = keys[keys.length - 1]; - key = key === '*' ? '*' : code(key); + key = key === '*' ? '*' : code(key); // 判断是否传入范围,没有就获取范围 - // 判断是否传入范围,没有就获取范围 - if (!scope) scope = getScope(); + if (!scope) scope = getScope(); // 如何key不在 _handlers 中返回不做处理 - // 如何key不在 _handlers 中返回不做处理 - if (!_handlers[key]) return; - - // 清空 handlers 中数据, + if (!_handlers[key]) return; // 清空 handlers 中数据, // 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的 + for (var r = 0; r < _handlers[key].length; r++) { - obj = _handlers[key][r]; - // 通过函数判断,是否解除绑定,函数相等直接返回 - var isMatchingMethod = method ? obj.method === method : true; + obj = _handlers[key][r]; // 通过函数判断,是否解除绑定,函数相等直接返回 + + var isMatchingMethod = method ? obj.method === method : true; // 判断是否在范围内并且键值相同 - // 判断是否在范围内并且键值相同 if (isMatchingMethod && obj.scope === scope && compareArray(obj.mods, mods)) { _handlers[key][r] = {}; } } } - } + } // 对监听对应快捷键的回调函数进行处理 + - // 对监听对应快捷键的回调函数进行处理 function eventHandler(event, handler, scope) { - var modifiersMatch = void 0; + var modifiersMatch; // 看它是否在当前范围 - // 看它是否在当前范围 if (handler.scope === scope || handler.scope === 'all') { // 检查是否匹配修饰符(如果有返回true) modifiersMatch = handler.mods.length > 0; @@ -275,9 +281,9 @@ if (Object.prototype.hasOwnProperty.call(_mods, y)) { if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) modifiersMatch = false; } - } + } // 调用处理程序,如果是修饰键不做处理 + - // 调用处理程序,如果是修饰键不做处理 if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') { if (handler.method(event, handler) === false) { if (event.preventDefault) event.preventDefault();else event.returnValue = false; @@ -286,64 +292,64 @@ } } } - } + } // 处理keydown事件 + - // 处理keydown事件 function dispatch(event) { var asterisk = _handlers['*']; - var key = event.keyCode || event.which || event.charCode; - - // 搜集绑定的键 - if (_downKeys.indexOf(key) === -1) _downKeys.push(key); + var key = event.keyCode || event.which || event.charCode; // 搜集绑定的键 - // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 + if (_downKeys.indexOf(key) === -1) _downKeys.push(key); // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致 // Webkit左右command键值不一样 + if (key === 93 || key === 224) key = 91; if (key in _mods) { - _mods[key] = true; + _mods[key] = true; // 将特殊字符的key注册到 hotkeys 上 - // 将特殊字符的key注册到 hotkeys 上 for (var k in _modifier) { if (_modifier[k] === key) hotkeys[k] = true; } if (!asterisk) return; - } + } // 将modifierMap里面的修饰键绑定到event中 + - // 将modifierMap里面的修饰键绑定到event中 for (var e in _mods) { if (Object.prototype.hasOwnProperty.call(_mods, e)) { _mods[e] = event[modifierMap[e]]; } - } + } // 表单控件过滤 默认表单控件不触发快捷键 + - // 表单控件过滤 默认表单控件不触发快捷键 - if (!hotkeys.filter.call(this, event)) return; + if (!hotkeys.filter.call(this, event)) return; // 获取范围 默认为all - // 获取范围 默认为all - var scope = getScope(); + var scope = getScope(); // 对任何快捷键都需要做的处理 - // 对任何快捷键都需要做的处理 if (asterisk) { for (var i = 0; i < asterisk.length; i++) { if (asterisk[i].scope === scope && (event.type === 'keydown' && !asterisk[i].keyup || event.type === 'keyup' && asterisk[i].keyup)) { eventHandler(event, asterisk[i], scope); } } - } - // key 不在_handlers中返回 + } // key 不在_handlers中返回 + + if (!(key in _handlers)) return; for (var _i = 0; _i < _handlers[key].length; _i++) { if (event.type === 'keydown' && _handlers[key][_i].keydown || event.type === 'keyup' && _handlers[key][_i].keyup) { if (_handlers[key][_i].key) { var keyShortcut = _handlers[key][_i].key.split('+'); + var _downKeysCurrent = []; // 记录当前按键键值 + for (var a = 0; a < keyShortcut.length; a++) { _downKeysCurrent.push(code(keyShortcut[a])); } + _downKeysCurrent = _downKeysCurrent.sort(); + if (_downKeysCurrent.join('') === _downKeys.sort().join('')) { // 找到处理内容 eventHandler(event, _handlers[key][_i], scope); @@ -355,41 +361,45 @@ function hotkeys(key, option, method) { var keys = getKeys(key); // 需要处理的快捷键列表 + var mods = []; var scope = 'all'; // scope默认为all,所有范围都有效 + var element = document; // 快捷键事件绑定节点 + var i = 0; var keyup = false; - var keydown = true; + var keydown = true; // 对为设定范围的判断 - // 对为设定范围的判断 if (method === undefined && typeof option === 'function') { method = option; } if (Object.prototype.toString.call(option) === '[object Object]') { if (option.scope) scope = option.scope; // eslint-disable-line + if (option.element) element = option.element; // eslint-disable-line + if (option.keyup) keyup = option.keyup; // eslint-disable-line + if (option.keydown) keydown = option.keydown; // eslint-disable-line } - if (typeof option === 'string') scope = option; + if (typeof option === 'string') scope = option; // 对于每个快捷键进行处理 - // 对于每个快捷键进行处理 for (; i < keys.length; i++) { key = keys[i].split('+'); // 按键列表 - mods = []; - // 如果是组合快捷键取得组合快捷键 - if (key.length > 1) mods = getMods(_modifier, key); + mods = []; // 如果是组合快捷键取得组合快捷键 + + if (key.length > 1) mods = getMods(_modifier, key); // 将非修饰键转化为键码 - // 将非修饰键转化为键码 key = key[key.length - 1]; key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键 - // 判断key是否在_handlers中,不在就赋一个空数组 + if (!(key in _handlers)) _handlers[key] = []; + _handlers[key].push({ keyup: keyup, keydown: keydown, @@ -399,21 +409,25 @@ method: method, key: keys[i] }); - } - // 在全局document上设置快捷键 + } // 在全局document上设置快捷键 + + if (typeof element !== 'undefined' && !isBindElement) { isBindElement = true; + if (keydown) { addEvent(element, 'keydown', function (e) { dispatch(e); }); } - if (keyup) { - addEvent(element, 'keyup', function (e) { + + addEvent(element, 'keyup', function (e) { + if (keyup) { dispatch(e); - clearModifier(e); - }); - } + } + + clearModifier(e); + }); } } @@ -426,6 +440,7 @@ filter: filter, unbind: unbind }; + for (var a in _api) { if (Object.prototype.hasOwnProperty.call(_api, a)) { hotkeys[a] = _api[a]; @@ -434,15 +449,18 @@ if (typeof window !== 'undefined') { var _hotkeys = window.hotkeys; + hotkeys.noConflict = function (deep) { if (deep && window.hotkeys === hotkeys) { window.hotkeys = _hotkeys; } + return hotkeys; }; + window.hotkeys = hotkeys; } return hotkeys; -}))); +})); diff --git a/dist/hotkeys.min.js b/dist/hotkeys.min.js index 4a7cfbf..0c07aa3 100644 --- a/dist/hotkeys.min.js +++ b/dist/hotkeys.min.js @@ -1,2 +1,2 @@ -/*! hotkeys-js v3.6.3 | MIT (c) 2019 kenny wong | http://jaywcjlove.github.io/hotkeys */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.hotkeys=t()}(this,function(){"use strict";var e="undefined"!=typeof navigator&&0 | http://jaywcjlove.github.io/hotkeys */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).hotkeys=t()}(this,function(){"use strict";var e="undefined"!=typeof navigator&&0