JavaScript Key Binding Library
Tính đến
Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta
// @require https://update.greasyfork.org/scripts/23404/148849/keyboard-js.js
"use strict"
var Keyboard = (function () {
function __Keyboard() {
this.keys = {} // to record the pressed key
this.register_list = {} // to record the registers(key combos)
this.state = {} // to record every register matching condition. do you want to get this value?
this.specialKeyString = {
"altKey": "Alt",
"ctrlKey": "Control",
"metaKey": "Meta",
"shiftKey": "Shift"
}
}
__Keyboard.prototype.listen = function () {
var option = this.option, element = document
if (option.element && typeof option.element.addEventListener === 'function') {
element = option.element
}
element.addEventListener('keydown', this.keydown.bind(this), false)
element.addEventListener('keyup', this.keyup.bind(this), false)
}
__Keyboard.prototype.unlisten = function () {
// maybe you need callback?
var option = this.option, element = document
if (option.element && typeof option.element.removeEventListener === 'function') {
element = option.element
}
element.removeEventListener('keydown', function () { })
element.removeEventListener('keyup', function () { })
}
__Keyboard.prototype.test = function (event) {
return this.testRegisters(event)
}
__Keyboard.prototype.testRegisters = function (event) {
var register_list = this.register_list
var register_names = Object.keys(register_list)
var testKeys = this.testKeys.bind(this)
var state = {}
for (var i = 0, len = register_names.length; i < len; i++) {
var regName = register_names[i]
var reg = register_list[regName]
var keylist = reg[0]
var callback = reg[1]
// hit the target
if (testKeys(keylist)) {
if (callback && typeof callback === 'function') {
// TODO:
// Need event object? or context?
var __wrapper_callback = (function () {
event.clearKeys = this.clearKeys.bind(this)
// inject the event(the last key) object
callback(event)
// BUG:
// when use `alert` or `confirm`, the event(keyup) of the pressed key will lost.
// so, you will don't know the key is really pressed or not when you are back.
// here code just detects some special keys.
// SO DO NOT USE ALERT OR CONFIRM!
Array.prototype.map.call(Object.keys(this.specialKeyString), ((function (key) {
if (event[key]) this.keys[this.specialKeyString[key]] = true
}).bind(this)))
}).bind(this)
if (window.requestAnimationFrame)
window.requestAnimationFrame(__wrapper_callback)
else
setTimeout(__wrapper_callback, 16)
}
state[regName] = true
// if match successfully, return directly.
return state
}
}
return state
}
// @param keylist Array(Array) [combo1, combo2, ...]
__Keyboard.prototype.testKeys = function (keylist) {
var result = [], state = false
for (var i = 0, len = keylist.length; i < len; i++) {
var combo = keylist[i]
var allPressedkeys = Object.keys(this.keys)
var nowPressedkeys = []
var __state = 0 // no state. not true or false
// collect all pressed key now
allPressedkeys.forEach((function (value, index) {
if (this.keys[value]) nowPressedkeys.push(value)
}).bind(this))
// DEBUG: print the pressing key message
// console.log(allPressedkeys, this.keys)
if (this.option.DEBUG === true) {
var __printKey = nowPressedkeys.map(function (k, i) {
if (k === " ") return "Space"
else return k
}).join(" ")
console.log('[' + Date.now() + '] You hit key: %c' + __printKey, 'color: #ea4335; font-size: 16px')
}
// compare nowPressedkeys and combo
// console.log('compare: ', nowPressedkeys, combo)
if (nowPressedkeys.length !== combo.length) {
__state = false
} else {
for (var j = 0, len2 = combo.length; j < len2; j++) {
if (nowPressedkeys.indexOf(combo[j]) < 0) {
// not in the array
__state = false
break
}
}
// if j is equal to combo.length, this means that user hit the combo.
// otherwise, user does't.
if (j === combo.length && __state !== false) __state = true
}
result.push(__state)
}
// console.log('> result', result, this.keys)
result.forEach(function (v, i) {
if (v === true) state = true
})
return state
}
__Keyboard.prototype.keydown = function (event) {
var key = event.key, state = {}, rlt = true, map = Array.prototype.map
this.keys[key] = event.type === 'keydown'
// this.keys[key] = true
// the result of test
// true: hit the target, then prevent the default action, so return true
// otherwise, don't prevent it, so return false
state = this.test(event)
Object.keys(state).forEach(function (regName, i) {
if (state[regName] === true) rlt = false
})
this.state = state
if (!rlt) {
event.preventDefault()
event.stopPropagation()
// event.stopImmediatePropagation()
}
// console.log(rlt)
return rlt
}
__Keyboard.prototype.keyup = function (event) {
var key = event.key
this.keys[key] = false
return true
}
__Keyboard.prototype.register = function (name, callback, keylist) {
if (typeof name !== 'string') throw new Error('Please input the register name.')
if (this.register_list[name]) throw new Error('The ' + name + ' has existed!')
var keylist = Array.prototype.slice.call(arguments, 2)
if (!(keylist[0] instanceof Array)) keylist = [keylist] // init [combo1:Array, combo2:Array, ....]
this.register_list[name] = [keylist, callback]
}
__Keyboard.prototype.clearRegister = function (name) {
delete this.register_list[name]
}
__Keyboard.prototype.clearRegisterAll = function () {
this.register_list = {}
}
__Keyboard.prototype.clearKeys = function () {
this.keys = {}
}
var k = new __Keyboard()
var __instance = {
start: function () { k.listen() },
end: function () { k.unlisten(); k.clearRegisterAll(); k.clearKeys(); },
register: function () { k.register.apply(k, arguments) },
unregister: function () { k.clearRegister.apply(k, arguments) },
// for test
__keydown: function () { k.keydown.apply(k, arguments) },
__keyup: function () { k.keyup.apply(k, arguments) },
}
return function (o) {
k.option = o || {}
window.addEventListener('focus', function () {
k.keys = {}
}, false)
// window.addEventListener('blur', function () {
// k.keys = {}
// }, false)
return __instance
}
})()
if (typeof exports !== "undefined") {
exports.Keyboard = Keyboard
} else if (typeof define !== 'undefined' && typeof define === 'function') {
define("Keyboard", [], function () {
return Keyboard
})
} else {
if (window.Keyboard === undefined) window.Keyboard = Keyboard
else {
throw new Error('Library Keyboard has existed! Loaded failed.')
}
}