combokeys
Version:
Handles keyboard shortcuts in the browser
88 lines (77 loc) • 2.93 kB
JavaScript
/* eslint-env node, browser */
/**
* finds all callbacks that match based on the keycode, modifiers,
* and action
*
* @param {string} character
* @param {Array} modifiers
* @param {Event|Object} e
* @param {string=} sequenceName - name of the sequence we are looking for
* @param {string=} combination
* @param {number=} level
* @returns {Array}
*/
module.exports = function (character, modifiers, e, sequenceName, combination, level) {
var self = this
var j
var callback
var matches = []
var action = e.type
var isModifier
var modifiersMatch
if (
action === 'keypress' &&
// Firefox fires keypress for arrows
!(e.code && e.code.slice(0, 5) === 'Arrow')
) {
// 'any-character' callbacks are only on `keypress`
var anyCharCallbacks = self.callbacks['any-character'] || []
anyCharCallbacks.forEach(function (callback) {
matches.push(callback)
})
}
if (!self.callbacks[character]) { return matches }
isModifier = require('../../helpers/isModifier')
// if a modifier key is coming up on its own we should allow it
if (action === 'keyup' && isModifier(character)) {
modifiers = [character]
}
// loop through all callbacks for the key that was pressed
// and see if any of them match
for (j = 0; j < self.callbacks[character].length; ++j) {
callback = self.callbacks[character][j]
// if a sequence name is not specified, but this is a sequence at
// the wrong level then move onto the next match
if (!sequenceName && callback.seq && self.sequenceLevels[callback.seq] !== callback.level) {
continue
}
// if the action we are looking for doesn't match the action we got
// then we should keep going
if (action !== callback.action) {
continue
}
// if this is a keypress event and the meta key and control key
// are not pressed that means that we need to only look at the
// character, otherwise check the modifiers as well
//
// chrome will not fire a keypress if meta or control is down
// safari will fire a keypress if meta or meta+shift is down
// firefox will fire a keypress if meta or control is down
modifiersMatch = require('./modifiersMatch')
if ((action === 'keypress' && !e.metaKey && !e.ctrlKey) || modifiersMatch(modifiers, callback.modifiers)) {
// when you bind a combination or sequence a second time it
// should overwrite the first one. if a sequenceName or
// combination is specified in this call it does just that
//
// @todo make deleting its own method?
var deleteCombo = !sequenceName && callback.combo === combination
var deleteSequence = sequenceName && callback.seq === sequenceName && callback.level === level
if (deleteCombo || deleteSequence) {
self.callbacks[character].splice(j, 1)
}
matches.push(callback)
}
}
return matches
}