mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
moving to keyboard gen2...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
6730ec2f24
commit
ebb3fcdc39
@ -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;
|
||||||
|
|||||||
@ -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')
|
||||||
}],
|
}],
|
||||||
|
|||||||
@ -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 : ''
|
||||||
|
|||||||
@ -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)...
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user