moving to keyboard gen2...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-11 00:41:35 +03:00
parent 6730ec2f24
commit ebb3fcdc39
4 changed files with 263 additions and 125 deletions

View File

@ -335,7 +335,7 @@ body {
font-weight: bold; font-weight: bold;
font-style: italic; font-style: italic;
} }
.browse-widget.key-bindings .list>.ignored .text:first-child { .browse-widget.key-bindings .list>.special-action .text:first-child {
font-style: italic; font-style: italic;
font-weight: bold; font-weight: bold;
} }
@ -359,6 +359,15 @@ body {
margin-right: 0em; margin-right: 0em;
} }
/* key doc... */
.browse-widget.key-bindings .list>.key[doc]:after {
display: inline;
content: " -- " attr(doc);
font-style: italic;
opacity: 0.5;
margin-left: 0.5em;
}
.browse-widget.key-bindings .list>.new { .browse-widget.key-bindings .list>.new {
font-style: italic; font-style: italic;

View File

@ -37,8 +37,9 @@ function customScale(n){
// XXX might be a good idea to be able ignore actions rather than keys... // XXX might be a good idea to be able ignore actions rather than keys...
// XXX add this to the global doc... // XXX add this to the global doc...
var GLOBAL_KEYBOARD = var GLOBAL_KEYBOARD =
window.GLOBAL_KEYBOARD =
module.GLOBAL_KEYBOARD = { module.GLOBAL_KEYBOARD = {
'Global':{ 'Global': {
doc: 'Global bindings that take priority over other sections.', doc: 'Global bindings that take priority over other sections.',
pattern: '*', pattern: '*',
@ -409,6 +410,7 @@ var keyboard2 = require('lib/keyboard2')
// XXX do we want to add sub-sections to better organize keys for // XXX do we want to add sub-sections to better organize keys for
// documentation??? // documentation???
var GLOBAL_KEYBOARD2 = var GLOBAL_KEYBOARD2 =
window.GLOBAL_KEYBOARD2 =
module.GLOBAL_KEYBOARD2 = { module.GLOBAL_KEYBOARD2 = {
'Global': { 'Global': {
doc: 'Global bindings that take priority over other sections.', doc: 'Global bindings that take priority over other sections.',
@ -452,13 +454,9 @@ module.GLOBAL_KEYBOARD2 = {
], ],
// NOTE: these are here so as to enable handling via the next // handle in next section...
// block, i.e. the Viewer '(': 'NEXT_SECTION',
// ...if not given, then the ignore above will shadow the ')': 'NEXT_SECTION',
// keys...
// NOTE: the 'nop' action does not exist, this it will get ignored
'(': 'nop',
')': 'nop',
// zooming... // zooming...
'#1': 'fitScreen', '#1': 'fitScreen',
@ -503,8 +501,8 @@ module.GLOBAL_KEYBOARD2 = {
// ignore sorting and reversing... // ignore sorting and reversing...
// XXX not sure about these yet, especially reversing... // XXX not sure about these yet, especially reversing...
shift_R: 'IGNORE', shift_R: 'DROP',
shift_S: 'IGNORE', shift_S: 'DROP',
}, },
// XXX add "save as collection..." // XXX add "save as collection..."
@ -749,6 +747,7 @@ module.GLOBAL_KEYBOARD2 = {
// NOTE: this stops the default: handler from getting the ctrl: // NOTE: this stops the default: handler from getting the ctrl:
// key case... // key case...
ctrl_C: '', ctrl_C: '',
ctrl_V: '',
// sort... // sort...
@ -771,8 +770,8 @@ module.GLOBAL_KEYBOARD2 = {
} }
//keyboard = keyboard2 keyboard = keyboard2
//GLOBAL_KEYBOARD = GLOBAL_KEYBOARD2 GLOBAL_KEYBOARD = GLOBAL_KEYBOARD2
window.kb = keyboard2.Keyboard(GLOBAL_KEYBOARD2, keyboard2.checkGlobalMode) window.kb = keyboard2.Keyboard(GLOBAL_KEYBOARD2, keyboard2.checkGlobalMode)
@ -808,8 +807,11 @@ var KeyboardActions = actions.Actions({
'keyboard-event-source': 'window', 'keyboard-event-source': 'window',
}, },
get keyboard(){ // XXX do we need these as wrappers???
get keybindigs(){
return this.__keyboard_config }, return this.__keyboard_config },
get keyboard(){
return this.__keyboard_object },
pauseKeyboardRepeat: ['- Interface/', pauseKeyboardRepeat: ['- Interface/',
function(){ function(){
@ -839,6 +841,25 @@ var KeyboardActions = actions.Actions({
return true return true
}).bind(this) }).bind(this)
//* XXX gen2
var kb = this.__keyboard_object =
this.__keyboard_object
|| keyboard.Keyboard(
function(){ return that.__keyboard_config },
function(mode, keyboard, context){
var pattern = keyboard[mode].pattern || mode
var target = that.ribbons.viewer
return !pattern
|| pattern == '*'
// XXX legacy...
//|| $(pattern).length > 0
// XXX can we join these into one search???
|| target.is(pattern)
|| target.find(pattern).length > 0
})
kb.service_fields = kb.constructor.service_fields.concat(['pattern'])
//*/
// start/reset keyboard handling... // start/reset keyboard handling...
if(state == 'on'){ if(state == 'on'){
var that = this var that = this
@ -866,7 +887,8 @@ var KeyboardActions = actions.Actions({
this.__keyboard_handler = this.__keyboard_handler =
keyboard.stoppableKeyboardRepeat( keyboard.stoppableKeyboardRepeat(
keyboard.makeKeyboardHandler( keyboard.makeKeyboardHandler(
function(){ return that.__keyboard_config }, this.keyboard,
//function(){ return that.__keyboard_config },
function(k){ window.DEBUG && console.log('KEY:', k) }, function(k){ window.DEBUG && console.log('KEY:', k) },
this), this),
check) check)
@ -879,7 +901,8 @@ var KeyboardActions = actions.Actions({
keyboard.stoppableKeyboardRepeat( keyboard.stoppableKeyboardRepeat(
keyboard.dropRepeatingkeys( keyboard.dropRepeatingkeys(
keyboard.makeKeyboardHandler( keyboard.makeKeyboardHandler(
function(){ return that.__keyboard_config }, this.keyboard,
//function(){ return that.__keyboard_config },
function(k){ window.DEBUG && console.log(k) }, function(k){ window.DEBUG && console.log(k) },
this), this),
function(){ function(){
@ -896,6 +919,7 @@ var KeyboardActions = actions.Actions({
&& this.__keyboard_event_source && this.__keyboard_event_source
.off('keydown', this.__keyboard_handler) .off('keydown', this.__keyboard_handler)
//delete this.__keyboard_object
delete this.__keyboard_handler delete this.__keyboard_handler
delete this.__keyboard_event_source delete this.__keyboard_event_source
} }
@ -914,54 +938,46 @@ var KeyboardActions = actions.Actions({
// XXX this does not check overloading between modes... // XXX this does not check overloading between modes...
getKeysForAction: ['- Interface/', getKeysForAction: ['- Interface/',
function(actions, modes){ function(actions, modes){
var that = this
actions = actions == '*' ? null : actions actions = actions == '*' ? null : actions
actions = !actions || actions instanceof Array ? actions : [actions] actions = !actions || actions instanceof Array ? actions : [actions]
modes = modes || null modes = modes || null
modes = !modes || modes instanceof Array ? modes : [modes] modes = !modes || modes instanceof Array ? modes : [modes]
modes = modes || this.getKeyboardModes() modes = modes || this.keyboard.modes()
var keys = this.keyboard.keys('*')
// XXX does this handle overloading???
var help = keyboard.buildKeybindingsHelp(
this.keyboard,
null,
this,
// get full doc compatible with get path...
function(action, args){
// NOTE: we do not care about the actual args
// here, all we need is for this to mismatch
// if args exist...
//return args.length == 0 ? Object.keys(this.getPath(action))[0] : '--' })
return args.length == 0 ? action : '--' })
var res = {} var res = {}
// build the result... // build the result...
Object.keys(help) Object.keys(keys)
// filter modes... // filter modes...
.filter(function(mode){ return modes.indexOf(mode) >= 0 }) .filter(function(mode){ return modes.indexOf(mode) >= 0 })
.forEach(function(mode){ .forEach(function(mode){
Object.keys(help[mode]) Object.keys(keys[mode])
// parse the actions...
// NOTE: this will ignore the no_defaults flag...
.map(function(action){
action = keyboard.parseActionCall(action.doc || action)
return (action.arguments.length == 0
&& action.action in that) ?
action.action
: '--'})
// keep only the actions given... // keep only the actions given...
.filter(function(action){ .filter(function(action){
return action != '--' return action != '--'
&& action != 'doc'
&& (!actions && (!actions
|| actions.indexOf(action) >= 0) || actions.indexOf(action) >= 0)
}) })
.forEach(function(action){ .forEach(function(action){
res[action] = (res[action] || []).concat(help[mode][action]) res[action] = (res[action] || []).concat(keys[mode][action])
}) })
}) })
return res return res
}], }],
// XXX argument #3 is not yet used (see: lib/keyboard.js)...
getKeyboardModes: ['- Interface/',
function(){
return this.__keyboard_event_source ?
keyboard.getApplicableModes(this.keyboard, null, this.__keyboard_event_source)
: [] }],
// XXX need to pre-process the docs... // XXX need to pre-process the docs...
// - remove the path component... // - remove the path component...
@ -1008,37 +1024,19 @@ var KeyboardActions = actions.Actions({
browseKeyboardBindings: ['Interface/Keyboard bindings...', browseKeyboardBindings: ['Interface/Keyboard bindings...',
widgets.makeUIDialog(function(path, edit){ widgets.makeUIDialog(function(path, edit){
var actions = this var actions = this
var keybindigs = this.keybindigs
// Format: var keys = this.keyboard.keys('*')
// {
// <mode>: {
// <action-code>: [ <key>, ... ],
// ...
// },
// ...
// }
var keys = keyboard.buildKeybindingsHelp(
this.keyboard,
null,
this,
// get full doc compatible with get path...
function(action, args, no_default, doc){
return action
+ (no_default ? '!' : '')
+ (args.length > 0 ?
': '+ args.map(JSON.stringify).join(' ')
: '')
})
var dialog = browse.makeLister(null, var dialog = browse.makeLister(null,
function(path, make){ function(path, make){
Object.keys(keys) Object.keys(keybindigs)
.forEach(function(mode){ .forEach(function(mode){
var ignored = actions.keyboard[mode].ignore || [] var dropped = keybindigs[mode].drop || []
var bound_ignored = [] var bound_ignored = []
// section heading... // section heading...
make(keys[mode].doc ? make(keybindigs[mode].doc ?
$('<span>') $('<span>')
// NOTE: at this time adding a br // NOTE: at this time adding a br
// is faster and simpler than // is faster and simpler than
@ -1047,7 +1045,7 @@ var KeyboardActions = actions.Actions({
.html(mode + '<br>') .html(mode + '<br>')
.append($('<span>') .append($('<span>')
.addClass('doc') .addClass('doc')
.html(keys[mode].doc)) .html(keybindigs[mode].doc))
: mode, : mode,
{ {
not_filtered_out: true, not_filtered_out: true,
@ -1058,30 +1056,45 @@ var KeyboardActions = actions.Actions({
// bindings... // bindings...
var c = 0 var c = 0
Object.keys(keys[mode]).forEach(function(action){ Object.keys(keys[mode] || {}).forEach(function(action){
action != 'doc'
var o = keyboard.parseActionCall(action)
var doc = o.doc
var code = o.action
+ (o.no_default ? '!' : '')
+ (o.arguments.length > 0 ?
(': '+ o.arguments.map(JSON.stringify).join(' '))
: '')
// NOTE: wee need the button spec to be // NOTE: wee need the button spec to be
// searchable, thus we are not using // searchable, thus we are not using
// the keys attr as in .browseActions(..) // the keys attr as in .browseActions(..)
&& make([action, ' ', '$BUTTONS'] make([code, ' ', '$BUTTONS']
.concat($('<span>') .concat($('<span>')
.addClass('text') .addClass('text')
.html(keys[mode][action] .html(keys[mode][action]
// mark key if it is in ignored... // mark key if it is in dropped...
.map(function(s){ .map(function(s){
s = s.split('+') s = s.split('+')
var k = s.pop() var k = s.pop()
var i = ignored.indexOf(k) var i = dropped.indexOf(k)
i >= 0 i >= 0
&& bound_ignored && bound_ignored
.push(ignored[i]) .push(dropped[i])
s.push(k s.push(k
+ (i >= 0 ? '<sup>*</sup>' : '')) + (i >= 0 ? '<sup>*</sup>' : ''))
return s.join('+') }) return s.join('+') })
.join(' / ')))) .join(' / '))))
.attr('doc',
doc.trim() != '' ?
doc
: (actions.keyboard.special_handlers[action]
|| null))
.addClass('key ' .addClass('key '
+ (action == 'IGNORE' ? 'ignored' : '')) + (action in actions.keyboard.special_handlers ?
&& c++ 'special-action'
: ''))
c++
}) })
// no keys in view mode... // no keys in view mode...
@ -1102,7 +1115,7 @@ var KeyboardActions = actions.Actions({
// together in path... // together in path...
' ', ' ',
'$BUTTONS', '$BUTTONS',
ignored dropped
.filter(function(k){ .filter(function(k){
return bound_ignored.indexOf(k) == -1 }) return bound_ignored.indexOf(k) == -1 })
.join(' / ')]) .join(' / ')])
@ -1211,8 +1224,8 @@ var KeyboardActions = actions.Actions({
: shift_modifiers +'+'+ shift_key : shift_modifiers +'+'+ shift_key
var any = modes == 'any' var any = modes == 'any'
modes = any ? this.getKeyboardModes() modes = any ? this.keyboard.modes()
: modes == '*' ? Object.keys(this.keyboard) : modes == '*' ? Object.keys(this.keybindigs)
: modes : modes
modes = modes instanceof Array ? modes : [modes] modes = modes instanceof Array ? modes : [modes]
@ -1225,7 +1238,7 @@ var KeyboardActions = actions.Actions({
return false return false
} }
var i = that.keyboard[mode].ignore || [] var i = that.keybindigs[mode].ignore || []
ignore = i.indexOf(full_key) >= 0 ignore = i.indexOf(full_key) >= 0
|| i.indexOf(key) >= 0 || i.indexOf(key) >= 0
@ -1250,7 +1263,7 @@ var KeyboardActions = actions.Actions({
return false return false
} }
var bindings = that.keyboard[mode] var bindings = that.keybindigs[mode]
if(action){ if(action){
var match = 'direct' var match = 'direct'
@ -1322,7 +1335,7 @@ var KeyboardActions = actions.Actions({
res[mode] = handler res[mode] = handler
} }
ignore = any && handler == 'IGNORE' ignore = any && handler == 'DROP'
} }
}) })
@ -1343,7 +1356,7 @@ var KeyboardActions = actions.Actions({
+ (args.length > 0 ? + (args.length > 0 ?
': '+ args.map(JSON.stringify).join(' ') ': '+ args.map(JSON.stringify).join(' ')
: '') : '')
var bindings = this.keyboard[mode] var bindings = this.keybindigs[mode]
var alias = code in bindings ? code : key var alias = code in bindings ? code : key
var handler = bindings[key] || bindings[code] var handler = bindings[key] || bindings[code]
@ -1391,7 +1404,7 @@ module.Keyboard = core.ImageGridFeatures.Feature({
['start', ['start',
function(){ function(){
var that = this var that = this
this.__keyboard_config = this.keyboard || GLOBAL_KEYBOARD this.__keyboard_config = this.keybindigs || GLOBAL_KEYBOARD
this.toggleKeyboardHandling('on') this.toggleKeyboardHandling('on')
}], }],

View File

@ -945,6 +945,7 @@ var BrowseActionsActions = actions.Actions({
}).bind(this) }).bind(this)
// Tree builder... // Tree builder...
// XXX normalize actions -- whitespace, '!', args...
var buildTree = function(path, leaf, action, mode, tree){ var buildTree = function(path, leaf, action, mode, tree){
path = path.slice() path = path.slice()
// build leaf... // build leaf...
@ -1062,7 +1063,8 @@ var BrowseActionsActions = actions.Actions({
disabled: mode == 'hidden' || mode == 'disabled', disabled: mode == 'hidden' || mode == 'disabled',
hidden: mode == 'hidden', hidden: mode == 'hidden',
}) })
.attr('keys', getKeys(action)) // XXX need to normalize state -- comments, whitespace, etc...
.attr('keys', getKeys(action +': "'+ state +'"'))
.addClass([ .addClass([
state == cur_state ? 'selected highlighted' : '', state == cur_state ? 'selected highlighted' : '',
mode == 'hidden' ? mode : '' mode == 'hidden' ? mode : ''

View File

@ -310,6 +310,10 @@ var KeyboardHandlerClassPrototype = {
var KeyboardHandlerPrototype = { var KeyboardHandlerPrototype = {
//service_fields: ['doc', 'drop'], //service_fields: ['doc', 'drop'],
special_handlers: {
DROP: 'drop key',
NEXT_SECTION: 'handle key in next section',
},
// Format: // Format:
// { // {
@ -384,16 +388,26 @@ var KeyboardHandlerPrototype = {
// NOTE: to match several compatible handlers, pass a list of handlers, // NOTE: to match several compatible handlers, pass a list of handlers,
// the result for each will be merged into one common list. // the result for each will be merged into one common list.
// //
// XXX passing a list of handlers will yield a single list of kyes... // Format:
// ...should this list be split into handlers??? // {
// <mode>: {
// <handler>: [ <key>, ... ],
// ...
// },
// ...
// }
//
keys: function(handler){ keys: function(handler){
var that = this var that = this
var res = {} var res = {}
var keyboard = this.keyboard var keyboard = this.keyboard
var key_separators = KEY_SEPARATORS var key_separators = KEY_SEPARATORS
handler = arguments.length > 1 ? [].slice.call(arguments) handler = arguments.length > 1 ? [].slice.call(arguments)
: handler == '*' || handler instanceof Function ? handler
: handler instanceof Array ? handler : handler instanceof Array ? handler
: [handler] : [handler]
var service_fields = this.service_fields
|| this.constructor.service_fields
var walkAliases = function(res, rev, bindings, key, mod){ var walkAliases = function(res, rev, bindings, key, mod){
mod = mod || [] mod = mod || []
@ -415,36 +429,123 @@ var KeyboardHandlerPrototype = {
// build a reverse index... // build a reverse index...
var rev = {} var rev = {}
// XXX this will not work for handlers that are not strings... // NOTE: this will not work for handlers that are not strings
Object.keys(bindings).forEach(function(key){ // and have no .doc...
rev[bindings[key]] = (rev[bindings[key]] || []).concat([key]) Object.keys(bindings)
.filter(function(key){
return service_fields.indexOf(key) < 0 })
.forEach(function(key){
var h = bindings[key]
h = typeof(h) == typeof('str') ? h
: (h.doc || h.name)
rev[h] = (rev[h] || [])
.concat((rev[bindings[key]] || []).concat([key]))
.unique()
}) })
var keys = [] var seen = []
handler.forEach(function(h){ var handlers = handler == '*' ? Object.keys(rev)
keys = keys.concat((rev[h] || []).map(that.normalizeKey.bind(that))) : handler instanceof Function ?
}) Object.keys(rev)
.filter(handler)
: handler
handlers
.forEach(function(h){
var keys = (rev[h] || []).map(that.normalizeKey.bind(that))
// find all reachable keys from the ones we just found in reverse... // find all reachable keys from the ones we just found in reverse...
keys.slice().forEach(function(key){ keys.slice()
.filter(function(key){ return seen.indexOf(key) < 0 })
.forEach(function(key){
// direct aliases...
walkAliases(keys, rev, bindings, key) walkAliases(keys, rev, bindings, key)
var mod = that.splitKey(key) var mod = that.splitKey(key)
var k = mod.pop() var k = mod.pop()
// aliases with modifiers...
k != key k != key
&& walkAliases(keys, rev, bindings, k, mod) && walkAliases(keys, rev, bindings, k, mod)
seen.push(seen)
}) })
if(keys.length > 0){ if(keys.length > 0){
res[mode] = keys var m = res[mode] = res[mode] || {}
m[h] = keys
} }
}) })
})
return res return res
}, },
// get/set handler for key... // Get/set/unset handler for key...
//
// In general if handler is not passed this will get the handlers,
// if a handler is given this will set the handler, if the passed
// handler is either null or '' then it will be unbound.
//
// Get handler for key in all modes...
// .handler(key)
// .handler('*', key)
// -> key-spec
//
// Get handlers for key in applicable modes...
// .handler('?', key)
// .handler('test', key)
// -> key-spec
//
// Get handler for key in a specific mode...
// .handler(mode, key)
// -> key-spec
//
// Get handler for key in a specific list of modes...
// .handler([mode, ..], key)
// -> key-spec
//
//
// Bind handler to key in specific mode...
// .handler(mode, key, handler)
// -> this
//
// Bind handler to key in all modes...
// .handler('*', key, handler)
// -> this
//
// Bind handler to key in applicable modes...
// .handler('?', key, handler)
// .handler('test', key, handler)
// -> this
//
// Bind handler to key in a specific list of modes...
// .handler([mode, ..], key, handler)
// -> this
//
//
// Unbind handler from key in specific mode...
// .handler(mode, key, null)
// .handler(mode, key, '')
// -> this
//
// Unbind handler from key in all modes...
// .handler('*', key, null)
// .handler('*', key, '')
// -> this
//
// Unbind handler from key in applicable modes...
// .handler('?', key, null)
// .handler('?', key, '')
// .handler('test', key, null)
// .handler('test', key, '')
// -> this
//
// Unbind handler from key in a specific list of modes...
// .handler([mode, ..], key, null)
// .handler([mode, ..], key, '')
// -> this
//
// //
// Search order: // Search order:
// - search for full key // - search for full key
@ -456,11 +557,21 @@ var KeyboardHandlerPrototype = {
// - if an alias is found it is first checked with and then // - if an alias is found it is first checked with and then
// without modifiers // without modifiers
// //
// XXX getting '(' yields a different result from 'shift-#9'
handler: function(mode, key, handler){ handler: function(mode, key, handler){
var that = this var that = this
var keyboard = this.keyboard var keyboard = this.keyboard
var key_separators = KEY_SEPARATORS var key_separators = KEY_SEPARATORS
if(arguments.length == 0){
return null
}
if(arguments.length == 1 && this.isKey(mode)){
key = mode
mode = '*'
}
var genKeys = function(key, shift_key){ var genKeys = function(key, shift_key){
// match candidates... // match candidates...
return key_separators return key_separators
@ -506,7 +617,7 @@ var KeyboardHandlerPrototype = {
// get modes... // get modes...
var modes = mode == '*' ? Object.keys(keyboard) var modes = mode == '*' ? Object.keys(keyboard)
: mode == 'applicable' || mode == '?' ? this.modes() : mode == 'test' || mode == '?' ? this.modes()
: mode instanceof Array ? mode : mode instanceof Array ? mode
: [mode] : [mode]
@ -524,7 +635,7 @@ var KeyboardHandlerPrototype = {
// .concat([k, c]) // .concat([k, c])
.unique() .unique()
var drop = mode == 'applicable' || mode == '?' var drop = mode == 'test' || mode == '?'
for(var i=0; i < modes.length; i++){ for(var i=0; i < modes.length; i++){
var m = modes[i] var m = modes[i]
@ -543,8 +654,8 @@ var KeyboardHandlerPrototype = {
mod) mod)
} }
// handle explicit IGNORE... // handle explicit DROP...
if(drop && handler == 'IGNORE'){ if(drop && handler == 'DROP'){
break break
} }
@ -555,6 +666,8 @@ var KeyboardHandlerPrototype = {
// if key in .drop then ignore the rest... // if key in .drop then ignore the rest...
if(drop if(drop
// explicit go to next section...
&& handler != 'NEXT_SECTION'
&& (bindings.drop == '*' && (bindings.drop == '*'
// XXX should this be more flexible by adding a // XXX should this be more flexible by adding a
// specific key combo? // specific key combo?
@ -567,7 +680,7 @@ var KeyboardHandlerPrototype = {
} }
return (typeof(mode) == typeof('str') return (typeof(mode) == typeof('str')
&& ['*', 'applicable', '?'].indexOf(mode) < 0) ? && ['*', 'test', '?'].indexOf(mode) < 0) ?
res[mode] res[mode]
: res : res
@ -638,7 +751,7 @@ function makeKeyboardHandler(keyboard, unhandled, actions){
var did_handling = false var did_handling = false
var key = kb.event2key(evt) var key = kb.event2key(evt)
var handlers = kb.handler('applicable', key) var handlers = kb.handler('test', key)
Object.keys(handlers).forEach(function(mode){ Object.keys(handlers).forEach(function(mode){
if(res === false){ if(res === false){
@ -669,6 +782,7 @@ function makeKeyboardHandler(keyboard, unhandled, actions){
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// handler wrappers...
// Event handler wrapper to stop handling keys if check callback does // Event handler wrapper to stop handling keys if check callback does
// not pass (returns false)... // not pass (returns false)...