tweaking, refactoring and .keyHandler(..) action/event (experimental)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-12 21:23:16 +03:00
parent c8645d3f6f
commit 3c4b538b7a
3 changed files with 155 additions and 61 deletions

View File

@ -69,8 +69,8 @@ module.GLOBAL_KEYBOARD2 = {
// handle in next section...
'(': 'NEXT_SECTION',
')': 'NEXT_SECTION',
'(': 'NEXT',
')': 'NEXT',
// zooming...
'#1': 'fitScreen',
@ -388,21 +388,6 @@ module.GLOBAL_KEYBOARD2 = {
//---------------------------------------------------------------------
/*/ XXX DEBUG: remove when done...
window.kb = keyboard.Keyboard(
GLOBAL_KEYBOARD,
function checkGlobalMode(mode, keyboard, context){
var pattern = keyboard[mode].pattern
return !pattern
|| pattern == '*'
|| $(keyboard[mode].pattern).length > 0 })
//*/
/*********************************************************************/
// XXX add loading/storing of kb bindings...
@ -429,6 +414,14 @@ var KeyboardActions = actions.Actions({
// the handler by cycling the toggler off and on...
// NOTE: the target element must be focusable...
'keyboard-event-source': 'window',
// If true enable .keyPressed(..) action calling on keyboard
// activity...
//
// NOTE: if updated the keyboard handler will need to be restarted
// for changes to take effect.
// XXX EXPERIMENTAL
'keyboard-key-pressed-action': false,
},
get keybindings(){
@ -569,6 +562,8 @@ var KeyboardActions = actions.Actions({
toggleKeyboardHandling: ['- Interface/Keyboard handling',
toggler.Toggler(null, function(_, state){
var that = this
if(state == null){
return this.__keyboard_handler ? 'on' : 'off'
}
@ -591,6 +586,24 @@ var KeyboardActions = actions.Actions({
return true
}).bind(this)
// pass keys pressed to .keyPressed(..) action...
// XXX EXPERIMENTAL...
var keyPressdCall = function(handler){
return that.config['keyboard-key-pressed-action'] ?
function(evt){
var e = that.keyPressed.pre(
that,
[keyboard.joinKey(keyboard.event2key(evt))])
var res = handler.apply(that, arguments)
e.result = res
that.keyPressed.post(that, e)
return res
}
: handler
}
var kb = this.__keyboard_object =
this.__keyboard_object
|| keyboard.KeyboardWithCSSModes(
@ -599,8 +612,6 @@ var KeyboardActions = actions.Actions({
// start/reset keyboard handling...
if(state == 'on'){
var that = this
// NOTE: the target element must be focusable...
var target =
this.__keyboard_event_source =
@ -611,41 +622,35 @@ var KeyboardActions = actions.Actions({
: $(this.config['keyboard-event-source'])
// need to reset...
if(this.__keyboard_handler != null){
target.off('keydown', this.__keyboard_handler)
}
this.__keyboard_handler
&& target.off('keydown', this.__keyboard_handler)
// make the base handler...
var handler =
keyboard.stoppableKeyboardRepeat(
// XXX EXPERIMENTAL...
keyPressdCall(
keyboard.makeKeyboardHandler(
this.keyboard,
function(k){ window.DEBUG && console.log('KEY:', k) },
this)),
check)
// setup base keyboard for devel, in case something breaks...
// This branch does not drop keys...
if(this.config['max-key-repeat-rate'] < 0
|| this.config['max-key-repeat-rate'] == null){
//this.ribbons.viewer
var handler =
this.__keyboard_handler =
keyboard.stoppableKeyboardRepeat(
keyboard.makeKeyboardHandler(
this.keyboard,
//function(){ return that.__keyboard_config },
function(k){ window.DEBUG && console.log('KEY:', k) },
this),
check)
this.__keyboard_handler = handler
// drop keys if repeating too fast...
// NOTE: this is done for smoother animations...
} else {
var handler =
handler =
this.__keyboard_handler =
keyboard.stoppableKeyboardRepeat(
keyboard.dropRepeatingkeys(
keyboard.makeKeyboardHandler(
this.keyboard,
//function(){ return that.__keyboard_config },
function(k){ window.DEBUG && console.log(k) },
this),
function(){
return that.config['max-key-repeat-rate']
}),
check)
keyboard.dropRepeatingkeys(
handler,
function(){
return that.config['max-key-repeat-rate'] })
}
target.keydown(handler)
@ -663,6 +668,21 @@ var KeyboardActions = actions.Actions({
},
['on', 'off'])],
// XXX EXPERIMENTAL: event for actions to be able to handle keys...
// ...not working yet...
// XXX not sure if we need this...
// ...the main reason being that this may be a way to bypass the
// .keyboard handler and config and handle keys within an action
// if overdone this can be a mess...
keyPressed: ['- Interface/Key pressed event',
'This is called by the keyboard handler when a key is pressed, '
+'the key is passed as argument.',
core.notUserCallable(function(key){
// This is the keyboard hook protocol root function
//
// Not for direct use.
})],
// interface stuff...
@ -715,7 +735,7 @@ var KeyboardActions = actions.Actions({
{
not_filtered_out: true,
// XXX should sections be searchable???
//not_searchable: true,
not_searchable: true,
})
.addClass('mode')

View File

@ -182,7 +182,12 @@ function event2key(evt){
evt.altKey && key.push('alt')
evt.metaKey && key.push('meta')
evt.shiftKey && key.push('shift')
key.push(code2key(evt.keyCode))
var k = code2key(evt.keyCode)
// add the key if it's not already in, this can happen if we just
// pressed a modifier key...
key.indexOf(k.toLowerCase()) < 0 && key.push(k)
return key
}
@ -241,6 +246,12 @@ function splitKey(key){
.concat(sep.indexOf(key.slice(-1)) >= 0 ? key.slice(-1) : [])
.filter(function(c){ return c != '' }) }
var joinKey =
module.joinKey =
function joinKey(key){
return key instanceof Array ?
key.join(KEY_SEPARATORS[0] || '+')
: key }
// Normalize key string/array...
//
@ -276,7 +287,7 @@ function normalizeKey(key){
return output == 'array' ?
key
: key.join(KEY_SEPARATORS[0] || '+')
: joinKey(key)
}
@ -305,7 +316,7 @@ function shifted(key){
return s == null ? null
: output == 'string' ?
res.join(KEY_SEPARATORS[0] || '+')
joinKey(res)
: res
}
@ -314,6 +325,63 @@ function shifted(key){
/*********************************************************************/
// Generic keyboard handler...
//
// Key binding format:
// {
// <section-title>: {
// doc: <section-doc>,
//
// // list of keys to drop after this section is done.
// //
// // Setting this to '*' will drop all keys...
// //
// // NOTE: these keys will be handled in current section.
// // NOTE: these keys will not get propagated to the next
// // matching section...
// // NOTE: it is possible to override this and explicitly pass
// // a key to the next section via 'NEXT' (see below).
// drop: [ <key>, ... ] | '*',
//
// // Key mapped to action...
// //
// // NOTE: the system poses no restrictions on action format,
// // but it is recommended to stick to strings or use the
// // doc(..) wrapper...
// <key>: <action>,
//
// // Key mapped to an alias...
// //
// // An alias is any string that is also a key in bindings, it
// // can be just a string or a key, when matching the string of
// // aliases will be resolved till either an action (non-alias)
// // is found or a loop is detected.
// //
// // NOTE: in case of a loop, nothing will get called...
// <key>: <alias> | <key>,
//
// // Alias-action mapping...
// <alias>: <action>,
//
// // Explicitly drop key...
// //
// // NOTE: this is similar in effect to .drop
// <key>: 'DROP',
//
// // Explicitly pass key to next section...
// //
// // This can be useful when it is needed to drop all keys
// // except for a small sub-group, this can be dune by setting
// // .drop to '*' (drop all) and explicitly setting the keys to
// // be propagated to 'NEXT'.
// //
// // NOTE: his takes precedence over .drop
// <key>: 'NEXT',
//
// ...
// },
// ...
// }
//
var KeyboardClassPrototype = {
service_fields: ['doc', 'drop'],
@ -323,6 +391,7 @@ var KeyboardClassPrototype = {
code2key: code2key,
isKey: isKey,
splitKey: splitKey,
joinKey: joinKey,
normalizeKey: normalizeKey,
shifted: shifted
}
@ -331,7 +400,7 @@ var KeyboardPrototype = {
//service_fields: ['doc', 'drop'],
special_handlers: {
DROP: 'drop key',
NEXT_SECTION: 'handle key in next section',
NEXT: 'handle key in next section',
},
// Format:
@ -349,11 +418,11 @@ var KeyboardPrototype = {
// }
//
// Reserved special handlers:
// - DROP - drop checking of key
// NOTE: this will prevent handling next sections
// for this key.
// - NEXT_SECTION - force check next section, this has priority
// over .drop
// - DROP - drop checking of key
// NOTE: this will prevent handling next sections
// for this key.
// - NEXT - force check next section, this has priority
// over .drop
//
__keyboard: null,
get keyboard(){
@ -372,6 +441,7 @@ var KeyboardPrototype = {
code2key: KeyboardClassPrototype.code2key,
shifted: KeyboardClassPrototype.shifted,
splitKey: KeyboardClassPrototype.splitKey,
joinKey: KeyboardClassPrototype.joinKey,
normalizeKey: KeyboardClassPrototype.normalizeKey,
isKey: KeyboardClassPrototype.isKey,
@ -435,10 +505,10 @@ var KeyboardPrototype = {
mod = mod || []
if(key in rev){
rev[key].forEach(function(k){
k = that.normalizeKey(mod
.concat(that.splitKey(k))
.unique()
.join(key_separators[0]))
k = that.normalizeKey(
that.joinKey(mod
.concat(that.splitKey(k))
.unique()))
res.indexOf(k) < 0
&& res.push(k)
&& walkAliases(res, rev, bindings, k, mod)
@ -688,7 +758,7 @@ var KeyboardPrototype = {
// if key in .drop then ignore the rest...
if(drop
// explicit go to next section...
&& handler != 'NEXT_SECTION'
&& handler != 'NEXT'
&& (bindings.drop == '*'
// XXX should this be more flexible by adding a
// specific key combo?

View File

@ -380,6 +380,10 @@ var BrowserPrototype = {
// keep text editing action from affecting the selection...
drop: '*',
// XXX not sure about this...
Up: 'NEXT',
Down: 'NEXT',
Enter: 'push!',
Esc: 'update!',
},
@ -400,8 +404,8 @@ var BrowserPrototype = {
// keep text editing action from affecting the selection...
drop: '*',
Up: 'NEXT_SECTION',
Down: 'NEXT_SECTION',
Up: 'NEXT',
Down: 'NEXT',
Enter: 'push!',
Esc: 'stopFilter!',