NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
"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.') } }