Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/bind plus #105

Merged
merged 1 commit into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ hotkeys('*','wcj', function(e){
if(hotkeys.ctrl) console.log('大哥你摁下了 ctrl 键!');
if(hotkeys.alt) console.log('大哥你摁下了 alt 键!');
});

// 可以设置自定义的分割符
hotkeys('ctrl-y, ctrl-a', {splitKey: '-'}, function(e){
console.log('you press bind keys')
})
```

#### option
Expand Down Expand Up @@ -229,9 +234,11 @@ hotkeys.setScope('scope1');

## 解除绑定

`hotkeys.unbind()` 解除绑定的所有快捷键
`hotkeys.unbind("ctrl+o, ctrl+alt+enter")` 解除绑定两组快捷键
`hotkeys.unbind("ctrl+o","files")` 解除绑定名字叫files钟的一组快捷键


```js
// 解除绑定 'a' 程序函数
hotkeys.unbind('a');
Expand All @@ -252,6 +259,26 @@ hotkeys.unbind('a', example);
hotkeys('a', 'issues', example);
hotkeys.unbind('a', 'issues', example);
```
```js
可以通过传入对象解除绑定的快捷键
hotkeys.unbind({
key: 'ctrl-e,ctrl-u',
scope: 'issues',
spitKey: '-'
})
传入数组可同时解除多个scope下绑定的快捷键
hotkeys.unbind([
{
key: 'a, ctrl+r',
scope: 'issues',
},
{
key: '+, ctrl-y',
scope: 'test',
splitKey: '-'
}
])
```

## 键判断

Expand Down
145 changes: 87 additions & 58 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ let _scope = 'all'; // 默认热键范围
const elementHasBindEvent = []; // 已绑定事件的节点记录

// 返回键码
const code = x => _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
const code = x =>
_keyMap[x.toLowerCase()] ||
_modifier[x.toLowerCase()] ||
x.toUpperCase().charCodeAt(0);

// 设置获取当前范围(默认为'所有')
function setScope(scope) { _scope = scope || 'all'; }
function setScope(scope) {
_scope = scope || 'all';
}
// 获取当前范围
function getScope() { return _scope || 'all'; }
function getScope() {
return _scope || 'all';
}
// 获取摁下绑定键的键值
function getPressedKeyCodes() { return _downKeys.slice(0); }
function getPressedKeyCodes() {
return _downKeys.slice(0);
}

// 表单控件控件判断 返回 Boolean
// hotkey is effective only when filter return true
Expand All @@ -35,13 +44,12 @@ function filter(event) {

// 判断摁下的键是否为某个键,返回true或者false
function isPressed(keyCode) {
if (typeof (keyCode) === 'string') {
if (typeof keyCode === 'string') {
keyCode = code(keyCode); // 转换成键码
}
return _downKeys.indexOf(keyCode) !== -1;
}


// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
let handlers;
Expand Down Expand Up @@ -88,58 +96,63 @@ function clearModifier(event) {
}
}

// 解除绑定某个范围的快捷键
function unbind(key, scope, method) {
const multipleKeys = getKeys(key);
let keys;
let mods = [];
let obj;
// 通过函数判断,是否解除绑定
// https://github.com/jaywcjlove/hotkeys/issues/44
if (typeof scope === 'function') {
method = scope;
scope = 'all';
}

for (let i = 0; i < multipleKeys.length; i++) {
// 将组合快捷键拆分为数组
keys = multipleKeys[i].split('+');

// 记录每个组合键中的修饰键的键码 返回数组
if (keys.length > 1) {
mods = getMods(_modifier, keys);
} else {
mods = [];
function unbind(keysInfo, ...args) {
// unbind(), unbind all keys
if (!keysInfo) {
Object.keys(_handlers).forEach(key => delete _handlers[key]);
} else if (Array.isArray(keysInfo)) {
// support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}])
keysInfo.forEach((info) => {
if (info.key) eachUnbind(info);
});
} else if (typeof keysInfo === 'object') {
// support like unbind({key: 'ctrl+a, ctrl+b', scope:'abc'})
if (keysInfo.key) eachUnbind(keysInfo);
} else if (typeof keysInfo === 'string') {
// support old method
// eslint-disable-line
let [scope, method] = args;
if (typeof scope === 'function') {
method = scope;
scope = '';
}
eachUnbind({
key: keysInfo,
scope,
method,
splitKey: '+',
});
}
}

// 获取除修饰键外的键值key
key = keys[keys.length - 1];
key = key === '*' ? '*' : code(key);

// 解除绑定某个范围的快捷键
const eachUnbind = ({
key, scope, method, splitKey = '+',
}) => {
const multipleKeys = getKeys(key);
multipleKeys.forEach((originKey) => {
const unbindKeys = originKey.split(splitKey);
const len = unbindKeys.length;
const lastKey = unbindKeys[len - 1];
const keyCode = lastKey === '*' ? '*' : code(lastKey);
if (!_handlers[keyCode]) return;
// 判断是否传入范围,没有就获取范围
if (!scope) scope = getScope();

// 如何key不在 _handlers 中返回不做处理
if (!_handlers[key]) return;

// 清空 handlers 中数据,
// 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
for (let r = 0; r < _handlers[key].length; r++) {
obj = _handlers[key][r];
const mods = len > 1 ? getMods(_modifier, unbindKeys) : [];
_handlers[keyCode] = _handlers[keyCode].map((record) => {
// 通过函数判断,是否解除绑定,函数相等直接返回
const isMatchingMethod = method ? obj.method === method : true;

// 判断是否在范围内并且键值相同
const isMatchingMethod = method ? record.method === method : true;
if (
isMatchingMethod &&
obj.scope === scope &&
compareArray(obj.mods, mods)
record.scope === scope &&
compareArray(record.mods, mods)
) {
_handlers[key][r] = {};
return {};
}
}
}
}
return record;
});
});
};

// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
Expand All @@ -155,13 +168,19 @@ function eventHandler(event, handler, scope) {
if (
(!_mods[y] && handler.mods.indexOf(+y) > -1) ||
(_mods[y] && handler.mods.indexOf(+y) === -1)
) modifiersMatch = false;
) {
modifiersMatch = false;
}
}
}

// 调用处理程序,如果是修饰键不做处理
if (
(handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) ||
(handler.mods.length === 0 &&
!_mods[16] &&
!_mods[18] &&
!_mods[17] &&
!_mods[91]) ||
modifiersMatch ||
handler.shortcut === '*'
) {
Expand All @@ -175,7 +194,6 @@ function eventHandler(event, handler, scope) {
}
}


// 处理keydown事件
function dispatch(event) {
const asterisk = _handlers['*'];
Expand Down Expand Up @@ -218,7 +236,11 @@ function dispatch(event) {
// 对任何快捷键都需要做的处理
if (asterisk) {
for (let i = 0; i < asterisk.length; i++) {
if (asterisk[i].scope === scope && ((event.type === 'keydown' && asterisk[i].keydown) || (event.type === 'keyup' && asterisk[i].keyup))) {
if (
asterisk[i].scope === scope &&
((event.type === 'keydown' && asterisk[i].keydown) ||
(event.type === 'keyup' && asterisk[i].keyup))
) {
eventHandler(event, asterisk[i], scope);
}
}
Expand All @@ -227,17 +249,22 @@ function dispatch(event) {
if (!(key in _handlers)) return;

for (let i = 0; i < _handlers[key].length; i++) {
if ((event.type === 'keydown' && _handlers[key][i].keydown) || (event.type === 'keyup' && _handlers[key][i].keyup)) {
if (
(event.type === 'keydown' && _handlers[key][i].keydown) ||
(event.type === 'keyup' && _handlers[key][i].keyup)
) {
if (_handlers[key][i].key) {
const keyShortcut = _handlers[key][i].key.split('+');
const record = _handlers[key][i];
const { splitKey } = record;
const keyShortcut = record.key.split(splitKey);
let _downKeysCurrent = []; // 记录当前按键键值
for (let 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);
eventHandler(event, record, scope);
}
}
}
Expand All @@ -257,6 +284,7 @@ function hotkeys(key, option, method) {
let i = 0;
let keyup = false;
let keydown = true;
let splitKey = '+';

// 对为设定范围的判断
if (method === undefined && typeof option === 'function') {
Expand All @@ -268,13 +296,14 @@ function hotkeys(key, option, method) {
if (option.element) element = option.element; // eslint-disable-line
if (option.keyup) keyup = option.keyup; // eslint-disable-line
if (option.keydown !== undefined) keydown = option.keydown; // eslint-disable-line
if (typeof option.splitKey === 'string') splitKey = option.splitKey; // eslint-disable-line
}

if (typeof option === 'string') scope = option;

// 对于每个快捷键进行处理
for (; i < keys.length; i++) {
key = keys[i].split('+'); // 按键列表
key = keys[i].split(splitKey); // 按键列表
mods = [];

// 如果是组合快捷键取得组合快捷键
Expand All @@ -294,6 +323,7 @@ function hotkeys(key, option, method) {
shortcut: keys[i],
method,
key: keys[i],
splitKey,
});
}
// 在全局document上设置快捷键
Expand All @@ -312,7 +342,6 @@ function hotkeys(key, option, method) {
}
}


const _api = {
setScope,
getScope,
Expand Down
11 changes: 11 additions & 0 deletions test/run.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ describe('\n Hotkeys.js Test Case.\n', () => {
await hotkeys.unbind('command+ctrl+shift+a');
});

test('Custom splitKey Test Case', async () => {
await hotkeys('ctrl-a', {splitKey: '-'}, (e) => {
expect(e.ctrlKey).toBeTruthy();
expect(hotkeys.getPressedKeyCodes()[0]).toBe(65);
});
await __triggerKeyboardEvent(document.body, 65, {
ctrlKey: true
});
await hotkeys.unbind();
})

test('HotKeys unbind Test Case', async () => {
hotkeys('enter', (e) => {
expect(e.keyCode).toBe(13);
Expand Down