Rebuild code.

pull/23/head
jaywcjlove 7 years ago
parent 4d45d40207
commit 717506f621

@ -0,0 +1,6 @@
{
"presets": [
"env",
"react"
]
}

4
.gitignore vendored

@ -1,5 +1,7 @@
npm-debug.log
node_modules/
node_modules
build
.cache
.idea/
package-lock.json
yarn.lock

@ -1,8 +1,9 @@
dist/hotkeys.js
dist/hotkeys.min.map
bower.json
.gitignore
.cache
scripts
test
build
package-lock.json
rollup.config.js
yarn.lock
src

@ -0,0 +1,8 @@
{
"modules": true,
"plugins": {
"autoprefixer": {
"grid": true
}
}
}

@ -103,7 +103,7 @@ hotkeys('shift+a,alt+d, w', function(e){
## 定义快捷键
```js
// 定义a快捷键
// 定义 F5 快捷键
hotkeys('f5', function(event,handler){
//event.srcElement: input
//event.target: input
@ -206,7 +206,7 @@ hotkeys.deleteScope('scope1');
**获取** 区域范围标记
```js
hotkeys.getScope('scope1');
hotkeys.getScope();
```
**设置** 区域范围标记

@ -1,24 +0,0 @@
{
"name": "hotkeys-js",
"description": "A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.",
"main": "dist/hotkeys.js",
"homepage": "https://github.com/jaywcjlove/hotkeys",
"authors": [
"jaywcjlove <398188662@qq.com>"
],
"license": "MIT",
"keywords": [
"key",
"keys",
"keybind",
"keyboard",
"shortcuts"
],
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

@ -1,52 +1,73 @@
//IE对indexOf方法的支持
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj) {
for (var i = 0; i < this.length; i++) if (this[i] === obj) return i;
'use strict';
return -1;
};
const 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 () { method(window.event); });
}
}
// IE对lastIndexOf方法的支持
if (!Array.prototype.lastIndexOf) {
Array.prototype.lastIndexOf = function (obj) {
for (var i = this.length - 1; i >= 0; i--) if (this[i] === obj) return i;
// 修饰键转换成对应的键码
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 -1;
// 处理传的key字符串转换成数组
function getKeys(key) {
if (!key) key = '';
var keys, index;
key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
keys = key.split(','); // 同时设置多个快捷键,以','分割
index = keys.lastIndexOf('');
// 快捷键可能包含',',需特殊处理
for (; index >= 0;) {
keys[index - 1] += ',';
keys.splice(index, 1);
index = keys.lastIndexOf('');
}
return keys;
}
var _api, // 对外API
isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false,
_keyMap = { // 特殊键
backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32,
left: 37, up: 38, right: 39, down: 40,
del: 46, 'delete': 46,
ins: 45, 'insert': 45,
home: 36, end: 35,
pageup: 33, pagedown: 34, '⇪': 20, 'capslock': 20,
',': 188, '.': 190, '/': 191,
'`': 192, '-': isff ? 173 : 189, '=': isff ? 61 : 187,
';': isff ? 59 : 186, '\'': 222,
'[': 219, ']': 221, '\\': 220
},
_scope = 'all', //默认热键范围
_modifier = { //修饰键
'⇧': 16, shift: 16,
'⌥': 18, alt: 18, option: 18,
'⌃': 17, ctrl: 17, control: 17,
'⌘': isff ? 224 : 91, cmd: isff ? 224 : 91, command: isff ? 224 : 91
},
_downKeys = [], // 记录摁下的绑定键
modifierMap = {
16: 'shiftKey',
18: 'altKey',
17: 'ctrlKey'
},
_mods = { 16: false, 18: false, 17: false },
_handlers = {};
const _keyMap = { // 特殊键
backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32,
left: 37, up: 38, right: 39, down: 40,
del: 46, 'delete': 46,
ins: 45, 'insert': 45,
home: 36, end: 35,
pageup: 33, pagedown: 34, '⇪': 20, 'capslock': 20,
',': 188, '.': 190, '/': 191,
'`': 192, '-': isff ? 173 : 189, '=': isff ? 61 : 187,
';': isff ? 59 : 186, '\'': 222,
'[': 219, ']': 221, '\\': 220
};
const _modifier = { //修饰键
'⇧': 16, shift: 16,
'⌥': 18, alt: 18, option: 18,
'⌃': 17, ctrl: 17, control: 17,
'⌘': isff ? 224 : 91, cmd: isff ? 224 : 91, command: isff ? 224 : 91
};
const _downKeys = []; // 记录摁下的绑定键
const modifierMap = {
16: 'shiftKey',
18: 'altKey',
17: 'ctrlKey'
};
const _mods = { 16: false, 18: false, 17: false };
const _handlers = {};
// F1~F12 特殊键
for (var k = 1; k < 20; k++) {
@ -57,22 +78,22 @@ for (var k = 1; k < 20; k++) {
modifierMap[isff ? 224 : 91] = 'metaKey';
_mods[isff ? 224 : 91] = false;
let _scope = 'all'; //默认热键范围
// 返回键码
function code(x) { return _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); }
const code = (x) => _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
// 设置获取当前范围(默认为'所有'
function setScope(scope) { _scope = scope || 'all'; }
// 获取当前范围
function getScope() { return _scope || 'all'; }
// 获取摁下绑定键的键值
function getPressedKeyCodes() { return _downKeys.slice(0); }
// 绑定事件
function addEvent(object, event, method) {
if (object.addEventListener) {
object.addEventListener(event, method, false);
} else if (object.attachEvent) {
object.attachEvent('on' + event, function () { method(window.event); });
}
// 表单控件控件判断 返回 Boolean
function filter(event) {
var tagName = (event.target || event.srcElement).tagName;
// 忽略这些标签情况下快捷键无效
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
}
// 判断摁下的键是否为某个键返回true或者false
@ -84,96 +105,55 @@ function isPressed(keyCode) {
return _downKeys.indexOf(keyCode) !== -1;
}
// 获取摁下绑定键的键值
function getPressedKeyCodes() { return _downKeys.slice(0); }
// 处理keydown事件
function dispatch(event) {
var key = event.keyCode || event.which || event.charCode,
scope,
asterisk = _handlers['*'];
// 搜集绑定的键
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;
// 将特殊字符的key注册到 hotkeys 上
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = true;
if (!asterisk) return;
}
// 将modifierMap里面的修饰键绑定到event中
for (var e in _mods) _mods[e] = event[modifierMap[e]];
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
let handlers;
let i;
// 表单控件过滤 默认表单控件不触发快捷键
if (!hotkeys.filter.call(this, event)) return;
// 没有指定scope获取scope
if (!scope) scope = getScope();
// 获取范围 默认为all
scope = getScope();
for (let key in _handlers) {
handlers = _handlers[key];
// 对任何快捷键都需要做的处理
if (asterisk) {
for (i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
for (i = 0; i < handlers.length;) {
if (handlers[i].scope === scope) handlers.splice(i, 1);
else i++;
}
}
// key 不在_handlers中返回
if (!(key in _handlers)) return;
for (var i = 0; i < _handlers[key].length; i++) {
// 找到处理内容
eventHandler(event, _handlers[key][i], scope);
}
// 如果scope被删除将scope重置为all
if (getScope() === scope) setScope(newScope || 'all');
}
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
var modifiersMatch;
// 清除修饰键
function clearModifier(event) {
let key = event.keyCode || event.which || event.charCode;
let i = _downKeys.indexOf(key);
// 看它是否在当前范围
if (handler.scope === scope || handler.scope === 'all') {
//检查是否匹配修饰符如果有返回true
modifiersMatch = handler.mods.length > 0;
// 从列表中清除按压过的键
if (i >= 0) _downKeys.splice(i, 1);
for (var y in _mods) {
if (
(!_mods[y] && handler.mods.indexOf(+y) > -1) ||
(_mods[y] && handler.mods.indexOf(+y) === -1)
) modifiersMatch = false;
}
// 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
if (key === 93 || key === 224) key = 91;
if (key in _mods) {
_mods[key] = 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;
if (event.stopPropagation) event.stopPropagation();
if (event.cancelBubble) event.cancelBubble = true;
}
}
// 将修饰键重置为false
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = false;
}
}
// 解除绑定某个范围的快捷键
function unbind(key, scope) {
var multipleKeys = getKeys(key),
let multipleKeys = getKeys(key),
keys,
mods = [],
obj;
for (var i = 0; i < multipleKeys.length; i++) {
for (let i = 0; i < multipleKeys.length; i++) {
// 将组合快捷键拆分为数组
keys = multipleKeys[i].split('+');
@ -192,7 +172,7 @@ function unbind(key, scope) {
// 清空 handlers 中数据,
// 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
for (var r = 0; r < _handlers[key].length; r++) {
for (let r = 0; r < _handlers[key].length; r++) {
obj = _handlers[key][r];
// 判断是否在范围内并且键值相同
@ -204,122 +184,107 @@ function unbind(key, scope) {
}
}
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
var key,
handlers,
i;
// 没有指定scope获取scope
if (!scope) scope = getScope();
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
let modifiersMatch;
for (key in _handlers) {
handlers = _handlers[key];
// 看它是否在当前范围
if (handler.scope === scope || handler.scope === 'all') {
//检查是否匹配修饰符如果有返回true
modifiersMatch = handler.mods.length > 0;
for (i = 0; i < handlers.length;) {
if (handlers[i].scope === scope) handlers.splice(i, 1);
else i++;
for (let y in _mods) {
if (
(!_mods[y] && handler.mods.indexOf(+y) > -1) ||
(_mods[y] && handler.mods.indexOf(+y) === -1)
) modifiersMatch = false;
}
}
// 如果scope被删除将scope重置为all
if (getScope() === scope) setScope(newScope || 'all');
}
//比较修饰键的数组
function compareArray(a1, a2) {
var arr1 = a1.length >= a2.length ? a1 : a2
var arr2 = a1.length >= a2.length ? a2 : a1
for (var i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) === -1) return 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;
if (event.stopPropagation) event.stopPropagation();
if (event.cancelBubble) event.cancelBubble = true;
}
}
}
return true;
}
// 表单控件控件判断 返回 Boolean
function filter(event) {
var tagName = (event.target || event.srcElement).tagName;
// 忽略这些标签情况下快捷键无效
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
}
// 修饰键转换成对应的键码
function getMods(key) {
var mods = key.slice(0, key.length - 1);
// 处理keydown事件
function dispatch(event) {
var key = event.keyCode || event.which || event.charCode,
scope,
asterisk = _handlers['*'];
for (var i = 0; i < mods.length; i++) mods[i] = _modifier[mods[i].toLowerCase()];
// 搜集绑定的键
if (_downKeys.indexOf(key) === -1) _downKeys.push(key);
return mods;
}
// Gecko(Firefox)的command键值224在Webkit(Chrome)中保持一致
// Webkit左右command键值不一样
if (key === 93 || key === 224) key = 91;
// 处理传的key字符串转换成数组
function getKeys(key) {
if (!key) key = '';
var keys, index;
if (key in _mods) {
_mods[key] = true;
key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
keys = key.split(','); // 同时设置多个快捷键,以','分割
index = keys.lastIndexOf('');
// 将特殊字符的key注册到 hotkeys 上
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = true;
// 快捷键可能包含',',需特殊处理
for (; index >= 0;) {
keys[index - 1] += ',';
keys.splice(index, 1);
index = keys.lastIndexOf('');
if (!asterisk) return;
}
return keys;
}
// 将modifierMap里面的修饰键绑定到event中
for (var e in _mods) _mods[e] = event[modifierMap[e]];
console.log('_downKeys:', _mods, _downKeys);
// 在全局document上设置快捷键
if (typeof document !== 'undefined') {
addEvent(document, "keydown", function (event) {
dispatch(event);
});
addEvent(document, "keyup", function (event) {
clearModifier(event);
});
}
// 表单控件过滤 默认表单控件不触发快捷键
if (!hotkeys.filter.call(this, event)) return;
// 清除修饰键
function clearModifier(event) {
var key = event.keyCode || event.which || event.charCode,
i = _downKeys.indexOf(key);
// 获取范围 默认为all
scope = getScope();
// 从列表中清除按压过的键
if (i >= 0) _downKeys.splice(i, 1);
// 对任何快捷键都需要做的处理
if (asterisk) {
for (i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
}
}
// 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
if (key === 93 || key === 224) key = 91;
if (key in _mods) {
_mods[key] = false;
// key 不在_handlers中返回
if (!(key in _handlers)) return;
// 将修饰键重置为false
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = false;
for (var i = 0; i < _handlers[key].length; i++) {
// 找到处理内容
eventHandler(event, _handlers[key][i], scope);
}
}
// 主体hotkeys函数
function hotkeys(key, scope, method) {
var keys = getKeys(key), // 需要处理的快捷键列表
mods = [],
i = 0;
let keys = getKeys(key); // 需要处理的快捷键列表
let mods = [];
let i = 0;
// 对为设定范围的判断
if (method === undefined) {
method = scope;
scope = 'all'; // scope默认为all所有范围都有效
}
// 对于每个快捷键进行处理
for (; i < keys.length; i++) {
key = keys[i].split('+'); // 按键列表
mods = [];
// 如果是组合快捷键取得组合快捷键
if (key.length > 1) mods = getMods(key);
if (key.length > 1) mods = getMods(_modifier, key);
// 将非修饰键转化为键码
key = key[key.length - 1];
@ -329,29 +294,31 @@ function hotkeys(key, scope, method) {
if (!(key in _handlers)) _handlers[key] = [];
_handlers[key].push({
scope, mods,
shortcut: keys[i],
scope: scope,
method: method,
key: keys[i],
mods: mods
});
}
}
_api = {
setScope: setScope,
getScope: getScope,
deleteScope: deleteScope,
getPressedKeyCodes: getPressedKeyCodes,
isPressed: isPressed,
filter: filter,
unbind: unbind
};
// 在全局document上设置快捷键
if (typeof document !== 'undefined') {
addEvent(document, "keydown", (e) => {
dispatch(e);
});
addEvent(document, "keyup", (e) => {
clearModifier(e);
});
}
const _api = { setScope, getScope, deleteScope, getPressedKeyCodes, isPressed, filter, unbind };
for (var a in _api) hotkeys[a] = _api[a];
if (typeof window !== 'undefined') {
var _hotkeys = window.hotkeys;
hotkeys.noConflict = function (deep) {
hotkeys.noConflict = (deep) => {
if (deep && window.hotkeys === hotkeys) {
window.hotkeys = _hotkeys;
}
@ -359,6 +326,5 @@ if (typeof window !== 'undefined') {
};
window.hotkeys = hotkeys;
}
window.hotkeys = hotkeys;
return hotkeys;
module.exports = hotkeys;

@ -0,0 +1,2 @@
/*! hotkeys-js v3.0.0 | MIT (c) 2018 kenny wang <wowohoo@qq.com> | */
"use strict";var isff="undefined"!=typeof navigator&&0<navigator.userAgent.toLowerCase().indexOf("firefox");function addEvent(e,o,t){e.addEventListener?e.addEventListener(o,t,!1):e.attachEvent&&e.attachEvent("on"+o,function(){t(window.event)})}function getMods(e,o){for(var t=o.slice(0,o.length-1),n=0;n<t.length;n++)t[n]=e[t[n].toLowerCase()];return t}function getKeys(e){var o,t;for(e||(e=""),t=(o=(e=e.replace(/\s/g,"")).split(",")).lastIndexOf("");0<=t;)o[t-1]+=",",o.splice(t,1),t=o.lastIndexOf("");return o}for(var _keyMap={backspace:8,tab:9,clear:12,enter:13,return:13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,delete:46,ins:45,insert:45,home:36,end:35,pageup:33,pagedown:34,"\u21ea":20,capslock:20,",":188,".":190,"/":191,"`":192,"-":isff?173:189,"=":isff?61:187,";":isff?59:186,"'":222,"[":219,"]":221,"\\":220},_modifier={"\u21e7":16,shift:16,"\u2325":18,alt:18,option:18,"\u2303":17,ctrl:17,control:17,"\u2318":isff?224:91,cmd:isff?224:91,command:isff?224:91},_downKeys=[],modifierMap={16:"shiftKey",18:"altKey",17:"ctrlKey"},_mods={16:!1,18:!1,17:!1},_handlers={},k=1;k<20;k++)_keyMap["f"+k]=111+k;modifierMap[isff?224:91]="metaKey",_mods[isff?224:91]=!1;var _scope="all",code=function(e){return _keyMap[e.toLowerCase()]||e.toUpperCase().charCodeAt(0)};function setScope(e){_scope=e||"all"}function getScope(){return _scope||"all"}function getPressedKeyCodes(){return _downKeys.slice(0)}function filter(e){var o=(e.target||e.srcElement).tagName;return!("INPUT"===o||"SELECT"===o||"TEXTAREA"===o)}function isPressed(e){return"string"==typeof e&&(e=code(e)),-1!==_downKeys.indexOf(e)}function deleteScope(e,o){var t=void 0,n=void 0;for(var s in e||(e=getScope()),_handlers)for(t=_handlers[s],n=0;n<t.length;)t[n].scope===e?t.splice(n,1):n++;getScope()===e&&setScope(o||"all")}function clearModifier(e){var o=e.keyCode||e.which||e.charCode,t=_downKeys.indexOf(o);if(t<0||_downKeys.splice(t,1),93!==o&&224!==o||(o=91),o in _mods)for(var n in _mods[o]=!1,_modifier)_modifier[n]===o&&(hotkeys[n]=!1)}function unbind(e,o){for(var t=getKeys(e),n=void 0,s=[],r=void 0,d=0;d<t.length;d++){if(1<(n=t[d].split("+")).length&&(s=getMods(n)),e="*"===(e=n[n.length-1])?"*":code(e),o||(o=getScope()),!_handlers[e])return;for(var i=0;i<_handlers[e].length;i++)(r=_handlers[e][i]).scope===o&&compareArray(r.mods,s)&&(_handlers[e][i]={})}}function eventHandler(e,o,t){var n=void 0;if(o.scope===t||"all"===o.scope){for(var s in n=0<o.mods.length,_mods)(!_mods[s]&&-1<o.mods.indexOf(+s)||_mods[s]&&-1===o.mods.indexOf(+s))&&(n=!1);(0!==o.mods.length||_mods[16]||_mods[18]||_mods[17]||_mods[91])&&!n&&"*"!==o.shortcut||!1===o.method(e,o)&&(e.preventDefault?e.preventDefault():e.returnValue=!1,e.stopPropagation&&e.stopPropagation(),e.cancelBubble&&(e.cancelBubble=!0))}}function dispatch(e){var o,t=e.keyCode||e.which||e.charCode,n=_handlers["*"];if(-1===_downKeys.indexOf(t)&&_downKeys.push(t),93!==t&&224!==t||(t=91),t in _mods){for(var s in _mods[t]=!0,_modifier)_modifier[s]===t&&(hotkeys[s]=!0);if(!n)return}for(var r in _mods)_mods[r]=e[modifierMap[r]];if(hotkeys.filter.call(this,e)){if(o=getScope(),n)for(d=0;d<n.length;d++)n[d].scope===o&&eventHandler(e,n[d],o);if(t in _handlers)for(var d=0;d<_handlers[t].length;d++)eventHandler(e,_handlers[t][d],o)}}function hotkeys(e,o,t){var n=getKeys(e),s=[],r=0;for(void 0===t&&(t=o,o="all");r<n.length;r++)s=[],1<(e=n[r].split("+")).length&&(s=getMods(_modifier,e)),(e="*"===(e=e[e.length-1])?"*":code(e))in _handlers||(_handlers[e]=[]),_handlers[e].push({scope:o,mods:s,shortcut:n[r],method:t,key:n[r]})}"undefined"!=typeof document&&(addEvent(document,"keydown",function(e){dispatch(e)}),addEvent(document,"keyup",function(e){clearModifier(e)}));var _api={setScope:setScope,getScope:getScope,deleteScope:deleteScope,getPressedKeyCodes:getPressedKeyCodes,isPressed:isPressed,filter:filter,unbind:unbind};for(var a in _api)hotkeys[a]=_api[a];if("undefined"!=typeof window){var _hotkeys=window.hotkeys;hotkeys.noConflict=function(e){return e&&window.hotkeys===hotkeys&&(window.hotkeys=_hotkeys),hotkeys},window.hotkeys=hotkeys}module.exports=hotkeys;

672
dist/hotkeys.js vendored

@ -1,350 +1,336 @@
/*!
* hotkeys-js v2.0.9
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
*
* Copyright (c) 2018 kenny wang <wowohoo@qq.com>
* https://github.com/jaywcjlove/hotkeys.git
*
* Licensed under the MIT license.
*/
(function(f) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f();
} else if (typeof define === "function" && define.amd) {
define([], f);
} else {
var g;
if (typeof window !== "undefined") {
g = window;
} else if (typeof global !== "undefined") {
g = global;
} else if (typeof self !== "undefined") {
g = self;
} else {
g = this;
}
g.hotkeys = f();
(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';
const 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 () { 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;
}
// 处理传的key字符串转换成数组
function getKeys(key) {
if (!key) key = '';
var keys, index;
key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
keys = key.split(','); // 同时设置多个快捷键,以','分割
index = keys.lastIndexOf('');
// 快捷键可能包含',',需特殊处理
for (; index >= 0;) {
keys[index - 1] += ',';
keys.splice(index, 1);
index = keys.lastIndexOf('');
}
return keys;
}
const _keyMap = { // 特殊键
backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32,
left: 37, up: 38, right: 39, down: 40,
del: 46, 'delete': 46,
ins: 45, 'insert': 45,
home: 36, end: 35,
pageup: 33, pagedown: 34, '⇪': 20, 'capslock': 20,
',': 188, '.': 190, '/': 191,
'`': 192, '-': isff ? 173 : 189, '=': isff ? 61 : 187,
';': isff ? 59 : 186, '\'': 222,
'[': 219, ']': 221, '\\': 220
};
const _modifier = { //修饰键
'⇧': 16, shift: 16,
'⌥': 18, alt: 18, option: 18,
'⌃': 17, ctrl: 17, control: 17,
'⌘': isff ? 224 : 91, cmd: isff ? 224 : 91, command: isff ? 224 : 91
};
const _downKeys = []; // 记录摁下的绑定键
const modifierMap = {
16: 'shiftKey',
18: 'altKey',
17: 'ctrlKey'
};
const _mods = { 16: false, 18: false, 17: false };
const _handlers = {};
// F1~F12 特殊键
for (var k = 1; k < 20; k++) {
_keyMap['f' + k] = 111 + k;
}
// 兼容Firefox处理
modifierMap[isff ? 224 : 91] = 'metaKey';
_mods[isff ? 224 : 91] = false;
let _scope = 'all'; //默认热键范围
// 返回键码
const code = (x) => _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
// 设置获取当前范围(默认为'所有'
function setScope(scope) { _scope = scope || 'all'; }
// 获取当前范围
function getScope() { return _scope || 'all'; }
// 获取摁下绑定键的键值
function getPressedKeyCodes() { return _downKeys.slice(0); }
// 表单控件控件判断 返回 Boolean
function filter(event) {
var tagName = (event.target || event.srcElement).tagName;
// 忽略这些标签情况下快捷键无效
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
}
// 判断摁下的键是否为某个键返回true或者false
function isPressed(keyCode) {
if (typeof (keyCode) === 'string') {
keyCode = code(keyCode); // 转换成键码
}
return _downKeys.indexOf(keyCode) !== -1;
}
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
let handlers;
let i;
// 没有指定scope获取scope
if (!scope) scope = getScope();
for (let key in _handlers) {
handlers = _handlers[key];
for (i = 0; i < handlers.length;) {
if (handlers[i].scope === scope) handlers.splice(i, 1);
else i++;
}
})(function() {
var define, module, exports;
//IE对indexOf方法的支持
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(obj) {
for (var i = 0; i < this.length; i++) if (this[i] === obj) return i;
return -1;
};
}
// 如果scope被删除将scope重置为all
if (getScope() === scope) setScope(newScope || 'all');
}
// 清除修饰键
function clearModifier(event) {
let key = event.keyCode || event.which || event.charCode;
let i = _downKeys.indexOf(key);
// 从列表中清除按压过的键
if (i >= 0) _downKeys.splice(i, 1);
// 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
if (key === 93 || key === 224) key = 91;
if (key in _mods) {
_mods[key] = false;
// 将修饰键重置为false
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = false;
}
}
// 解除绑定某个范围的快捷键
function unbind(key, scope) {
let multipleKeys = getKeys(key),
keys,
mods = [],
obj;
for (let i = 0; i < multipleKeys.length; i++) {
// 将组合快捷键拆分为数组
keys = multipleKeys[i].split('+');
// 记录每个组合键中的修饰键的键码 返回数组
if (keys.length > 1) mods = getMods(keys);
// 获取除修饰键外的键值key
key = keys[keys.length - 1];
key = key === '*' ? '*' : code(key);
// 判断是否传入范围,没有就获取范围
if (!scope) scope = getScope();
// 如何key不在 _handlers 中返回不做处理
if (!_handlers[key]) return;
// 清空 handlers 中数据,
// 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
for (let r = 0; r < _handlers[key].length; r++) {
obj = _handlers[key][r];
// 判断是否在范围内并且键值相同
if (
obj.scope === scope &&
compareArray(obj.mods, mods)
) _handlers[key][r] = {};
}
// IE对lastIndexOf方法的支持
if (!Array.prototype.lastIndexOf) {
Array.prototype.lastIndexOf = function(obj) {
for (var i = this.length - 1; i >= 0; i--) if (this[i] === obj) return i;
return -1;
};
}
}
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
let modifiersMatch;
// 看它是否在当前范围
if (handler.scope === scope || handler.scope === 'all') {
//检查是否匹配修饰符如果有返回true
modifiersMatch = handler.mods.length > 0;
for (let y in _mods) {
if (
(!_mods[y] && handler.mods.indexOf(+y) > -1) ||
(_mods[y] && handler.mods.indexOf(+y) === -1)
) modifiersMatch = false;
}
var _api, // 对外API
isff = typeof navigator !== "undefined" ? navigator.userAgent.toLowerCase().indexOf("firefox") > 0 : false, _keyMap = {
// 特殊键
backspace: 8,
tab: 9,
clear: 12,
enter: 13,
return: 13,
esc: 27,
escape: 27,
space: 32,
left: 37,
up: 38,
right: 39,
down: 40,
del: 46,
delete: 46,
ins: 45,
insert: 45,
home: 36,
end: 35,
pageup: 33,
pagedown: 34,
"⇪": 20,
capslock: 20,
",": 188,
".": 190,
"/": 191,
"`": 192,
"-": isff ? 173 : 189,
"=": isff ? 61 : 187,
";": isff ? 59 : 186,
"'": 222,
"[": 219,
"]": 221,
"\\": 220
}, _scope = "all", //默认热键范围
_modifier = {
//修饰键
"⇧": 16,
shift: 16,
"⌥": 18,
alt: 18,
option: 18,
"⌃": 17,
ctrl: 17,
control: 17,
"⌘": isff ? 224 : 91,
cmd: isff ? 224 : 91,
command: isff ? 224 : 91
}, _downKeys = [], // 记录摁下的绑定键
modifierMap = {
16: "shiftKey",
18: "altKey",
17: "ctrlKey"
}, _mods = {
16: false,
18: false,
17: false
}, _handlers = {};
// F1~F12 特殊键
for (var k = 1; k < 20; k++) {
_keyMap["f" + k] = 111 + k;
// 调用处理程序,如果是修饰键不做处理
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;
if (event.stopPropagation) event.stopPropagation();
if (event.cancelBubble) event.cancelBubble = true;
}
}
// 兼容Firefox处理
modifierMap[isff ? 224 : 91] = "metaKey";
_mods[isff ? 224 : 91] = false;
// 返回键码
function code(x) {
return _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
}
}
// 处理keydown事件
function dispatch(event) {
var key = event.keyCode || event.which || event.charCode,
scope,
asterisk = _handlers['*'];
// 搜集绑定的键
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;
// 将特殊字符的key注册到 hotkeys 上
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = true;
if (!asterisk) return;
}
// 将modifierMap里面的修饰键绑定到event中
for (var e in _mods) _mods[e] = event[modifierMap[e]];
console.log('_downKeys:', _mods, _downKeys);
// 表单控件过滤 默认表单控件不触发快捷键
if (!hotkeys.filter.call(this, event)) return;
// 获取范围 默认为all
scope = getScope();
// 对任何快捷键都需要做的处理
if (asterisk) {
for (i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
}
// 设置获取当前范围(默认为'所有'
function setScope(scope) {
_scope = scope || "all";
}
// key 不在_handlers中返回
if (!(key in _handlers)) return;
for (var i = 0; i < _handlers[key].length; i++) {
// 找到处理内容
eventHandler(event, _handlers[key][i], scope);
}
}
function hotkeys(key, scope, method) {
let keys = getKeys(key); // 需要处理的快捷键列表
let mods = [];
let i = 0;
// 对为设定范围的判断
if (method === undefined) {
method = scope;
scope = 'all'; // scope默认为all所有范围都有效
}
// 对于每个快捷键进行处理
for (; i < keys.length; i++) {
key = keys[i].split('+'); // 按键列表
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({
scope, mods,
shortcut: keys[i],
method: method,
key: keys[i],
});
}
}
// 在全局document上设置快捷键
if (typeof document !== 'undefined') {
addEvent(document, "keydown", (e) => {
dispatch(e);
});
addEvent(document, "keyup", (e) => {
clearModifier(e);
});
}
const _api = { setScope, getScope, deleteScope, getPressedKeyCodes, isPressed, filter, unbind };
for (var a in _api) hotkeys[a] = _api[a];
if (typeof window !== 'undefined') {
var _hotkeys = window.hotkeys;
hotkeys.noConflict = (deep) => {
if (deep && window.hotkeys === hotkeys) {
window.hotkeys = _hotkeys;
}
// 获取当前范围
function getScope() {
return _scope || "all";
}
// 绑定事件
function addEvent(object, event, method) {
if (object.addEventListener) {
object.addEventListener(event, method, false);
} else if (object.attachEvent) {
object.attachEvent("on" + event, function() {
method(window.event);
});
}
}
// 判断摁下的键是否为某个键返回true或者false
function isPressed(keyCode) {
if (typeof keyCode === "string") {
keyCode = code(keyCode);
// 转换成键码
}
return _downKeys.indexOf(keyCode) !== -1;
}
// 获取摁下绑定键的键值
function getPressedKeyCodes() {
return _downKeys.slice(0);
}
// 处理keydown事件
function dispatch(event) {
var key = event.keyCode || event.which || event.charCode, scope, asterisk = _handlers["*"];
// 搜集绑定的键
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;
// 将特殊字符的key注册到 hotkeys 上
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = true;
if (!asterisk) return;
}
// 将modifierMap里面的修饰键绑定到event中
for (var e in _mods) _mods[e] = event[modifierMap[e]];
// 表单控件过滤 默认表单控件不触发快捷键
if (!hotkeys.filter.call(this, event)) return;
// 获取范围 默认为all
scope = getScope();
// 对任何快捷键都需要做的处理
if (asterisk) {
for (i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
}
}
// key 不在_handlers中返回
if (!(key in _handlers)) return;
for (var i = 0; i < _handlers[key].length; i++) {
// 找到处理内容
eventHandler(event, _handlers[key][i], scope);
}
}
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
var modifiersMatch;
// 看它是否在当前范围
if (handler.scope === scope || handler.scope === "all") {
//检查是否匹配修饰符如果有返回true
modifiersMatch = handler.mods.length > 0;
for (var y in _mods) {
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;
if (event.stopPropagation) event.stopPropagation();
if (event.cancelBubble) event.cancelBubble = true;
}
}
}
}
// 解除绑定某个范围的快捷键
function unbind(key, scope) {
var multipleKeys = getKeys(key), keys, mods = [], obj;
for (var i = 0; i < multipleKeys.length; i++) {
// 将组合快捷键拆分为数组
keys = multipleKeys[i].split("+");
// 记录每个组合键中的修饰键的键码 返回数组
if (keys.length > 1) mods = getMods(keys);
// 获取除修饰键外的键值key
key = keys[keys.length - 1];
key = key === "*" ? "*" : code(key);
// 判断是否传入范围,没有就获取范围
if (!scope) scope = getScope();
// 如何key不在 _handlers 中返回不做处理
if (!_handlers[key]) return;
// 清空 handlers 中数据,
// 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
for (var r = 0; r < _handlers[key].length; r++) {
obj = _handlers[key][r];
// 判断是否在范围内并且键值相同
if (obj.scope === scope && compareArray(obj.mods, mods)) _handlers[key][r] = {};
}
}
}
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
var key, handlers, i;
// 没有指定scope获取scope
if (!scope) scope = getScope();
for (key in _handlers) {
handlers = _handlers[key];
for (i = 0; i < handlers.length; ) {
if (handlers[i].scope === scope) handlers.splice(i, 1); else i++;
}
}
// 如果scope被删除将scope重置为all
if (getScope() === scope) setScope(newScope || "all");
}
//比较修饰键的数组
function compareArray(a1, a2) {
var arr1 = a1.length >= a2.length ? a1 : a2;
var arr2 = a1.length >= a2.length ? a2 : a1;
for (var i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) === -1) return false;
}
return true;
}
// 表单控件控件判断 返回 Boolean
function filter(event) {
var tagName = (event.target || event.srcElement).tagName;
// 忽略这些标签情况下快捷键无效
return !(tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA");
}
// 修饰键转换成对应的键码
function getMods(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;
}
// 处理传的key字符串转换成数组
function getKeys(key) {
if (!key) key = "";
var keys, index;
key = key.replace(/\s/g, "");
// 匹配任何空白字符,包括空格、制表符、换页符等等
keys = key.split(",");
// 同时设置多个快捷键,以','分割
index = keys.lastIndexOf("");
// 快捷键可能包含',',需特殊处理
for (;index >= 0; ) {
keys[index - 1] += ",";
keys.splice(index, 1);
index = keys.lastIndexOf("");
}
return keys;
}
// 在全局document上设置快捷键
if (typeof document !== "undefined") {
addEvent(document, "keydown", function(event) {
dispatch(event);
});
addEvent(document, "keyup", function(event) {
clearModifier(event);
});
}
// 清除修饰键
function clearModifier(event) {
var key = event.keyCode || event.which || event.charCode, i = _downKeys.indexOf(key);
// 从列表中清除按压过的键
if (i >= 0) _downKeys.splice(i, 1);
// 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
if (key === 93 || key === 224) key = 91;
if (key in _mods) {
_mods[key] = false;
// 将修饰键重置为false
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = false;
}
}
// 主体hotkeys函数
function hotkeys(key, scope, method) {
var keys = getKeys(key), // 需要处理的快捷键列表
mods = [], i = 0;
// 对为设定范围的判断
if (method === undefined) {
method = scope;
scope = "all";
// scope默认为all所有范围都有效
}
// 对于每个快捷键进行处理
for (;i < keys.length; i++) {
key = keys[i].split("+");
// 按键列表
mods = [];
// 如果是组合快捷键取得组合快捷键
if (key.length > 1) mods = getMods(key);
// 将非修饰键转化为键码
key = key[key.length - 1];
key = key === "*" ? "*" : code(key);
// *表示匹配所有快捷键
// 判断key是否在_handlers中不在就赋一个空数组
if (!(key in _handlers)) _handlers[key] = [];
_handlers[key].push({
shortcut: keys[i],
scope: scope,
method: method,
key: keys[i],
mods: mods
});
}
}
_api = {
setScope: setScope,
getScope: getScope,
deleteScope: deleteScope,
getPressedKeyCodes: getPressedKeyCodes,
isPressed: isPressed,
filter: filter,
unbind: unbind
};
for (var a in _api) hotkeys[a] = _api[a];
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;
}
window.hotkeys = hotkeys;
return hotkeys;
});
};
window.hotkeys = hotkeys;
}
return hotkeys;
})));

@ -1,3 +1,2 @@
/*! hotkeys-js v2.0.9 | MIT (c) 2018 kenny wang <wowohoo@qq.com> | https://github.com/jaywcjlove/hotkeys.git */
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).hotkeys=e()}}(function(){Array.prototype.indexOf||(Array.prototype.indexOf=function(e){for(var n=0;n<this.length;n++)if(this[n]===e)return n;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(e){for(var n=this.length-1;n>=0;n--)if(this[n]===e)return n;return-1});for(var e,n="undefined"!=typeof navigator&&navigator.userAgent.toLowerCase().indexOf("firefox")>0,t={backspace:8,tab:9,clear:12,enter:13,return:13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,delete:46,ins:45,insert:45,home:36,end:35,pageup:33,pagedown:34,"⇪":20,capslock:20,",":188,".":190,"/":191,"`":192,"-":n?173:189,"=":n?61:187,";":n?59:186,"'":222,"[":219,"]":221,"\\":220},o="all",r={"⇧":16,shift:16,"⌥":18,alt:18,option:18,"⌃":17,ctrl:17,control:17,"⌘":n?224:91,cmd:n?224:91,command:n?224:91},i=[],f={16:"shiftKey",18:"altKey",17:"ctrlKey"},a={16:!1,18:!1,17:!1},l={},d=1;d<20;d++)t["f"+d]=111+d;function s(e){return t[e.toLowerCase()]||e.toUpperCase().charCodeAt(0)}function c(e){o=e||"all"}function u(){return o||"all"}function p(e,n,t){e.addEventListener?e.addEventListener(n,t,!1):e.attachEvent&&e.attachEvent("on"+n,function(){t(window.event)})}function h(e,n,t){var o;if(n.scope===t||"all"===n.scope){for(var r in o=n.mods.length>0,a)(!a[r]&&n.mods.indexOf(+r)>-1||a[r]&&-1===n.mods.indexOf(+r))&&(o=!1);(0!==n.mods.length||a[16]||a[18]||a[17]||a[91])&&!o&&"*"!==n.shortcut||!1===n.method(e,n)&&(e.preventDefault?e.preventDefault():e.returnValue=!1,e.stopPropagation&&e.stopPropagation(),e.cancelBubble&&(e.cancelBubble=!0))}}function g(e,n){for(var t=e.length>=n.length?e:n,o=e.length>=n.length?n:e,r=0;r<t.length;r++)if(-1===o.indexOf(t[r]))return!1;return!0}function y(e){for(var n=e.slice(0,e.length-1),t=0;t<n.length;t++)n[t]=r[n[t].toLowerCase()];return n}function v(e){var n,t;for(e||(e=""),t=(n=(e=e.replace(/\s/g,"")).split(",")).lastIndexOf("");t>=0;)n[t-1]+=",",n.splice(t,1),t=n.lastIndexOf("");return n}function w(e,n,t){var o=v(e),r=[],i=0;for(void 0===t&&(t=n,n="all");i<o.length;i++)r=[],(e=o[i].split("+")).length>1&&(r=y(e)),(e="*"===(e=e[e.length-1])?"*":s(e))in l||(l[e]=[]),l[e].push({shortcut:o[i],scope:n,method:t,key:o[i],mods:r})}for(var m in f[n?224:91]="metaKey",a[n?224:91]=!1,"undefined"!=typeof document&&(p(document,"keydown",function(e){!function(e){var n,t=e.keyCode||e.which||e.charCode,o=l["*"];if(-1===i.indexOf(t)&&i.push(t),93!==t&&224!==t||(t=91),t in a){for(var d in a[t]=!0,r)r[d]===t&&(w[d]=!0);if(!o)return}for(var s in a)a[s]=e[f[s]];if(w.filter.call(this,e)){if(n=u(),o)for(c=0;c<o.length;c++)o[c].scope===n&&h(e,o[c],n);if(t in l)for(var c=0;c<l[t].length;c++)h(e,l[t][c],n)}}(e)}),p(document,"keyup",function(e){!function(e){var n=e.keyCode||e.which||e.charCode,t=i.indexOf(n);t>=0&&i.splice(t,1);93!==n&&224!==n||(n=91);if(n in a)for(var o in a[n]=!1,r)r[o]===n&&(w[o]=!1)}(e)})),e={setScope:c,getScope:u,deleteScope:function(e,n){var t,o,r;for(t in e||(e=u()),l)for(o=l[t],r=0;r<o.length;)o[r].scope===e?o.splice(r,1):r++;u()===e&&c(n||"all")},getPressedKeyCodes:function(){return i.slice(0)},isPressed:function(e){return"string"==typeof e&&(e=s(e)),-1!==i.indexOf(e)},filter:function(e){var n=(e.target||e.srcElement).tagName;return!("INPUT"===n||"SELECT"===n||"TEXTAREA"===n)},unbind:function(e,n){for(var t,o,r=v(e),i=[],f=0;f<r.length;f++){if((t=r[f].split("+")).length>1&&(i=y(t)),e="*"===(e=t[t.length-1])?"*":s(e),n||(n=u()),!l[e])return;for(var a=0;a<l[e].length;a++)(o=l[e][a]).scope===n&&g(o.mods,i)&&(l[e][a]={})}}})w[m]=e[m];if("undefined"!=typeof window){var x=window.hotkeys;w.noConflict=function(e){return e&&window.hotkeys===w&&(window.hotkeys=x),w},window.hotkeys=w}return window.hotkeys=w,w});
/*! hotkeys-js v3.0.0 | MIT (c) 2018 kenny wang <wowohoo@qq.com> | */
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.hotkeys=n()}(this,function(){"use strict";var e="undefined"!=typeof navigator&&0<navigator.userAgent.toLowerCase().indexOf("firefox");function n(e,n,t){e.addEventListener?e.addEventListener(n,t,!1):e.attachEvent&&e.attachEvent("on"+n,function(){t(window.event)})}function c(e,n){for(var t=n.slice(0,n.length-1),o=0;o<t.length;o++)t[o]=e[t[o].toLowerCase()];return t}function d(e){var n,t;for(e||(e=""),t=(n=(e=e.replace(/\s/g,"")).split(",")).lastIndexOf("");0<=t;)n[t-1]+=",",n.splice(t,1),t=n.lastIndexOf("");return n}for(var t={backspace:8,tab:9,clear:12,enter:13,return:13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,delete:46,ins:45,insert:45,home:36,end:35,pageup:33,pagedown:34,"\u21ea":20,capslock:20,",":188,".":190,"/":191,"`":192,"-":e?173:189,"=":e?61:187,";":e?59:186,"'":222,"[":219,"]":221,"\\":220},a={"\u21e7":16,shift:16,"\u2325":18,alt:18,option:18,"\u2303":17,ctrl:17,control:17,"\u2318":e?224:91,cmd:e?224:91,command:e?224:91},s=[],l={16:"shiftKey",18:"altKey",17:"ctrlKey"},u={16:!1,18:!1,17:!1},p={},o=1;o<20;o++)t["f"+o]=111+o;l[e?224:91]="metaKey",u[e?224:91]=!1;var r="all",h=function(e){return t[e.toLowerCase()]||e.toUpperCase().charCodeAt(0)};function i(e){r=e||"all"}function v(){return r||"all"}function g(e,n,t){var o=void 0;if(n.scope===t||"all"===n.scope){for(var r in o=0<n.mods.length,u)(!u[r]&&-1<n.mods.indexOf(+r)||u[r]&&-1===n.mods.indexOf(+r))&&(o=!1);(0!==n.mods.length||u[16]||u[18]||u[17]||u[91])&&!o&&"*"!==n.shortcut||!1===n.method(e,n)&&(e.preventDefault?e.preventDefault():e.returnValue=!1,e.stopPropagation&&e.stopPropagation(),e.cancelBubble&&(e.cancelBubble=!0))}}function y(e,n,t){var o=d(e),r=[],i=0;for(void 0===t&&(t=n,n="all");i<o.length;i++)r=[],1<(e=o[i].split("+")).length&&(r=c(a,e)),(e="*"===(e=e[e.length-1])?"*":h(e))in p||(p[e]=[]),p[e].push({scope:n,mods:r,shortcut:o[i],method:t,key:o[i]})}"undefined"!=typeof document&&(n(document,"keydown",function(e){!function(e){var n,t=e.keyCode||e.which||e.charCode,o=p["*"];if(-1===s.indexOf(t)&&s.push(t),93!==t&&224!==t||(t=91),t in u){for(var r in u[t]=!0,a)a[r]===t&&(y[r]=!0);if(!o)return}for(var i in u)u[i]=e[l[i]];if(y.filter.call(this,e)){if(n=v(),o)for(f=0;f<o.length;f++)o[f].scope===n&&g(e,o[f],n);if(t in p)for(var f=0;f<p[t].length;f++)g(e,p[t][f],n)}}(e)}),n(document,"keyup",function(e){!function(e){var n=e.keyCode||e.which||e.charCode,t=s.indexOf(n);if(t<0||s.splice(t,1),93!==n&&224!==n||(n=91),n in u)for(var o in u[n]=!1,a)a[o]===n&&(y[o]=!1)}(e)}));var f={setScope:i,getScope:v,deleteScope:function(e,n){var t=void 0,o=void 0;for(var r in e||(e=v()),p)for(t=p[r],o=0;o<t.length;)t[o].scope===e?t.splice(o,1):o++;v()===e&&i(n||"all")},getPressedKeyCodes:function(){return s.slice(0)},isPressed:function(e){return"string"==typeof e&&(e=h(e)),-1!==s.indexOf(e)},filter:function(e){var n=(e.target||e.srcElement).tagName;return!("INPUT"===n||"SELECT"===n||"TEXTAREA"===n)},unbind:function(e,n){for(var t=d(e),o=void 0,r=[],i=void 0,f=0;f<t.length;f++){if(1<(o=t[f].split("+")).length&&(r=c(o)),e="*"===(e=o[o.length-1])?"*":h(e),n||(n=v()),!p[e])return;for(var a=0;a<p[e].length;a++)(i=p[e][a]).scope===n&&compareArray(i.mods,r)&&(p[e][a]={})}}};for(var m in f)y[m]=f[m];if("undefined"!=typeof window){var w=window.hotkeys;y.noConflict=function(e){return e&&window.hotkeys===y&&(window.hotkeys=w),y},window.hotkeys=y}return y});

File diff suppressed because one or more lines are too long

@ -0,0 +1,6 @@
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/hotkeys.common.min.js');
} else {
module.exports = require('./dist/hotkeys.common.js');
}

@ -1,16 +1,14 @@
{
"name": "hotkeys-js",
"version": "2.0.9",
"description": "A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.",
"author": "kenny wang <wowohoo@qq.com>",
"main": "dist/hotkeys.min.js",
"version": "3.0.0",
"main": "index.js",
"scripts": {
"build:test": "browserify test/hotkeys.js | uglifyjs --compress --mangle > test/hotkeys.test.js",
"build:min": "umd hotkeys src/hotkeys.js | uglifyjs -mc | bannerjs -o > dist/hotkeys.min.js",
"build:dist": "umd hotkeys src/hotkeys.js | bannerjs -m | uglifyjs -b beautify=true --comments 'all' > dist/hotkeys.js ",
"build": "npm run build:min && npm run build:dist",
"test": "npm run build:test && ssr",
"watch": "onchange 'src/hotkeys.js' -v -- npm run build "
"build": "node scripts/build.js",
"watch": "node scripts/watch.js",
"pretest": "npm run build",
"doc:dev": "NODE_ENV=development parcel website/index.html --out-dir build/website --no-cache",
"doc:build": "NODE_ENV=production parcel build website/index.html --out-dir build/website --public-url ./ --no-cache"
},
"keywords": [
"hotkey",
@ -23,21 +21,31 @@
"shortcuts",
"keypress"
],
"repository": {
"type": "git",
"url": "https://github.com/jaywcjlove/hotkeys.git"
},
"author": "kenny wong <wowohoo@qq.com>",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"autoprefixer": "^8.1.0",
"babel-core": "^6.26.0",
"babel-plugin-external-helpers": "^6.22.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"bannerjs": "^1.0.5",
"browserify": "^14.4.0",
"jsdom": "^11.1.0",
"onchange": "^3.2.1",
"ssr": "^1.1.1",
"tape": "^4.8.0",
"tape-dom": "0.0.12",
"uglify-js": "^3.0.27",
"umd": "^3.0.1"
},
"license": "MIT",
"dependencies": {}
"classnames": "^2.2.5",
"colors-cli": "^1.0.13",
"highlight.js": "^9.12.0",
"less": "^3.0.1",
"parcel-bundler": "^1.6.2",
"parcel-plugin-markdown-string": "^1.3.1",
"postcss-modules": "^1.1.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-markdown": "^3.3.0",
"rollup": "^0.57.0",
"rollup-plugin-babel": "^3.0.3",
"rollup-plugin-commonjs": "^9.1.0",
"rollup-plugin-node-resolve": "^3.2.0",
"uglify-js": "^3.3.15",
"zlib": "^1.0.5"
}
}

@ -0,0 +1,101 @@
const fs = require('fs');
const path = require('path');
const rollup = require('rollup');
const babel = require('rollup-plugin-babel');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const banner = require('bannerjs');
const zlib = require('zlib');
const pkg = require('../package.json');
const uglify = require('uglify-js');
require('colors-cli/toxic');
// see below for details on the options
const inputOptions = {
input: 'src/main.js',
plugins: [
resolve(), // so Rollup can find `ms`
commonjs(), // so Rollup can convert `ms` to an ES module
babel({
exclude: 'node_modules/**' // 只编译我们的源代码
})
]
};
const outputOptions = {
file: pkg.unpkg,
sourcemap: false,
format: 'umd',
name: 'hotkeys',
banner: banner.multibanner()
};
async function build() {
// create a bundle
const bundle = await rollup.rollup(inputOptions);
const uglifyOption = {
'compress': {
'pure_getters': true,
'unsafe': true,
'unsafe_comps': true,
'warnings': false
},
'output': {
'ascii_only': true,
}
}
// console.log(bundle.imports); // an array of external dependencies
// console.log(bundle.exports); // an array of names exported by the entry point
// console.log(bundle.modules); // an array of module objects
const umd = await bundle.generate({
format: 'umd',
name: 'hotkeys',
banner: banner.multibanner()
});
const umdMinified = banner.onebanner() + '\n' + uglify.minify(umd.code, uglifyOption).code;
const common = await bundle.generate({
format: 'cjs',
name: 'hotkeys',
banner: banner.multibanner()
});
const commonMinified = banner.onebanner() + '\n' + uglify.minify(common.code, uglifyOption).code;
write('dist/hotkeys.js', umd.code)
.then(() => write('dist/hotkeys.min.js', umdMinified, true))
.then(() => write('dist/hotkeys.common.js', common.code))
.then(() => write('dist/hotkeys.common.min.js', commonMinified, true));
}
build();
function write(dest, code, zip) {
return new Promise(function (resolve, reject) {
function report(extra) {
console.log((path.relative(process.cwd(), dest)).blue_bt + ' ' + getSize(code).green_bt + (extra || ''))
resolve()
}
if (!fs.existsSync(path.dirname(dest))) {
fs.mkdirSync(path.dirname(dest));
}
fs.writeFile(dest, code, function (err) {
if (err) return reject(err)
if (zip) {
zlib.gzip(code, (err, zipped) => {
if (err) return reject(err)
report(' (gzipped: ' + getSize(zipped).green_bt + ')')
})
} else {
report()
}
})
})
}
function getSize(code) {
return (code.length / 1024).toFixed(2) + 'kb'
}

@ -0,0 +1,35 @@
const path = require('path');
const rollup = require('rollup');
const pkg = require('../package.json');
require('colors-cli/toxic');
const watchOptions = {
input: 'src/main.js',
output: [
{ file: 'dist/hotkeys.common.js', name: 'hotkeys', format: 'cjs' },
{ file: 'dist/hotkeys.js', name: 'hotkeys', format: 'umd' }
]
};
const watcher = rollup.watch(watchOptions);
watcher.on('event', event => {
// event.code can be one of:
// START — the watcher is (re)starting
// BUNDLE_START — building an individual bundle
// BUNDLE_END — finished building a bundle
// END — finished building all bundles
// ERROR — encountered an error while bundling
// FATAL — encountered an unrecoverable error
if (event.code === 'BUNDLE_END') {
event.output.map(function (item) {
console.log('bundles '.x39 + `${event.input}${item.replace(process.cwd() + path.sep, '')}`.blue_bt);
})
console.log(`duration ${event.duration}ms\n`.green)
} else if (event.code === 'END') {
console.log('waiting for changes... ');
}
});
// stop watching
// watcher.close();

@ -0,0 +1,8 @@
{
"presets": [
["env", {
"modules": false
}]
],
"plugins": ["external-helpers"]
}

@ -0,0 +1,254 @@
import { addEvent, getMods, getKeys } from './utils';
import { _keyMap, _modifier, _downKeys, modifierMap, _mods, _handlers } from './var';
let _scope = 'all'; //默认热键范围
// 返回键码
const code = (x) => _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
// 设置获取当前范围(默认为'所有'
function setScope(scope) { _scope = scope || 'all'; }
// 获取当前范围
function getScope() { return _scope || 'all'; }
// 获取摁下绑定键的键值
function getPressedKeyCodes() { return _downKeys.slice(0); }
// 表单控件控件判断 返回 Boolean
function filter(event) {
var tagName = (event.target || event.srcElement).tagName;
// 忽略这些标签情况下快捷键无效
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
}
// 判断摁下的键是否为某个键返回true或者false
function isPressed(keyCode) {
if (typeof (keyCode) === 'string') {
keyCode = code(keyCode); // 转换成键码
}
return _downKeys.indexOf(keyCode) !== -1;
}
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
let handlers;
let i;
// 没有指定scope获取scope
if (!scope) scope = getScope();
for (let key in _handlers) {
handlers = _handlers[key];
for (i = 0; i < handlers.length;) {
if (handlers[i].scope === scope) handlers.splice(i, 1);
else i++;
}
}
// 如果scope被删除将scope重置为all
if (getScope() === scope) setScope(newScope || 'all');
}
// 清除修饰键
function clearModifier(event) {
let key = event.keyCode || event.which || event.charCode;
let i = _downKeys.indexOf(key);
// 从列表中清除按压过的键
if (i >= 0) _downKeys.splice(i, 1);
// 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
if (key === 93 || key === 224) key = 91;
if (key in _mods) {
_mods[key] = false;
// 将修饰键重置为false
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = false;
}
}
// 解除绑定某个范围的快捷键
function unbind(key, scope) {
let multipleKeys = getKeys(key),
keys,
mods = [],
obj;
for (let i = 0; i < multipleKeys.length; i++) {
// 将组合快捷键拆分为数组
keys = multipleKeys[i].split('+');
// 记录每个组合键中的修饰键的键码 返回数组
if (keys.length > 1) mods = getMods(keys);
// 获取除修饰键外的键值key
key = keys[keys.length - 1];
key = key === '*' ? '*' : code(key);
// 判断是否传入范围,没有就获取范围
if (!scope) scope = getScope();
// 如何key不在 _handlers 中返回不做处理
if (!_handlers[key]) return;
// 清空 handlers 中数据,
// 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
for (let r = 0; r < _handlers[key].length; r++) {
obj = _handlers[key][r];
// 判断是否在范围内并且键值相同
if (
obj.scope === scope &&
compareArray(obj.mods, mods)
) _handlers[key][r] = {};
}
}
}
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
let modifiersMatch;
// 看它是否在当前范围
if (handler.scope === scope || handler.scope === 'all') {
//检查是否匹配修饰符如果有返回true
modifiersMatch = handler.mods.length > 0;
for (let y in _mods) {
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;
if (event.stopPropagation) event.stopPropagation();
if (event.cancelBubble) event.cancelBubble = true;
}
}
}
}
// 处理keydown事件
function dispatch(event) {
var key = event.keyCode || event.which || event.charCode,
scope,
asterisk = _handlers['*'];
// 搜集绑定的键
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;
// 将特殊字符的key注册到 hotkeys 上
for (var k in _modifier) if (_modifier[k] === key) hotkeys[k] = true;
if (!asterisk) return;
}
// 将modifierMap里面的修饰键绑定到event中
for (var e in _mods) _mods[e] = event[modifierMap[e]];
console.log('_downKeys:', _mods, _downKeys);
// 表单控件过滤 默认表单控件不触发快捷键
if (!hotkeys.filter.call(this, event)) return;
// 获取范围 默认为all
scope = getScope();
// 对任何快捷键都需要做的处理
if (asterisk) {
for (i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
}
}
// key 不在_handlers中返回
if (!(key in _handlers)) return;
for (var i = 0; i < _handlers[key].length; i++) {
// 找到处理内容
eventHandler(event, _handlers[key][i], scope);
}
}
function hotkeys(key, scope, method) {
let keys = getKeys(key); // 需要处理的快捷键列表
let mods = [];
let i = 0;
// 对为设定范围的判断
if (method === undefined) {
method = scope;
scope = 'all'; // scope默认为all所有范围都有效
}
// 对于每个快捷键进行处理
for (; i < keys.length; i++) {
key = keys[i].split('+'); // 按键列表
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({
scope, mods,
shortcut: keys[i],
method: method,
key: keys[i],
});
}
}
// 在全局document上设置快捷键
if (typeof document !== 'undefined') {
addEvent(document, "keydown", (e) => {
dispatch(e);
});
addEvent(document, "keyup", (e) => {
clearModifier(e);
});
}
const _api = { setScope, getScope, deleteScope, getPressedKeyCodes, isPressed, filter, unbind };
for (var a in _api) hotkeys[a] = _api[a];
if (typeof window !== 'undefined') {
var _hotkeys = window.hotkeys;
hotkeys.noConflict = (deep) => {
if (deep && window.hotkeys === hotkeys) {
window.hotkeys = _hotkeys;
}
return hotkeys;
};
window.hotkeys = hotkeys;
}
export default hotkeys;

@ -0,0 +1,45 @@
const 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 () { 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;
}
// 处理传的key字符串转换成数组
function getKeys(key) {
if (!key) key = '';
var keys, index;
key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
keys = key.split(','); // 同时设置多个快捷键,以','分割
index = keys.lastIndexOf('');
// 快捷键可能包含',',需特殊处理
for (; index >= 0;) {
keys[index - 1] += ',';
keys.splice(index, 1);
index = keys.lastIndexOf('');
}
return keys;
}
export {
isff,
getMods,
getKeys,
addEvent
}

@ -0,0 +1,50 @@
import { isff } from './utils';
const _keyMap = { // 特殊键
backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32,
left: 37, up: 38, right: 39, down: 40,
del: 46, 'delete': 46,
ins: 45, 'insert': 45,
home: 36, end: 35,
pageup: 33, pagedown: 34, '⇪': 20, 'capslock': 20,
',': 188, '.': 190, '/': 191,
'`': 192, '-': isff ? 173 : 189, '=': isff ? 61 : 187,
';': isff ? 59 : 186, '\'': 222,
'[': 219, ']': 221, '\\': 220
}
const _modifier = { //修饰键
'⇧': 16, shift: 16,
'⌥': 18, alt: 18, option: 18,
'⌃': 17, ctrl: 17, control: 17,
'⌘': isff ? 224 : 91, cmd: isff ? 224 : 91, command: isff ? 224 : 91
};
const _downKeys = []; // 记录摁下的绑定键
const modifierMap = {
16: 'shiftKey',
18: 'altKey',
17: 'ctrlKey'
};
const _mods = { 16: false, 18: false, 17: false };
const _handlers = {};
// F1~F12 特殊键
for (var k = 1; k < 20; k++) {
_keyMap['f' + k] = 111 + k;
}
// 兼容Firefox处理
modifierMap[isff ? 224 : 91] = 'metaKey';
_mods[isff ? 224 : 91] = false;
export {
_keyMap,
_modifier,
_downKeys,
modifierMap,
_mods,
_handlers,
}

@ -1,305 +0,0 @@
var tape = require('tape');
require('tape-dom')(tape);
var hotkeys = require('../dist/hotkeys.js');
var isff = navigator.userAgent.toLowerCase().indexOf('firefox') > 0;
// 模拟键盘摁键
// http://output.jsbin.com/awenaq/3
function __triggerKeyboardEvent(el, keyCode, opt) {
var eventObj = document.createEventObject ?
document.createEventObject() : document.createEvent("Events");
if (eventObj.initEvent) {
eventObj.initEvent("keydown", true, true);
}
eventObj.keyCode = keyCode;
eventObj.which = keyCode;
if (opt) {
for (var a in opt) {
eventObj[a] = opt[a];
}
}
el.dispatchEvent ? el.dispatchEvent(eventObj) : el.fireEvent("onkeydown", eventObj);
}
tape('hotkeys 单元测试', function (t) {
hotkeys('w', function(e){
t.equal(e.keyCode, 87, '单个按键 w keyCode == 87');
});
__triggerKeyboardEvent(document.body, 87);
hotkeys('enter', function(e){
t.equal(e.keyCode, 13, '单个特殊键按键 enterenter验证 keyCode == 13');
});
hotkeys('return', function(e){
t.equal(e.keyCode, 13, '单个特殊键按键 returnreturn验证 keyCode == 13');
});
__triggerKeyboardEvent(document.body, 13);
hotkeys('space', function(e){
t.equal(e.keyCode, 32, '单个特殊键按键 spacespace验证 keyCode == 32');
});
__triggerKeyboardEvent(document.body, 32);
hotkeys('backspace', function(e){
t.equal(e.keyCode, 8, '单个特殊键按键 backspacebackspace 验证 keyCode == 8');
});
__triggerKeyboardEvent(document.body, 8);
hotkeys('tab', function(e){
t.equal(e.keyCode, 9, '单个特殊键按键 tabtab 验证 keyCode == 9');
});
__triggerKeyboardEvent(document.body, 9);
hotkeys('clear', function(e){
t.equal(e.keyCode, 12, '单个特殊键按键 clearclear 验证 keyCode == 12');
});
__triggerKeyboardEvent(document.body, 12);
hotkeys(',', function(e){
t.equal(e.keyCode, 188, '单个特殊键按键 , , 验证 keyCode == 188');
});
__triggerKeyboardEvent(document.body, 188);
hotkeys('.', function(e){
t.equal(e.keyCode, 190, '单个特殊键按键 . . 验证 keyCode == 190');
});
__triggerKeyboardEvent(document.body, 190);
hotkeys('.', function(e){
t.equal(e.keyCode, 190, '单个特殊键按键 . . 验证 keyCode == 190');
});
__triggerKeyboardEvent(document.body, 190);
hotkeys('/', function(e){
t.equal(e.keyCode, 191, '单个特殊键按键 / / 验证 keyCode == 191');
});
__triggerKeyboardEvent(document.body, 191);
hotkeys('`', function(e){
t.equal(e.keyCode, 192, '单个特殊键按键 ` ` 验证 keyCode == 192');
});
__triggerKeyboardEvent(document.body, 192);
hotkeys('-', function(e){
t.equal(e.keyCode, isff?173:189, '单个特殊键按键 -- 验证 keyCode == 火狐?173:189');
});
__triggerKeyboardEvent(document.body, isff?173:189);
hotkeys('=', function(e){
t.equal(e.keyCode, isff?61:187, '单个特殊键按键 == 验证 keyCode == 火狐?61:187');
});
__triggerKeyboardEvent(document.body, isff?61:187);
hotkeys(';', function(e){
t.equal(e.keyCode, isff?59:186, '单个特殊键按键 ; ; 验证 keyCode == 火狐?59:186');
});
__triggerKeyboardEvent(document.body, isff?59:186);
hotkeys("\'".toString(), function(e){
t.equal(e.keyCode, 222, "单个特殊键按键 \' \' 验证 keyCode == 222 ");
});
__triggerKeyboardEvent(document.body, 222);
hotkeys("\\".toString(), function(e){
t.equal(e.keyCode, 220, "单个特殊键按键 \\ \\ 验证 keyCode == 220 ");
});
__triggerKeyboardEvent(document.body, 220);
hotkeys("[".toString(), function(e){
t.equal(e.keyCode, 219, "单个特殊键按键 [ [ 验证 keyCode == 219 ");
});
__triggerKeyboardEvent(document.body, 219);
hotkeys("]".toString(), function(e){
t.equal(e.keyCode, 221, "单个特殊键按键 ] ] 验证 keyCode == 221 ");
});
__triggerKeyboardEvent(document.body, 221);
hotkeys('left', function(e){
t.equal(e.keyCode, 37, '单个特殊键按键 leftleft 验证 keyCode == 37');
});
__triggerKeyboardEvent(document.body, 37);
hotkeys('up', function(e){
t.equal(e.keyCode, 38, '单个特殊键按键 upup 验证 keyCode == 38');
});
__triggerKeyboardEvent(document.body, 38);
hotkeys('del', function(e){
t.equal(e.keyCode, 46, '单个特殊键按键 deldel 验证 keyCode == 46');
});
hotkeys('delete', function(e){
t.equal(e.keyCode, 46, '单个特殊键按键 deletedelete 验证 keyCode == 46');
});
__triggerKeyboardEvent(document.body, 46);
hotkeys('home', function(e){
t.equal(e.keyCode, 36, '单个特殊键按键 homehome 验证 keyCode == 36');
});
__triggerKeyboardEvent(document.body, 36);
hotkeys('pageup', function(e){
t.equal(e.keyCode, 33, '单个特殊键按键 pageuppageup 验证 keyCode == 33');
});
__triggerKeyboardEvent(document.body, 33);
hotkeys('pagedown', function(e){
t.equal(e.keyCode, 34, '单个特殊键按键 pagedownpagedown 验证 keyCode == 34');
});
__triggerKeyboardEvent(document.body, 34);
hotkeys('end', function(e){
t.equal(e.keyCode, 35, '单个特殊键按键 endend 验证 keyCode == 35');
});
__triggerKeyboardEvent(document.body, 35);
hotkeys('right', function(e){
t.equal(e.keyCode, 39, '单个特殊键按键 rightright 验证 keyCode == 39');
});
__triggerKeyboardEvent(document.body, 39);
hotkeys('down', function(e){
t.equal(e.keyCode, 40, '单个特殊键按键 downdown 验证 keyCode == 40');
});
__triggerKeyboardEvent(document.body, 40);
hotkeys('esc', function(e){
t.equal(e.keyCode, 27, '单个特殊键按键 escesc 验证 keyCode == 27');
});
hotkeys('escape', function(e){
t.equal(e.keyCode, 27, '单个特殊键按键 escapeescape 验证 keyCode == 27');
});
__triggerKeyboardEvent(document.body, 27);
hotkeys('CapsLock', function(e){
t.equal(e.keyCode, 20, '单个特殊键按键 CapsLockCapsLock验证 keyCode == 20');
});
hotkeys('⇪', function(e){
t.equal(e.keyCode, 20, '单个特殊键按键 ⇪,⇪验证 keyCode == 20');
});
__triggerKeyboardEvent(document.body, 20);
hotkeys('⌘+d', function(e){
t.equal(e.keyCode, 82, '组合键 ⌘+dd验证 keyCode == 82');
t.equal(e.metaKey, true, '组合键 ⌘+dalt验证 metaKey == true');
return false;
});
__triggerKeyboardEvent(document.body, 82,{
metaKey:true
});
hotkeys('alt+d', function(e){
t.equal(e.keyCode, 68, '组合键 alt+dd验证 keyCode == 68');
t.equal(e.altKey, true, '组合键 alt+dalt验证 altKey == true');
});
__triggerKeyboardEvent(document.body, 68,{
altKey:true
});
hotkeys('shift+a', function(e){
t.equal(e.keyCode, 65, '组合键 shift+aa验证 keyCode == 65');
t.equal(e.shiftKey, true, '组合键 shift+ashift验证 shiftKey == true');
});
__triggerKeyboardEvent(document.body, 65,{
shiftKey:true
});
hotkeys('⇧+a', function(e){
t.equal(e.keyCode, 65, '组合键 ⇧+aa验证 keyCode == 65');
t.equal(e.shiftKey, true, '组合键 ⇧+a⇧验证 shiftKey == true');
});
__triggerKeyboardEvent(document.body, 65,{
shiftKey:true
});
hotkeys('⌘+a', function(e){
t.equal(e.keyCode, 65, '组合键 ⌘+aa验证 keyCode == 65');
t.equal(e.metaKey, true, '组合键 ⌘+a⌘验证 metaKey == true');
});
__triggerKeyboardEvent(document.body, 65,{
metaKey:true
});
hotkeys('⌃+a', function(e){
t.equal(e.keyCode, 65, '组合键 ⌃+aa验证 keyCode == 65');
t.equal(e.ctrlKey, true, '组合键 ⌃+a⌃验证 ctrlKey == true');
});
__triggerKeyboardEvent(document.body, 65,{
ctrlKey:true
});
hotkeys.unbind("⌃+a")
hotkeys('⌥+a', function(e){
t.equal(e.keyCode, 65, '组合键 ⌥+aa验证 keyCode == 65');
t.equal(e.altKey, true, '组合键 ⌥+a⌥验证 altKey == true');
});
__triggerKeyboardEvent(document.body, 65,{
altKey:true
});
hotkeys('ctrl+,,ctrl+d', function (e) {
t.equal(e.keyCode, 188, '组合键 ctrl+,,验证 keyCode == 65');
t.equal(e.ctrlKey, true, '组合键 ctrl+,ctrl验证 ctrlKey == true');
});
__triggerKeyboardEvent(document.body, 188, {
ctrlKey: true
});
hotkeys.unbind("ctrl+,,ctrl+d")
hotkeys('Ctrl+A', function (e) {
t.equal(e.keyCode, 65, '大小写组合键 Ctrl+AA验证 keyCode == 65');
t.equal(e.ctrlKey, true, '大小写组合键 Ctrl+ACtrl验证 ctrlKey == true');
});
__triggerKeyboardEvent(document.body, 65, {
ctrlKey: true
});
hotkeys.unbind("Ctrl+A")
hotkeys('CTRL+A', function (e) {
t.equal(e.keyCode, 65, '大小写组合键 CTRL+AA验证 keyCode == 65');
t.equal(e.ctrlKey, true, '大小写组合键 CTRL+ACTRL验证 ctrlKey == true');
});
__triggerKeyboardEvent(document.body, 65, {
ctrlKey: true
});
hotkeys.unbind("CTRL+A")
hotkeys('⌃+a',function(){
t.equal(hotkeys.getScope(), 'all', ' 验证 getScope() == all');
});
__triggerKeyboardEvent(document.body, 65,{
ctrlKey:true
});
hotkeys.unbind("⌃+a")
hotkeys('⌃+a','scope1',function(){
t.equal(hotkeys.getScope(), 'scope1', ' 验证 getScope() == scope1');
});
__triggerKeyboardEvent(document.body, 65,{
ctrlKey:true
});
hotkeys('⌃+a','scope2',function(){
t.equal(hotkeys.getScope(), 'scope2', ' 验证 getScope() == scope2');
});
hotkeys.setScope('scope1');
__triggerKeyboardEvent(document.body, 65,{
ctrlKey:true
});
hotkeys.setScope('scope2');
__triggerKeyboardEvent(document.body, 65,{
ctrlKey:true
});
});

File diff suppressed because one or more lines are too long

@ -1,37 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<title>hotkeys</title>
<style type="text/css">
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body,html{margin: 0;padding: 0;}
body div.test{
margin: 0;
border-top: 1px dotted rgba(128, 128, 128, 0);
}
body div.test .name{
padding:0 10px;
}
body div.test .assert{
padding:0 10px;
line-height: 23px;
font-size: 12px;
}
body div.test .assert span{
vertical-align: middle;
}
body div.test .assert span.name{
max-width: inherit;
}
</style>
<meta charset="UTF-8">
<title>hotkeys.js - A robust Javascript library for capturing keyboard input.</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies. Try to press your keyboard, The following button will highlight.">
</head>
<body>
<div id="tests"/>
<script src="../dist/hotkeys.js"></script>
<script src="../test/hotkeys.test.js"></script>
<div id="root"></div>
<script src="../dist/index.js"></script>
</body>
</html>

@ -0,0 +1,116 @@
import React, { Component } from 'react';
import GithubCorner from './components/GithubCorner';
import KeyBoard from './components/KeyBoard';
import Footer from './components/Footer';
import Markdown from './components/Markdown';
import GithubShields from './components/GithubShields';
import styles from './styles/index.less';
import DocumentStr from './doc.md';
import hotkeys from '../dist/hotkeys.common';
export default class App extends Component {
constructor() {
super();
this.state = {
keyCode: [],
keyStr: [],
}
this.onKeyUpEvent = this.onKeyUpEvent.bind(this);
}
componentDidMount() {
const { keyCode } = this.state;
document.addEventListener('keyup', this.onKeyUpEvent);
function pkeys(keys, key) {
if (keys.indexOf(key) === -1) keys.push(key);
return keys;
}
function pkeysStr(keysStr, key) {
if (keysStr.indexOf(key) === -1) keysStr.push(key);
return keysStr;
}
hotkeys('*', (evn) => {
evn.preventDefault()
const keys = [];
const keyStr = [];
if (hotkeys.shift) pkeys(keys,16), pkeysStr(keyStr,'shift');
if (hotkeys.ctrl) pkeys(keys,17), pkeysStr(keyStr,'ctrl');
if (hotkeys.alt) pkeys(keys,18), pkeysStr(keyStr,'alt');
if (hotkeys.control) pkeys(keys,17), pkeysStr(keyStr,'control');
if (hotkeys.command) pkeys(keys,91), pkeysStr(keyStr,'command');
keyStr.push(evn.keyCode);
if (keys.indexOf(evn.keyCode) === -1) keys.push(evn.keyCode);
this.setState({ keyCode: keys, keyStr });
});
return false;
}
componentWillUnmount() {
document.removeEventListener('keyup', this.onKeyUpEvent);
}
onKeyUpEvent() {
this.setState({ keyCode: [], keyStr: [] });
}
onKeyBoardMouseDown(item) {
if (item.keycode > -1) {
this.setState({ keyStr: [item.keycode] });
}
}
onKeyBoardMouseUp(item) {
this.setState({ keyStr: [] });
}
render() {
const { keyCode, keyStr } = this.state;
return (
<div>
{keyStr.length > -1 && (
<div className={styles.keyCodeInfo}>
{keyStr.map((item, idx) => <span key={idx}>{item}</span>)}
</div>
)}
<GithubCorner url="https://github.com/jaywcjlove/hotkeys" />
<div className={styles.header}>
<div className={styles.title}>HotKeys.js</div>
<div className={styles.github}>
<a href="https://github.com/jaywcjlove/hotkeys/zipball/master">
<button>Download as zip</button>
</a>
<a href="https://github.com/jaywcjlove/hotkeys/tarball/master">
<button>Download as tar.gz</button>
</a>
<a href="https://github.com/jaywcjlove/hotkeys/">
<button>Fork on Github</button>
</a>
<a href="https://github.com/jaywcjlove/hotkeys/">
<button>Doc on Github</button>
</a>
</div>
<div className={styles.info}>A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies. Try to press your keyboard, The following button will highlight.</div>
</div>
<KeyBoard
onMouseDown={this.onKeyBoardMouseDown.bind(this)}
onMouseUp={this.onKeyBoardMouseUp.bind(this)}
keyCode={this.state.keyCode}
/>
<Markdown source={DocumentStr} />
<GithubShields source={[
{
href: 'https://github.com/jaywcjlove/hotkeys/network',
img: 'https://img.shields.io/github/forks/jaywcjlove/hotkeys.svg?style=social'
},
{
href: 'https://github.com/jaywcjlove/hotkeys/stargazers',
img: 'https://img.shields.io/github/stars/jaywcjlove/hotkeys.svg?style=social'
},
{
href: 'https://github.com/jaywcjlove/hotkeys/watchers',
img: 'https://img.shields.io/github/watchers/jaywcjlove/hotkeys.svg?style=social&label=Watch'
},
{
href: 'https://github.com/jaywcjlove/followers',
img: 'https://img.shields.io/github/followers/jaywcjlove.svg?style=social'
},
]} />
<Footer name="Kenny Wong" href="http://jaywcjlove.github.io" year="2015" />
</div>
)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@ -0,0 +1,8 @@
import React from 'react';
import style from './Footer.less';
export default function Footer({ name, href, year}) {
return (
<div className={style.footer}>© <a target="_blank" href={href}>{name}</a> {year}</div>
)
}

@ -0,0 +1,5 @@
.footer {
text-align: center;
padding: 15px 0 100px 0;
font-size: 12px;
}

@ -0,0 +1,17 @@
import React from 'react';
import styles from './GithubCorner.less';
export default function GithubCorner({ url }) {
if (!url) {
return null;
}
return (
<a href={url} target="_blank" className={styles.corner}>
<svg viewBox="0 0 250 250">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style={{ transformOrigin: "130px 106px" }} className="octo-arm" />
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" className="octo-body" />
</svg>
</a>
)
}

@ -0,0 +1,32 @@
a.corner {
position: fixed;
top: 0;
right: 0;
svg {
fill:#e1e1e1;
color:#000;
position:absolute;
top:0;
border:0;
right:0;
z-index:99;
width:4.375rem;
height:4.375rem;
}
&:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
}
@keyframes octocat-wave {
0%,100% {
transform:rotate(0);
}
20%,60% {
transform:rotate(-25deg);
}
40%,80% {
transform:rotate(10deg);
}
}

@ -0,0 +1,20 @@
import React from 'react';
import styles from './GithubShields.less'
// source = [
// {
// href: 'https://github.com/jaywcjlove/hotkeys/network',
// img: 'https://img.shields.io/github/forks/jaywcjlove/hotkeys.svg?style=social'
// },
// ]
export default function GithubShields({ source }) {
return (
<div className={styles.shields}>
{source.map((item, idx) => (
<a key={idx} href={item.href} target="_blank" rel="external">
<img src={item.img} alt="" />
</a>
))}
</div>
);
}

@ -0,0 +1,8 @@
.shields {
padding: 60px 0 0 0;
text-align:center;
a + a{
margin-left: 10px;
}
}

@ -0,0 +1,109 @@
import React from 'react';
import classNames from 'classnames';
import styles from './KeyBoard.less';
const keyCode = [
{ keycode: 27, name: ["esc"] },
{ keycode: 112, name: ["F1"] },
{ keycode: 113, name: ["F2"] },
{ keycode: 114, name: ["F3"] },
{ keycode: 115, name: ["F4"] },
{ keycode: 116, name: ["F5"] },
{ keycode: 117, name: ["F6"] },
{ keycode: 118, name: ["F7"] },
{ keycode: 119, name: ["F8"] },
{ keycode: 120, name: ["F9"] },
{ keycode: 121, name: ["F10"] },
{ keycode: 122, name: ["F11"] },
{ keycode: 123, name: ["F12"] },
{ keycode: -1, name: [""] },
{ keycode: 192, name: ["~", "`"] },
{ keycode: 49, name: ["!", "1"] },
{ keycode: 50, name: ["@", "2"] },
{ keycode: 51, name: ["#", "3"] },
{ keycode: 52, name: ["$", "4"] },
{ keycode: 53, name: ["%", "5"] },
{ keycode: 54, name: ["^", "6"] },
{ keycode: 55, name: ["&", "7"] },
{ keycode: 56, name: ["*", "8"] },
{ keycode: 57, name: ["(", "9"] },
{ keycode: 48, name: [")", "0"] },
{ keycode: 189, name: ["_", "-"] },
{ keycode: 187, name: ["", ": "] },
{ keycode: 8, name: ["delete"] },
{ keycode: 9, name: ["tab"] },
{ keycode: 81, name: ["Q"] },
{ keycode: 87, name: ["W"] },
{ keycode: 69, name: ["E"] },
{ keycode: 82, name: ["R"] },
{ keycode: 84, name: ["T"] },
{ keycode: 89, name: ["Y"] },
{ keycode: 85, name: ["U"] },
{ keycode: 73, name: ["I"] },
{ keycode: 79, name: ["O"] },
{ keycode: 80, name: ["P"] },
{ keycode: 219, name: ["{", "["] },
{ keycode: 221, name: ["}", "]"] },
{ keycode: 220, name: ["|", "\\"] },
{ keycode: 20, name: ["", "CapsLock"] },
{ keycode: 65, name: ["A"] },
{ keycode: 83, name: ["S"] },
{ keycode: 68, name: ["D"] },
{ keycode: 70, name: ["F"] },
{ keycode: 71, name: ["G"] },
{ keycode: 72, name: ["H"] },
{ keycode: 74, name: ["J"] },
{ keycode: 75, name: ["K"] },
{ keycode: 76, name: ["L"] },
{ keycode: 186, name: [":", ";"] },
{ keycode: 222, name: ["\"", "'"] },
{ keycode: 13, name: ["enter", "return"] },
{ keycode: 16, name: ["⇧"] },
{ keycode: 90, name: ["Z"] },
{ keycode: 88, name: ["X"] },
{ keycode: 67, name: ["C"] },
{ keycode: 86, name: ["V"] },
{ keycode: 66, name: ["B"] },
{ keycode: 78, name: ["N"] },
{ keycode: 77, name: ["M"] },
{ keycode: 188, name: ["<", ","] },
{ keycode: 190, name: [">", "."] },
{ keycode: 191, name: ["?", "/"] },
{ keycode: 16, name: ["⇧"] },
{ keycode: -1, name: ["fn"] },
{ keycode: 17, name: ["control"] },
{ keycode: 18, name: ["alt", "option"] },
{ keycode: 91, name: ["command"] },
{ keycode: 32, name: [""] },
{ keycode: 93, name: ["command"] },
{ keycode: 18, name: ["alt", "option"] },
{ keycode: 37, name: ["◀"] },
{ keycode: 38, name: ["▲"] },
{ keycode: 39, name: ["▶"] },
{ keycode: 40, name: ["▼"] },
];
export default function KeyBoard({ keyCode: keyCodeNum, onMouseDown, onMouseUp }) {
// console.log('keyCodeNum:', keyCodeNum)
return (
<div className={styles.keyboard}>
<ul>
{keyCode.map((item, idx) => {
const name = item.name.map((item, _idx) => <span key={_idx}>{item}</span>);
return (
<li
key={idx}
onMouseDown={() => onMouseDown(item)}
onMouseUp={() => onMouseUp(item)}
className={classNames({ pressed: keyCodeNum.indexOf(item.keycode) > -1})}
data-key={item.keycode}
>
{name}
</li>
)
})}
</ul>
</div>
)
}

@ -0,0 +1,248 @@
.keyboard {
height: 394px;
border-radius: 10px;
border: 1px solid #C9C9C9;
background: #F2F2F2;
box-shadow: 2px 0px 2px #E2E2E2 inset,-2px 2px 3px #E2E2E2 inset,1px -0px 0px #C1C1C1 inset,0px -2px 3px #C1C1C1 inset;
user-select: none;
position: relative;
top: -66;
width: 995px;
margin: 0 auto;
ul {
width: 992px;
margin-top: 9px;
padding-left: 11px;
position: relative;
float: left;
}
li {
width: 62px;
height: 62px;
float: left;
margin-right: 5px;
margin-bottom: 5px;
background: #151515;
color: rgb(200,200,200);
text-align: center;
line-height: 62px;
font-size: 12px;
border-radius: 8px;
border: 1px solid #3A3A3A;
box-shadow: 1px 0px 0px rgb(0,0,0),0px 1px 0px rgb(0,0,0),-1px 0px 0px rgb(0,0,0),0px -1px 0px rgb(0,0,0);
user-select: none;
cursor: pointer;
position: relative;
&:active, &:global(.pressed) {
color:#52F800;
background-color: #100068;
border:1px solid #332376;
}
&:nth-child(1) {
width: 99px;
height: 28px;
line-height: 28px;
text-indent: 1em;
text-align: left;
}
&:nth-child(2),
&:nth-child(3),
&:nth-child(4),
&:nth-child(5),
&:nth-child(6),
&:nth-child(7),
&:nth-child(8),
&:nth-child(9),
&:nth-child(10),
&:nth-child(11),
&:nth-child(12),
&:nth-child(13),
&:nth-child(14) {
width: 60px;
height: 28px;
line-height: 28px;
}
&:nth-child(15),
&:nth-child(16),
&:nth-child(17),
&:nth-child(18),
&:nth-child(19),
&:nth-child(20),
&:nth-child(21),
&:nth-child(22),
&:nth-child(23),
&:nth-child(24),
&:nth-child(25),
&:nth-child(26),
&:nth-child(27),
&:nth-child(40),
&:nth-child(41),
&:nth-child(42),
&:nth-child(53),
&:nth-child(54),
&:nth-child(64),
&:nth-child(65),
&:nth-child(66) {
padding: 7px 0;
height: 48px;
}
}
}
.keyboard li:nth-child(15) span,
.keyboard li:nth-child(16) span,
.keyboard li:nth-child(17) span,
.keyboard li:nth-child(18) span,
.keyboard li:nth-child(19) span,
.keyboard li:nth-child(20) span,
.keyboard li:nth-child(21) span,
.keyboard li:nth-child(22) span,
.keyboard li:nth-child(23) span,
.keyboard li:nth-child(24) span,
.keyboard li:nth-child(25) span,
.keyboard li:nth-child(26) span,
.keyboard li:nth-child(27) span,
.keyboard li:nth-child(40) span,
.keyboard li:nth-child(41) span,
.keyboard li:nth-child(42) span,
.keyboard li:nth-child(53) span,
.keyboard li:nth-child(54) span,
.keyboard li:nth-child(64) span,
.keyboard li:nth-child(65) span,
.keyboard li:nth-child(66) span {
line-height: 23px;
height: 23px;
width: 100%;
float: left;
font-size:14px;
}
.keyboard li:nth-child(28) span,
.keyboard li:nth-child(55) span,
.keyboard li:nth-child(67) span {
line-height: 14px;
margin-top: 43px;
float: right;
margin-right: 8px;
}
//字母键
.keyboard li:nth-child(30),
.keyboard li:nth-child(31),
.keyboard li:nth-child(32),
.keyboard li:nth-child(33),
.keyboard li:nth-child(34),
.keyboard li:nth-child(35),
.keyboard li:nth-child(36),
.keyboard li:nth-child(37),
.keyboard li:nth-child(38),
.keyboard li:nth-child(39),
.keyboard li:nth-child(44),
.keyboard li:nth-child(45),
.keyboard li:nth-child(46),
.keyboard li:nth-child(47),
.keyboard li:nth-child(48),
.keyboard li:nth-child(49),
.keyboard li:nth-child(50),
.keyboard li:nth-child(51),
.keyboard li:nth-child(52),
.keyboard li:nth-child(57),
.keyboard li:nth-child(58),
.keyboard li:nth-child(59),
.keyboard li:nth-child(60),
.keyboard li:nth-child(61),
.keyboard li:nth-child(62),
.keyboard li:nth-child(63) {
font-size: 18px;
line-height: 64px;
}
.keyboard li:nth-child(29) span,
.keyboard li:nth-child(43) span,
.keyboard li:nth-child(56) span,
.keyboard li:nth-child(68) span,
.keyboard li:nth-child(69) span,
.keyboard li:nth-child(70) span,
.keyboard li:nth-child(71) span,
.keyboard li:nth-child(73) span,
.keyboard li:nth-child(74) span {
line-height: 14px;
margin-top: 43px;
text-indent: 5px;
float: left;
}
.keyboard li:nth-child(28),
.keyboard li:nth-child(29) {
width: 73px;
}
.keyboard li:nth-child(43),
.keyboard li:nth-child(55) {
width: 102px;
}
.keyboard {
li:nth-child(43) {
&:active {
span:first-child {
background:#52f800;
}
}
span:first-child {
position: absolute;
top: -36px;
left: 5px;
width: 6px;
height: 6px;
background: #fff;
border-radius: 3px;
}
}
}
.keyboard li:nth-child(55) span:first-child,
.keyboard li:nth-child(70) span:first-child {
position: absolute;
right: 0px;
top: -37px;
font-size: 12px;
line-height: 12px;
}
.keyboard li:nth-child(70) span:first-child {
left: 0px;
text-align: left;
}
.keyboard li:nth-child(74) span:first-child {
position: absolute;
left: 0;
top: -37px;
font-size: 12px;
line-height: 12px;
}
.keyboard li:nth-child(56) {
width: 136px;
}
.keyboard li:nth-child(67) {
width: 137px;
}
.keyboard li:nth-child(71),
.keyboard li:nth-child(73) {
width: 70px;
}
.keyboard li:nth-child(72) {
width: 333px;
}
.keyboard li:nth-child(76),
.keyboard li:nth-child(78) {
height: 29px;
line-height: 29px;
}
.keyboard li:nth-child(76) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.keyboard li:nth-child(78) {
border-top-left-radius: 0;
border-top-right-radius: 0;
position: absolute;
bottom: 0;
right: 84px;
}

@ -0,0 +1,43 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown';
import hljs from 'highlight.js';
import classNames from 'classnames';
import styles from './styles/index.less';
hljs.configure({
tabReplace: ' ', // 2 spaces
classPrefix: '', // don't append class prefix
});
export default class Markdown extends Component {
componentDidMount() {
let code = ReactDOM.findDOMNode(this);
code = code.getElementsByTagName('code');
for (let i = 0; i < code.length; i += 1) {
if (code[i].parentNode && code[i].parentNode.tagName === 'PRE') {
hljs.highlightBlock(code[i]);
}
}
}
render() {
const { source }= this.props;
return (
<ReactMarkdown
className={classNames(styles.markdown, 'markdown')}
source={source}
escapeHtml={false}
allowNode={(node) => {
if (node.type === 'html') {
if (/<!--([^]+?)-->/.test(node.value)) return false;
// const scriptValue = node.value.match(/<script.*?>(.*?)<\/script>/ig);
// node.value.replace(/<script.*?>(.*?)<\/script>/, (te) => {
// console.log('te:', te);
// });
}
return node;
}}
/>
)
}
}

@ -0,0 +1,216 @@
code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
word-wrap: normal;
}
code:not(.hljs){
padding: 0.2em 0.4em 0.08em 0.4em;
margin: 0;
font-size: 85%;
background-color: rgba(27, 31, 35, 0.07);
border-radius: 3px;
}
// code.hljs {
// padding: 16px;
// font-size: 95%;
// line-height: 1.5;
// display: block;
// text-shadow: 0 1px #fff;
// }
pre code {
padding: 16px;
font-size: 95%;
line-height: 1.5;
display: block;
text-shadow: 0 1px #fff;
}
pre {
margin-bottom: 18px;
max-height: 35em;
position: relative;
overflow: auto;
background-color: #F0F0F0;
border-radius: 3px;
}
pre code {
background: none;
font-size: 1em;
overflow-wrap: normal;
white-space: inherit;
}
ul, ol {
padding-left: 2em;
}
dl {
padding: 0;
dt {
padding: 0;
margin-top: 16px;
font-size: 14px;
font-style: italic;
font-weight: 600;
}
}
li + li {
margin-top: 3px;
}
a {
color: #0366d6;
}
p {
margin-bottom: 10px;
}
blockquote {
margin: 0;
padding: 0 1em;
margin-bottom: 10px;
color: #6a737d;
border-left: 0.25em solid #dfe2e5;
& >:first-child {
margin-top: 0;
}
& >:last-child {
margin-bottom: 0;
}
}
hr {
height: 0.25em;
padding: 0;
margin: 24px 0;
background-color: #e1e4e8;
border: 0;
}
h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code {
font-size: inherit
}
h1 {
padding-bottom: 0.3em;
font-size: 2em;
border-bottom: 1px solid #cecece;
margin-bottom: 10px;
}
h2 {
margin-bottom: 10px;
padding-bottom: 0.3em;
font-size: 1.5em;
border-bottom: 1px solid #cecece;
}
h3 {
margin-bottom: 10px;
font-size: 1.25em
}
h4 {
margin-bottom: 8px;
font-size: 1em
}
h5 {
margin-bottom: 8px;
font-size: 0.875em
}
h6 {
margin-bottom: 5px;
font-size: 0.85em;
color: #6a737d
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
display: block;
width: 100%;
}
table th {
font-weight: 600;
}
table th,table td {
padding: 6px 13px;
border: 1px solid #dfe2e5;
}
table tr {
background-color: #fff;
border-top: 1px solid #c6cbd1;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
table img {
background-color: transparent;
}
img {
max-width: 100%;
box-sizing: content-box;
background-color: #fff;
vertical-align: middle;
}
img[align=right] {
padding-left: 20px;
}
img[align=left] {
padding-right: 20px;
}
.comment,.quote{
color:#998;
}
.keyword,.selector-tag,.subst{
color:#333;font-weight:bold;
}
.number,.literal,.variable,.template-variable,.tag .attr{
color:#008080;
}
.string,.doctag{
color:#d14;
}
.title,.section,.selector-id{
color:#900;font-weight:bold;
}
.subst{
font-weight:normal;
}
.type,.class .title{
color:#458;font-weight:bold;
}
.tag,.name,.attribute{
color:#000098;
font-weight:normal;
}
.regexp,.link{
color:#009926;
}
.symbol,.bullet{
color:#990073;
}
.built_in,.builtin-name{
color:#0086b3;
}
.meta{
color:#999;font-weight:bold;
}
.deletion{
background:#fdd;
}
.addition{
background:#dfd;
}
.emphasis{
font-style:italic;
}
.strong{
font-weight:bold;
}

@ -0,0 +1,25 @@
.markdown {
padding: 0 20px 20px;
max-width: 995px;
margin: 0 auto;
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;
color: #24292e;
& >*:first-child {
margin-top: 0 !important
}
& >*:last-child {
margin-bottom: 0 !important
}
:global {
@import "./default.less";
// @import "./xml.less";
// @import "./swift.less";
// @import "./diff.less";
// @import "./css.less";
@import "./javascript.less";
}
}

@ -0,0 +1,34 @@
.language-jsx, .language-js,.language-javascript{
.keyword, .selector-tag {
color: #b111bf;
font-weight: 600;
}
.subst {
color: #0000ca;
}
.title, .section {
color: #4e00dc;
font-weight: normal;
}
.string, .doctag {
color: #d73a49;
}
.attr {
color: #0000ca;
}
.class .keyword{
color: #008cd4;
}
.function {
color: #0000ca;
.params {
color: #008cd4;
}
}
}
.language-json {
color: #444;
.attr {
color: #0000ca;
}
}

@ -0,0 +1,246 @@
HotKeys.js is an input capture library with some very special features, it is easy to pick up and use, has a reasonable footprint (~3kb), and has no dependencies. It should not interfere with any JavaScript libraries or frameworks.
## USAGE
You will need `Node.js` installed on your system.
```shell
$ npm install hotkeys-js --save
```
```
import hotkeys from 'hotkeys-js';
```
Or manually download and link **hotkeys.js** in your HTML:
```js
<script type="text/javascript" src="hotkeys.js"></script>
```
### Used in React
[react-hotkeys](https://github.com/jaywcjlove/react-hotkeys) is the React component that listen to keydown and keyup keyboard events, defining and dispatching keyboard shortcuts.
```shell
$ npm install react-hot-keys --save
```
Detailed use method please see its documentation [react-hotkeys](https://github.com/jaywcjlove/react-hotkeys).
## Browser Support
Mousetrap has been tested and should work in.
```shell
Internet Explorer 6+
Safari
Firefox
Chrome
```
## DEFINING SHORTCUTS
One global method is exposed, key which defines shortcuts when called directly.
```js
hotkeys('f5', function(event, handler){
// Prevent the default refresh event under WIDNOWS system
event.preventDefault()
alert('you pressed F5!')
});
hotkeys('a', function(event,handler){
//event.srcElement: input
//event.target: input
if(event.target === "input"){
alert('you pressed a!')
}
alert('you pressed a!')
});
hotkeys('ctrl+a,ctrl+b,r,f', function(event,handler){
switch(handler.key){
case "ctrl+a":alert('you pressed ctrl+a!');break;
case "ctrl+b":alert('you pressed ctrl+b!');break;
case "r":alert('you pressed r!');break;
case "f":alert('you pressed f!');break;
}
});
hotkeys('*','wcj', function(e){
console.log('do something',e);
});
```
## API REFERENCE
Asterisk "*"
Modifier key judgments
```js
hotkeys('*','wcj', function(e){
if(hotkeys.shift) console.log('shift is pressed');
if(hotkeys.ctrl) console.log('shift is pressed! ');
if(hotkeys.alt) console.log('shift is pressed! ');
});
```
### setScope
Use the `hotkeys.setScope` method to set scope.
```js
// define shortcuts with a scope
hotkeys('ctrl+o, ctrl+alt+enter', 'issues', function(){
console.log('do something');
});
hotkeys('o, enter', 'files', function(){
console.log('do something else');
});
// set the scope (only 'all' and 'issues' shortcuts will be honored)
hotkeys.setScope('issues'); // default scope is 'all'
```
### getScope
Use the `hotkeys.getScope` method to get scope.
```js
hotkeys.getScope();
```
### deleteScope
Use the `hotkeys.deleteScope` method to delete set scope.
```js
hotkeys.deleteScope('issues');
```
### unbind
Similar to defining shortcuts, they can be unbound using `hotkeys.unbind`.
```js
// unbind 'a' handler
hotkeys.unbind('a');
// unbind a hotkeys only for a single scope
// when no scope is specified it defaults to the current scope (hotkeys.getScope())
hotkeys.unbind('o, enter', 'issues');
hotkeys.unbind('o, enter', 'files');
```
### isPressed
Other key queries. For example, `hotkeys.isPressed(77)` is true if the `M` key is currently pressed.
```js
hotkeys('a', function(){
console.log(hotkeys.isPressed("a")); //=> true
console.log(hotkeys.isPressed("A")); //=> true
console.log(hotkeys.isPressed(65)); //=> true
});
```
### getPressedKeyCodes
returns an array of key codes currently pressed.
```js
hotkeys('command+ctrl+shift+a,f', function(){
console.log(hotkeys.getPressedKeyCodes()); //=> [17, 65] or [70]
})
```
### filter
`INPUT` `SELECT` `TEXTAREA` default does not handle.
`Hotkeys.filter` to return to the `true` shortcut keys set to play a role, `flase` shortcut keys set up failure.
```js
hotkeys.filter = function(event){
return true;
}
//How to add the filter to edit labels. <div contentEditable="true"></div>
//"contentEditable" Older browsers that do not support drops
hotkeys.filter = function(event) {
var tagName = (event.target || event.srcElement).tagName;
return !(tagName.isContentEditable || tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
}
hotkeys.filter = function(event){
var tagName = (event.target || event.srcElement).tagName;
hotkeys.setScope(/^(INPUT|TEXTAREA|SELECT)$/.test(tagName) ? 'input' : 'other');
return true;
}
```
### noConflict
Relinquish HotKeyss control of the `hotkeys` variable.
```js
var k = hotkeys.noConflict();
k('a', function() {
console.log("do something")
});
hotkeys()
// -->Uncaught TypeError: hotkeys is not a function(anonymous function)
// @ VM2170:2InjectedScript._evaluateOn
// @ VM2165:883InjectedScript._evaluateAndWrap
// @ VM2165:816InjectedScript.evaluate @ VM2165:682
```
### SUPPORTED KEYS
HotKeys understands the following modifiers: `⇧`, `shift`, `option`, `⌥`, `alt`, `ctrl`, `control`, `command`, and `⌘`.
The following special keys can be used for shortcuts: backspace, tab, clear, enter, return, esc, escape, space, up, down, left, right, home, end, pageup, pagedown, del, delete and f1 through f19.
`⌘` Command()
`⌃` Control
`⌥` Option(alt)
`⇧` Shift
`⇪` Caps Lock(Capital)
~~`fn` Does not support fn~~
`↩︎` return/Enter space
## Development
To develop, run the self-reloading build, Get the code:
```shell
$ git https://github.com/jaywcjlove/hotkeys.git
$ cd hotkeys # Into the directory
$ npm install # or yarn install
```
To develop, run the self-reloading build:
```shell
$ npm run watch
```
Run Document Website Environment.
```shell
$ npm run doc:dev
```
## License
[MIT © Kenny Wong](https://kossnocorp.mit-license.org/)
```bash
__ __ __
| |--..-----.| |_ | |--..-----..--.--..-----.
| || _ || _|| < | -__|| | ||__ --|
|__|__||_____||____||__|__||_____||___ ||_____|
|_____|
```

@ -0,0 +1,13 @@
<html>
<head>
<meta charset="UTF-8">
<title>hotkeys.js - A robust Javascript library for capturing keyboard input.</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies. Try to press your keyboard, The following button will highlight.">
</head>
<body>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>

@ -0,0 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './styles/reset.less';
ReactDOM.render(<App />, document.getElementById('root'));

@ -0,0 +1,77 @@
.keyCodeInfo {
position: fixed;
bottom: 10px;
left: 10px;
span + span {
margin-left: 10px;
}
span {
display: inline-block;
background: #eff0f2;
border-radius: 3px;
padding: 5px 10px;
border-top: 1px solid #f5f5f5;
box-shadow: inset 0 0 25px #e8e8e8, 0 1px 0 #c3c3c3, 0 2px 0 #c9c9c9, 0 2px 3px #333;
text-shadow: 0px 1px 0px #f5f5f5;
}
}
.header {
background-color: #292929;
padding: 74px 0 80px 0;
.title {
text-align: center;
font-size: 53px;
font-weight: bold;
color: #fff;
text-shadow: -3px -3px 0 #676767, -3px -3px 0 #676767, -3px -3px 0 #676767, -2px -2px 0 #676767, -2px -2px 0 #676767, -1px -1px 0 #676767;
}
.lang {
text-align: center;
padding-top: 20px;
a {
color: #fff;
margin: 0 5px;
}
}
.info {
padding: 25px 0 27px 0;
text-align: center;
font-size: 23px;
line-height: 29px;
color: #878787;
max-width: 702px;
margin: 0 auto;
}
.github {
text-align: center;
padding: 60px 0 22px 0;
a + a {
margin-left: 10px;
}
button {
position: relative;
display: inline-block;
border: 1px solid #ddd;
border-bottom-color: #bbb;
padding: 9px 15px;
font-family: Helvetica, arial, freesans, clean, sans-serif;
font-size: 12px;
font-weight: bold;
color: #666;
text-shadow: 0 1px rgba(255, 255, 255, 0.9);
cursor: pointer;
border-radius: 3px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
background: whitesmoke;
background-image: linear-gradient(-90deg, whitesmoke 0%, #e5e5e5 100%);
&:hover {
color: #337797;
border: 1px solid #CBE3EE;
border-bottom-color: #97C7DD;
background: #f0f7fa;
background-image: -webkit-linear-gradient(-90deg, #f0f7fa 0%, #d8eaf2 100%);
}
}
}
}

@ -0,0 +1,44 @@
html {
font-size: 14px;
background: #e0e0e0;
}
/* margin */
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, img, form, applet, fieldset, legend, button, input, textarea, th, table, tr, td{
margin: 0;
padding: 0;
border: none;
}
/* body */
body {
font-family: "微软雅黑";
font-size: 12px;
color:#535353;
position: relative;
font-family: "PingHei","Lucida Grande", "Lucida Sans Unicode", "STHeitiSC-Light", "Helvetica","Arial","Verdana","sans-serif";
background: #f8f8f8 url(../assets/bg.jpg) repeat top left;
}
body, div, fieldset, form, h1, h2, h3, h4, h5, h6, html, p {
-webkit-text-size-adjust: none
}
/* img */
img {
padding: 0;
margin: 0;
vertical-align: top;
border: none;
}
/* div */
li,ul {
list-style: none;
margin: 0 auto;
padding: 0 auto;
display: block;
font-family: "Vrinda";
user-select: none;
}
Loading…
Cancel
Save