feat: 1.版本升级
parent
1aebd6d839
commit
6556d213c1
|
@ -0,0 +1,228 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2020/10/29 16:48:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MULTI_KEY_CODES } from './key.dict.v1.js'
|
||||||
|
import { bind, unbind, hide, check, parseAction } from './utils';
|
||||||
|
|
||||||
|
class KeyboardV1 {
|
||||||
|
constructor(elem) {
|
||||||
|
this.$elem = elem
|
||||||
|
|
||||||
|
hide(this, '__EVENTS__', {})
|
||||||
|
hide(this, 'paused', false)
|
||||||
|
hide(this, '__finally__', null)
|
||||||
|
|
||||||
|
hide(
|
||||||
|
this,
|
||||||
|
'_keydown',
|
||||||
|
bind(elem, ev => {
|
||||||
|
// 允许暂停
|
||||||
|
if (this.paused) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 屏蔽纯辅助键的监听
|
||||||
|
if (MULTI_KEY_CODES.includes(ev.keyCode)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k in this.__EVENTS__) {
|
||||||
|
var item = this.__EVENTS__[k]
|
||||||
|
var res = item.check(ev)
|
||||||
|
var now = Date.now()
|
||||||
|
var end = false // 是否结束检测
|
||||||
|
|
||||||
|
// 假设之前有激活过, 优先再检测子组合
|
||||||
|
if (item.actived === true) {
|
||||||
|
// 如果超时(300毫秒)了, 则不再管子组合了
|
||||||
|
if (now - item.last > 300) {
|
||||||
|
delete item.actived
|
||||||
|
} else {
|
||||||
|
for (let next of item.next) {
|
||||||
|
let tmp = next.check(ev)
|
||||||
|
if (tmp) {
|
||||||
|
end = true
|
||||||
|
// 第2组一定有回调,无需判断
|
||||||
|
next.fn.forEach(function(fn) {
|
||||||
|
fn(ev)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第一组, 只要检测通过了, 就触发回调
|
||||||
|
if (res) {
|
||||||
|
end = true
|
||||||
|
if (item.next) {
|
||||||
|
item.actived = true
|
||||||
|
item.last = now
|
||||||
|
}
|
||||||
|
// 有回调就触发
|
||||||
|
if (item.fn) {
|
||||||
|
item.fn.forEach(function(fn) {
|
||||||
|
fn(ev)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 命中了, 后面的就不再检测了
|
||||||
|
if (end) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.__finally__) {
|
||||||
|
this.__finally__(ev)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return this.paused
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(v) {
|
||||||
|
this.paused = !!v
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
unbind(this.$elem, this._keydown)
|
||||||
|
delete this.__EVENTS__
|
||||||
|
delete this._keydown
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
off(act, callback) {
|
||||||
|
if (act.length < 1 || typeof callback !== 'function') {
|
||||||
|
return console.error('无效热键或回调')
|
||||||
|
}
|
||||||
|
|
||||||
|
let { keys, dict, passed } = parseAction(act)
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
let k1 = keys[0]
|
||||||
|
|
||||||
|
if (keys.length === 1) {
|
||||||
|
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].fn) {
|
||||||
|
let i = 0
|
||||||
|
for (let fn of this.__EVENTS__[k1].fn) {
|
||||||
|
if (fn === callback) {
|
||||||
|
this.__EVENTS__[k1].fn.splice(i, 1)
|
||||||
|
// 只剩1个, 删除fn字段
|
||||||
|
if (this.__EVENTS__[k1].fn.length < 1) {
|
||||||
|
delete this.__EVENTS__[k1].fn
|
||||||
|
|
||||||
|
// 删完fn字段, 如果没有next字段的话, 整个热键删除
|
||||||
|
if (!this.__EVENTS__[k1].next) {
|
||||||
|
delete this.__EVENTS__[k1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].next) {
|
||||||
|
let k2 = keys[1]
|
||||||
|
let i = 0
|
||||||
|
let sub
|
||||||
|
|
||||||
|
for (sub of this.__EVENTS__[k1].next) {
|
||||||
|
if (sub.id === k2) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub.fn) {
|
||||||
|
let j = 0
|
||||||
|
for (let fn of sub.fn) {
|
||||||
|
if (fn === callback) {
|
||||||
|
sub.fn.splice(j, 1)
|
||||||
|
// 如果该组的事件为空了, 则删除该组合
|
||||||
|
if (sub.fn.length < 1) {
|
||||||
|
this.__EVENTS__[k1].next.splice(i, 1)
|
||||||
|
|
||||||
|
// 第2组, 如果回调队列为空了, 直接删除整个第2组
|
||||||
|
if (this.__EVENTS__[k1].next.length < 1) {
|
||||||
|
delete this.__EVENTS__[k1].next
|
||||||
|
|
||||||
|
// 如果此时, 上一层没的回调了, 则整个热键删除
|
||||||
|
if (!this.__EVENTS__[k1].fn) {
|
||||||
|
delete this.__EVENTS__[k1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on(act, callback) {
|
||||||
|
if (act.length < 1 || typeof callback !== 'function') {
|
||||||
|
return console.error('无效热键或回调')
|
||||||
|
}
|
||||||
|
|
||||||
|
let { keys, dict, passed } = parseAction(act)
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
// 最多支持2组
|
||||||
|
let first = keys.shift()
|
||||||
|
let second = keys.shift()
|
||||||
|
|
||||||
|
if (!this.__EVENTS__[first]) {
|
||||||
|
this.__EVENTS__[first] = {
|
||||||
|
id: first,
|
||||||
|
keys: dict[0],
|
||||||
|
last: 0, //上次触发时间戳
|
||||||
|
check
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (second) {
|
||||||
|
if (this.__EVENTS__[first].next) {
|
||||||
|
for (let i = -1, it; (it = this.__EVENTS__[first].next[++i]); ) {
|
||||||
|
if (it.id === second) {
|
||||||
|
it.fn.push(callback)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.__EVENTS__[first].next = [
|
||||||
|
{
|
||||||
|
id: second,
|
||||||
|
keys: dict[1],
|
||||||
|
check,
|
||||||
|
fn: [callback]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
if (this.__EVENTS__[first].fn) {
|
||||||
|
this.__EVENTS__[first].fn.push(callback)
|
||||||
|
} else {
|
||||||
|
this.__EVENTS__[first].fn = [callback]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finally(callback) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
this.__finally__ = callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { KeyboardV1 };
|
|
@ -0,0 +1,228 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2020/10/29 16:48:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MULTI_KEY_CODES } from './key.dict.v2.js'
|
||||||
|
import { bind, unbind, hide, check, parseAction } from './utils';
|
||||||
|
|
||||||
|
class KeyboardV2 {
|
||||||
|
constructor(elem) {
|
||||||
|
this.$elem = elem
|
||||||
|
|
||||||
|
hide(this, '__EVENTS__', {})
|
||||||
|
hide(this, 'paused', false)
|
||||||
|
hide(this, '__finally__', null)
|
||||||
|
|
||||||
|
hide(
|
||||||
|
this,
|
||||||
|
'_keydown',
|
||||||
|
bind(elem, ev => {
|
||||||
|
// 允许暂停
|
||||||
|
if (this.paused) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 屏蔽纯辅助键的监听
|
||||||
|
if (MULTI_KEY_CODES.includes(ev.keyCode)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k in this.__EVENTS__) {
|
||||||
|
var item = this.__EVENTS__[k]
|
||||||
|
var res = item.check(ev)
|
||||||
|
var now = Date.now()
|
||||||
|
var end = false // 是否结束检测
|
||||||
|
|
||||||
|
// 假设之前有激活过, 优先再检测子组合
|
||||||
|
if (item.actived === true) {
|
||||||
|
// 如果超时(300毫秒)了, 则不再管子组合了
|
||||||
|
if (now - item.last > 300) {
|
||||||
|
delete item.actived
|
||||||
|
} else {
|
||||||
|
for (let next of item.next) {
|
||||||
|
let tmp = next.check(ev)
|
||||||
|
if (tmp) {
|
||||||
|
end = true
|
||||||
|
// 第2组一定有回调,无需判断
|
||||||
|
next.fn.forEach(function(fn) {
|
||||||
|
fn(ev)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第一组, 只要检测通过了, 就触发回调
|
||||||
|
if (res) {
|
||||||
|
end = true
|
||||||
|
if (item.next) {
|
||||||
|
item.actived = true
|
||||||
|
item.last = now
|
||||||
|
}
|
||||||
|
// 有回调就触发
|
||||||
|
if (item.fn) {
|
||||||
|
item.fn.forEach(function(fn) {
|
||||||
|
fn(ev)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 命中了, 后面的就不再检测了
|
||||||
|
if (end) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.__finally__) {
|
||||||
|
this.__finally__(ev)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return this.paused
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(v) {
|
||||||
|
this.paused = !!v
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
unbind(this.$elem, this._keydown)
|
||||||
|
delete this.__EVENTS__
|
||||||
|
delete this._keydown
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
off(act, callback) {
|
||||||
|
if (act.length < 1 || typeof callback !== 'function') {
|
||||||
|
return console.error('无效热键或回调')
|
||||||
|
}
|
||||||
|
|
||||||
|
let { keys, dict, passed } = parseAction(act)
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
let k1 = keys[0]
|
||||||
|
|
||||||
|
if (keys.length === 1) {
|
||||||
|
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].fn) {
|
||||||
|
let i = 0
|
||||||
|
for (let fn of this.__EVENTS__[k1].fn) {
|
||||||
|
if (fn === callback) {
|
||||||
|
this.__EVENTS__[k1].fn.splice(i, 1)
|
||||||
|
// 只剩1个, 删除fn字段
|
||||||
|
if (this.__EVENTS__[k1].fn.length < 1) {
|
||||||
|
delete this.__EVENTS__[k1].fn
|
||||||
|
|
||||||
|
// 删完fn字段, 如果没有next字段的话, 整个热键删除
|
||||||
|
if (!this.__EVENTS__[k1].next) {
|
||||||
|
delete this.__EVENTS__[k1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].next) {
|
||||||
|
let k2 = keys[1]
|
||||||
|
let i = 0
|
||||||
|
let sub
|
||||||
|
|
||||||
|
for (sub of this.__EVENTS__[k1].next) {
|
||||||
|
if (sub.id === k2) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub.fn) {
|
||||||
|
let j = 0
|
||||||
|
for (let fn of sub.fn) {
|
||||||
|
if (fn === callback) {
|
||||||
|
sub.fn.splice(j, 1)
|
||||||
|
// 如果该组的事件为空了, 则删除该组合
|
||||||
|
if (sub.fn.length < 1) {
|
||||||
|
this.__EVENTS__[k1].next.splice(i, 1)
|
||||||
|
|
||||||
|
// 第2组, 如果回调队列为空了, 直接删除整个第2组
|
||||||
|
if (this.__EVENTS__[k1].next.length < 1) {
|
||||||
|
delete this.__EVENTS__[k1].next
|
||||||
|
|
||||||
|
// 如果此时, 上一层没的回调了, 则整个热键删除
|
||||||
|
if (!this.__EVENTS__[k1].fn) {
|
||||||
|
delete this.__EVENTS__[k1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on(act, callback) {
|
||||||
|
if (act.length < 1 || typeof callback !== 'function') {
|
||||||
|
return console.error('无效热键或回调')
|
||||||
|
}
|
||||||
|
|
||||||
|
let { keys, dict, passed } = parseAction(act)
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
// 最多支持2组
|
||||||
|
let first = keys.shift()
|
||||||
|
let second = keys.shift()
|
||||||
|
|
||||||
|
if (!this.__EVENTS__[first]) {
|
||||||
|
this.__EVENTS__[first] = {
|
||||||
|
id: first,
|
||||||
|
keys: dict[0],
|
||||||
|
last: 0, //上次触发时间戳
|
||||||
|
check
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (second) {
|
||||||
|
if (this.__EVENTS__[first].next) {
|
||||||
|
for (let i = -1, it; (it = this.__EVENTS__[first].next[++i]); ) {
|
||||||
|
if (it.id === second) {
|
||||||
|
it.fn.push(callback)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.__EVENTS__[first].next = [
|
||||||
|
{
|
||||||
|
id: second,
|
||||||
|
keys: dict[1],
|
||||||
|
check,
|
||||||
|
fn: [callback]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
if (this.__EVENTS__[first].fn) {
|
||||||
|
this.__EVENTS__[first].fn.push(callback)
|
||||||
|
} else {
|
||||||
|
this.__EVENTS__[first].fn = [callback]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finally(callback) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
this.__finally__ = callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { KeyboardV2 };
|
302
src/index.es7
302
src/index.es7
|
@ -1,302 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author yutent<yutent.io@gmail.com>
|
|
||||||
* @date 2020/10/29 16:48:26
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { KEY_DICT, MULTI_KEYS, MULTI_KEY_CODES } from './key.dict.js'
|
|
||||||
|
|
||||||
function bind(el, fn) {
|
|
||||||
;(el || document).addEventListener('keydown', fn, false)
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
function unbind(el, fn) {
|
|
||||||
;(el || document).removeEventListener('keydown', fn, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide(target, name, value) {
|
|
||||||
Object.defineProperty(target, name, {
|
|
||||||
value,
|
|
||||||
writable: true,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按键检测
|
|
||||||
function check(ev) {
|
|
||||||
var checked = false
|
|
||||||
|
|
||||||
if (typeof this.keys.key === 'object') {
|
|
||||||
checked = this.keys.key.includes(ev.keyCode)
|
|
||||||
} else {
|
|
||||||
checked = ev.keyCode === this.keys.key
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checked) {
|
|
||||||
for (let k in this.keys) {
|
|
||||||
if (ev[k] !== this.keys[k]) {
|
|
||||||
checked = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return checked
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Keyboard {
|
|
||||||
constructor(elem) {
|
|
||||||
this.$elem = elem
|
|
||||||
|
|
||||||
hide(this, '__EVENTS__', {})
|
|
||||||
hide(this, 'paused', false)
|
|
||||||
hide(this, '__finally__', null)
|
|
||||||
|
|
||||||
hide(
|
|
||||||
this,
|
|
||||||
'_keydown',
|
|
||||||
bind(elem, ev => {
|
|
||||||
// 允许暂停
|
|
||||||
if (this.paused) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 屏蔽纯辅助键的监听
|
|
||||||
if (MULTI_KEY_CODES.includes(ev.keyCode)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let k in this.__EVENTS__) {
|
|
||||||
var item = this.__EVENTS__[k]
|
|
||||||
var res = item.check(ev)
|
|
||||||
var now = Date.now()
|
|
||||||
var end = false // 是否结束检测
|
|
||||||
|
|
||||||
// 假设之前有激活过, 优先再检测子组合
|
|
||||||
if (item.actived === true) {
|
|
||||||
// 如果超时(300毫秒)了, 则不再管子组合了
|
|
||||||
if (now - item.last > 300) {
|
|
||||||
delete item.actived
|
|
||||||
} else {
|
|
||||||
for (let next of item.next) {
|
|
||||||
let tmp = next.check(ev)
|
|
||||||
if (tmp) {
|
|
||||||
end = true
|
|
||||||
// 第2组一定有回调,无需判断
|
|
||||||
next.fn.forEach(function(fn) {
|
|
||||||
fn(ev)
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第一组, 只要检测通过了, 就触发回调
|
|
||||||
if (res) {
|
|
||||||
end = true
|
|
||||||
if (item.next) {
|
|
||||||
item.actived = true
|
|
||||||
item.last = now
|
|
||||||
}
|
|
||||||
// 有回调就触发
|
|
||||||
if (item.fn) {
|
|
||||||
item.fn.forEach(function(fn) {
|
|
||||||
fn(ev)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 命中了, 后面的就不再检测了
|
|
||||||
if (end) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.__finally__) {
|
|
||||||
this.__finally__(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
get disabled() {
|
|
||||||
return this.paused
|
|
||||||
}
|
|
||||||
|
|
||||||
set disabled(v) {
|
|
||||||
this.paused = !!v
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
unbind(this.$elem, this._keydown)
|
|
||||||
delete this.__EVENTS__
|
|
||||||
delete this._keydown
|
|
||||||
}
|
|
||||||
|
|
||||||
__parse_action__(act) {
|
|
||||||
var keys = []
|
|
||||||
var dict = []
|
|
||||||
var passed = true // 语法检测通过
|
|
||||||
|
|
||||||
act.forEach(it => {
|
|
||||||
var tmp = {}
|
|
||||||
|
|
||||||
it = it.split('+').map(k => {
|
|
||||||
k = k.trim().toLowerCase()
|
|
||||||
if (MULTI_KEYS[k]) {
|
|
||||||
if (tmp[`${k}Key`]) {
|
|
||||||
passed = false
|
|
||||||
console.error('功能键,同组中不能重复。⎣%s⎤', it)
|
|
||||||
} else {
|
|
||||||
tmp[`${k}Key`] = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tmp.key) {
|
|
||||||
passed = false
|
|
||||||
console.error('非功能键,同组不能出现多个。⎣%s⎤', it)
|
|
||||||
} else {
|
|
||||||
hide(tmp, 'key', KEY_DICT[k])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return k
|
|
||||||
})
|
|
||||||
|
|
||||||
for (let k in MULTI_KEYS) {
|
|
||||||
tmp[`${k}Key`] = tmp[`${k}Key`] || false
|
|
||||||
}
|
|
||||||
|
|
||||||
dict.push(tmp)
|
|
||||||
keys.push(it.join('+'))
|
|
||||||
})
|
|
||||||
|
|
||||||
return { keys, dict, passed }
|
|
||||||
}
|
|
||||||
|
|
||||||
off(act, callback) {
|
|
||||||
if (act.length < 1 || typeof callback !== 'function') {
|
|
||||||
return console.error('无效热键或回调')
|
|
||||||
}
|
|
||||||
|
|
||||||
let { keys, dict, passed } = this.__parse_action__(act)
|
|
||||||
|
|
||||||
if (passed) {
|
|
||||||
let k1 = keys[0]
|
|
||||||
|
|
||||||
if (keys.length === 1) {
|
|
||||||
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].fn) {
|
|
||||||
let i = 0
|
|
||||||
for (let fn of this.__EVENTS__[k1].fn) {
|
|
||||||
if (fn === callback) {
|
|
||||||
this.__EVENTS__[k1].fn.splice(i, 1)
|
|
||||||
// 只剩1个, 删除fn字段
|
|
||||||
if (this.__EVENTS__[k1].fn.length < 1) {
|
|
||||||
delete this.__EVENTS__[k1].fn
|
|
||||||
|
|
||||||
// 删完fn字段, 如果没有next字段的话, 整个热键删除
|
|
||||||
if (!this.__EVENTS__[k1].next) {
|
|
||||||
delete this.__EVENTS__[k1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.__EVENTS__[k1] && this.__EVENTS__[k1].next) {
|
|
||||||
let k2 = keys[1]
|
|
||||||
let i = 0
|
|
||||||
let sub
|
|
||||||
|
|
||||||
for (sub of this.__EVENTS__[k1].next) {
|
|
||||||
if (sub.id === k2) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sub.fn) {
|
|
||||||
let j = 0
|
|
||||||
for (let fn of sub.fn) {
|
|
||||||
if (fn === callback) {
|
|
||||||
sub.fn.splice(j, 1)
|
|
||||||
// 如果该组的事件为空了, 则删除该组合
|
|
||||||
if (sub.fn.length < 1) {
|
|
||||||
this.__EVENTS__[k1].next.splice(i, 1)
|
|
||||||
|
|
||||||
// 第2组, 如果回调队列为空了, 直接删除整个第2组
|
|
||||||
if (this.__EVENTS__[k1].next.length < 1) {
|
|
||||||
delete this.__EVENTS__[k1].next
|
|
||||||
|
|
||||||
// 如果此时, 上一层没的回调了, 则整个热键删除
|
|
||||||
if (!this.__EVENTS__[k1].fn) {
|
|
||||||
delete this.__EVENTS__[k1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
on(act, callback) {
|
|
||||||
if (act.length < 1 || typeof callback !== 'function') {
|
|
||||||
return console.error('无效热键或回调')
|
|
||||||
}
|
|
||||||
|
|
||||||
let { keys, dict, passed } = this.__parse_action__(act)
|
|
||||||
|
|
||||||
if (passed) {
|
|
||||||
// 最多支持2组
|
|
||||||
let first = keys.shift()
|
|
||||||
let second = keys.shift()
|
|
||||||
|
|
||||||
if (!this.__EVENTS__[first]) {
|
|
||||||
this.__EVENTS__[first] = {
|
|
||||||
id: first,
|
|
||||||
keys: dict[0],
|
|
||||||
last: 0, //上次触发时间戳
|
|
||||||
check
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (second) {
|
|
||||||
if (this.__EVENTS__[first].next) {
|
|
||||||
for (let i = -1, it; (it = this.__EVENTS__[first].next[++i]); ) {
|
|
||||||
if (it.id === second) {
|
|
||||||
it.fn.push(callback)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.__EVENTS__[first].next = [
|
|
||||||
{
|
|
||||||
id: second,
|
|
||||||
keys: dict[1],
|
|
||||||
check,
|
|
||||||
fn: [callback]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
if (this.__EVENTS__[first].fn) {
|
|
||||||
this.__EVENTS__[first].fn.push(callback)
|
|
||||||
} else {
|
|
||||||
this.__EVENTS__[first].fn = [callback]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finally(callback) {
|
|
||||||
if (typeof callback === 'function') {
|
|
||||||
this.__finally__ = callback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2020/10/29 16:48:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { KeyboardV1 } from './Keyboard.v1';
|
||||||
|
export { KeyboardV2 } from './Keyboard.v2';
|
|
@ -0,0 +1,112 @@
|
||||||
|
// 允许组合出现的辅助键
|
||||||
|
export const MULTI_KEYS = {
|
||||||
|
ctrl: 1,
|
||||||
|
shift: 1,
|
||||||
|
alt: 1,
|
||||||
|
meta: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MULTI_KEY_CODES = [200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212]
|
||||||
|
|
||||||
|
// 按键对应的code值
|
||||||
|
export const KEY_DICT = {
|
||||||
|
'0': 48, // Digit{N}, Numpad{N}
|
||||||
|
'1': 49,
|
||||||
|
'2': 50,
|
||||||
|
'3': 51,
|
||||||
|
'4': 52,
|
||||||
|
'5': 53,
|
||||||
|
'6': 54,
|
||||||
|
'7': 55,
|
||||||
|
'8': 56,
|
||||||
|
'9': 57,
|
||||||
|
"'": 222,
|
||||||
|
'*': 106,
|
||||||
|
'+': 107,
|
||||||
|
',': 188,
|
||||||
|
'-': [109, 189],
|
||||||
|
'.': [110, 190],
|
||||||
|
'/': [111, 191],
|
||||||
|
';': 186,
|
||||||
|
'=': 187,
|
||||||
|
'[': 219,
|
||||||
|
'\\': 220,
|
||||||
|
']': 221,
|
||||||
|
'`': 192,
|
||||||
|
a: 65,
|
||||||
|
b: 66,
|
||||||
|
c: 67,
|
||||||
|
d: 68,
|
||||||
|
e: 69,
|
||||||
|
f: 70,
|
||||||
|
g: 71,
|
||||||
|
h: 72,
|
||||||
|
i: 73,
|
||||||
|
j: 74,
|
||||||
|
k: 75,
|
||||||
|
l: 76,
|
||||||
|
m: 77,
|
||||||
|
n: 78,
|
||||||
|
o: 79,
|
||||||
|
p: 80,
|
||||||
|
q: 81,
|
||||||
|
r: 82,
|
||||||
|
s: 83,
|
||||||
|
t: 84,
|
||||||
|
u: 85,
|
||||||
|
v: 86,
|
||||||
|
w: 87,
|
||||||
|
x: 88,
|
||||||
|
y: 89,
|
||||||
|
z: 90,
|
||||||
|
enter: 13, // Enter, NumpadEnter
|
||||||
|
space: 32,
|
||||||
|
meta: 91, // MetaLeft, MetaRight
|
||||||
|
tab: 9,
|
||||||
|
backspace: 8,
|
||||||
|
numlock: 12,
|
||||||
|
capslock: 20,
|
||||||
|
esc: 27,
|
||||||
|
menu: 93,
|
||||||
|
insert: 45,
|
||||||
|
delete: 46,
|
||||||
|
pagedown: 34,
|
||||||
|
pageup: 33,
|
||||||
|
home: 36,
|
||||||
|
end: 35,
|
||||||
|
up: 38,
|
||||||
|
down: 40,
|
||||||
|
left: 37,
|
||||||
|
right: 39,
|
||||||
|
f1: 112,
|
||||||
|
f2: 113,
|
||||||
|
f3: 114,
|
||||||
|
f4: 115,
|
||||||
|
f5: 116,
|
||||||
|
f6: 117,
|
||||||
|
f7: 118,
|
||||||
|
f8: 119,
|
||||||
|
f9: 120,
|
||||||
|
f10: 121,
|
||||||
|
f11: 122,
|
||||||
|
f12: 123,
|
||||||
|
f13: 124, // Print键
|
||||||
|
f14: 125, // Screen键
|
||||||
|
f15: 126, // Pause键
|
||||||
|
print: 124, // Print键
|
||||||
|
screen: 125, // Screen键
|
||||||
|
pause: 126, // Pause键
|
||||||
|
|
||||||
|
shift_left: 200, // ShiftLeft
|
||||||
|
shift_right: 201, // ShiftRight
|
||||||
|
ctrl_left: 202, // ControlLeft
|
||||||
|
ctrl_right: 203, // ControlRight
|
||||||
|
alt_left: 204, // AltLeft
|
||||||
|
alt_right: 205, // AltRight
|
||||||
|
option_left: 207, // OptionLeft
|
||||||
|
option_right: 208, // OptionRight
|
||||||
|
win_left: 209, // WinLeft
|
||||||
|
win_right: 210, // WinRight
|
||||||
|
cmd_left: 211, // CmdRight
|
||||||
|
cmd_right: 212, // CmdRight
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
function bind(el, fn) {
|
||||||
|
;(el || document).addEventListener('keydown', fn, false)
|
||||||
|
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
function unbind(el, fn) {
|
||||||
|
;(el || document).removeEventListener('keydown', fn, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { bind, unbind };
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 按键检测
|
||||||
|
function check(ev) {
|
||||||
|
let checked = false
|
||||||
|
|
||||||
|
if (typeof this.keys.key === 'object') {
|
||||||
|
checked = this.keys.key.includes(ev.keyCode)
|
||||||
|
} else {
|
||||||
|
checked = ev.keyCode === this.keys.key
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
for (let k in this.keys) {
|
||||||
|
if (ev[k] !== this.keys[k]) {
|
||||||
|
checked = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return checked
|
||||||
|
}
|
||||||
|
|
||||||
|
export { check };
|
|
@ -0,0 +1,10 @@
|
||||||
|
function hide(target, name, value) {
|
||||||
|
Object.defineProperty(target, name, {
|
||||||
|
value,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export { hide };
|
|
@ -0,0 +1,4 @@
|
||||||
|
export { bind, unbind } from './bind';
|
||||||
|
export { hide } from './hide';
|
||||||
|
export { check } from './check';
|
||||||
|
export { parseAction } from './parseAction';
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {KEY_DICT, MULTI_KEYS} from "../key.dict.v1";
|
||||||
|
import {hide} from "./hide";
|
||||||
|
|
||||||
|
function parseAction(act) {
|
||||||
|
var keys = []
|
||||||
|
var dict = []
|
||||||
|
var passed = true // 语法检测通过
|
||||||
|
|
||||||
|
act.forEach(it => {
|
||||||
|
var tmp = {}
|
||||||
|
|
||||||
|
it = it.split('+').map(k => {
|
||||||
|
k = k.trim().toLowerCase()
|
||||||
|
if (MULTI_KEYS[k]) {
|
||||||
|
if (tmp[`${k}Key`]) {
|
||||||
|
passed = false
|
||||||
|
console.error('功能键,同组中不能重复。⎣%s⎤', it)
|
||||||
|
} else {
|
||||||
|
tmp[`${k}Key`] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tmp.key) {
|
||||||
|
passed = false
|
||||||
|
console.error('非功能键,同组不能出现多个。⎣%s⎤', it)
|
||||||
|
} else {
|
||||||
|
hide(tmp, 'key', KEY_DICT[k])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let k in MULTI_KEYS) {
|
||||||
|
tmp[`${k}Key`] = tmp[`${k}Key`] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
dict.push(tmp)
|
||||||
|
keys.push(it.join('+'))
|
||||||
|
})
|
||||||
|
|
||||||
|
return { keys, dict, passed }
|
||||||
|
}
|
||||||
|
|
||||||
|
export { parseAction };
|
Loading…
Reference in New Issue