made the keyhandler mode-aware...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2012-09-10 03:02:34 +04:00
parent 093ff72d5c
commit d9a59440fd
3 changed files with 218 additions and 169 deletions

View File

@ -177,9 +177,9 @@ Priority work
[X] 100% actions [X] 100% actions
[X] bug: shifting up to new ribbon pushes the current row down... [X] bug: shifting up to new ribbon pushes the current row down...
| before starting on a fix, need to cleanup the code from old hacks and workarounds... | before starting on a fix, need to cleanup the code from old hacks and workarounds...
[_] 37% Preview II (optional features) [_] 39% Preview II (optional features)
[_] 0% make things modular and reusable [_] 14% make things modular and reusable
[_] make the keyboard handler local to selector (mode-aware) [X] make the keyboard handler local to selector (mode-aware)
[_] prefix an ID to all selectors to make their actions "local" [_] prefix an ID to all selectors to make their actions "local"
[_] avoid use of id html attr [_] avoid use of id html attr
[_] avoid use of globals [_] avoid use of globals
@ -204,7 +204,6 @@ Priority work
[_] .dblclick(...) does not work... [_] .dblclick(...) does not work...
[_] .dragable(...) does not work... [_] .dragable(...) does not work...
[_] slideshow... [_] slideshow...
[_] make keyboard handler mode-aware...
| this is needed to disable navigation keys in setup-mode, for example... | this is needed to disable navigation keys in setup-mode, for example...
[X] 100% serialization/deserialization [X] 100% serialization/deserialization
[X] JSON loader/unloader [X] JSON loader/unloader

View File

@ -10,6 +10,7 @@
// - are the benefits worth the code bloat? // - are the benefits worth the code bloat?
// //
var ImageGrid = { var ImageGrid = {
// this can be serialized... // this can be serialized...
// NOTE: to load a serialized set of options use ImageGrid.set(options)... // NOTE: to load a serialized set of options use ImageGrid.set(options)...
@ -524,6 +525,8 @@ function toKeyName(code){
// XXX this must create it's own overlay... // XXX this must create it's own overlay...
function showInOverlay(obj){ function showInOverlay(obj){
obj.click(function(){ return false }) obj.click(function(){ return false })
// XXX
$('.viewer').addClass('overlay-mode')
// clean things up... // clean things up...
$('.overlay .content').children().remove() $('.overlay .content').children().remove()
// put it in the overlay... // put it in the overlay...
@ -536,6 +539,7 @@ function showInOverlay(obj){
$('.overlay .content') $('.overlay .content')
.children() .children()
.remove() .remove()
$('.overlay-mode').removeClass('overlay-mode')
}) })
}) })
.fadeIn() .fadeIn()
@ -1113,10 +1117,10 @@ function setupEvents(){
// keyboard... // keyboard...
if(DEBUG){ if(DEBUG){
$(document) $(document)
.keydown(makeKeyboardHandler(keybindings, ignorekeys, function(k){alert(k)})) .keydown(makeKeyboardHandler(keybindings, function(k){alert(k)}))
} else { } else {
$(document) $(document)
.keydown(makeKeyboardHandler(keybindings, ignorekeys)) .keydown(makeKeyboardHandler(keybindings))
} }
// swipe... // swipe...
$('.viewer') $('.viewer')
@ -1474,52 +1478,58 @@ var KEYBOARD_HANDLER_PROPAGATE = false
* *
* XXX might need to add meta information to generate sensible help... * XXX might need to add meta information to generate sensible help...
*/ */
function makeKeyboardHandler(keybindings, ignore, unhandled){ function makeKeyboardHandler(keybindings, unhandled){
if(unhandled == null){ if(unhandled == null){
unhandled = function(){return false} unhandled = function(){return false}
} }
return function(evt){ return function(evt){
var key = evt.keyCode for(var mode in keybindings){
if(ignore != null && ignore.indexOf(key) != -1){ if($(mode).length > 0){
return true var bindings = keybindings[mode]
}
// XXX ugly...
var modifers = evt.ctrlKey ? 'ctrl' : ''
modifers += evt.altKey ? (modifers != '' ? '+alt' : 'alt') : ''
modifers += evt.shiftKey ? (modifers != '' ? '+shift' : 'shift') : ''
var handler = keybindings[key] var key = evt.keyCode
if(bindings.ignore != null && bindings.ignore.indexOf(key) != -1){
return true
}
// XXX ugly...
var modifers = evt.ctrlKey ? 'ctrl' : ''
modifers += evt.altKey ? (modifers != '' ? '+alt' : 'alt') : ''
modifers += evt.shiftKey ? (modifers != '' ? '+shift' : 'shift') : ''
// alias... var handler = bindings[key]
while (typeof(handler) == typeof(123)) {
handler = keybindings[handler] // alias...
} while (typeof(handler) == typeof(123)) {
// no handler... handler = bindings[handler]
if(handler == null){ }
return unhandled(key) // no handler...
} if(handler == null){
// Array, lisp style with docs... return unhandled(key)
// XXX for some odd reason in chrome typeof([]) == typeof({})!!! }
if(typeof(handler) == typeof([]) && handler.constructor.name == 'Array'){ // Array, lisp style with docs...
// we do not care about docs here, so just get the handler... // XXX for some odd reason in chrome typeof([]) == typeof({})!!!
handler = handler[0] if(typeof(handler) == typeof([]) && handler.constructor.name == 'Array'){
} // we do not care about docs here, so just get the handler...
// complex handler... handler = handler[0]
if(typeof(handler) == typeof({})){ }
var callback = handler[modifers] // complex handler...
if(callback == null){ if(typeof(handler) == typeof({})){
callback = handler['default'] var callback = handler[modifers]
if(callback == null){
callback = handler['default']
}
if(callback != null){
var res = callback()
return KEYBOARD_HANDLER_PROPAGATE&&res?true:false
}
} else {
// simple callback...
var res = handler()
return KEYBOARD_HANDLER_PROPAGATE&&res?true:false
}
return unhandled(key)
} }
if(callback != null){
var res = callback()
return KEYBOARD_HANDLER_PROPAGATE&&res?true:false
}
} else {
// simple callback...
var res = handler()
return KEYBOARD_HANDLER_PROPAGATE&&res?true:false
} }
return unhandled(key)
} }
} }
@ -1642,6 +1652,7 @@ ImageGrid.GROUP('Configuration and Help',
}, },
function(e){return e.click_handler}) function(e){return e.click_handler})
}), }),
// XXX do not use global keybindings...
ImageGrid.ACTION({ ImageGrid.ACTION({
title: 'Keyboard configuration', title: 'Keyboard configuration',
doc: 'Show keyboard configuration interface.', doc: 'Show keyboard configuration interface.',
@ -1649,39 +1660,52 @@ ImageGrid.GROUP('Configuration and Help',
function showKeyboardBindings(){ function showKeyboardBindings(){
// build reverse key index... // build reverse key index...
var bindings = {} var bindings = {}
for(var k in keybindings){ for(var m in keybindings){
var id var mode_bindings = keybindings[m]
var v = keybindings[k]
// alias... // XXX do the doc for the mode...
while (typeof(v) == typeof(123)) { // XXX
v = keybindings[v]
} for(var k in mode_bindings){
// Array, lisp style with docs... // XXX skip doc attrs...
if(typeof(v) == typeof([]) && v.constructor.name == 'Array'){ if(k == 'title' || k == 'doc' || k == 'ignore'){
// XXX what do we do here??? continue
}
// function...
if(typeof(v) == typeof(function(){})){
id = v.id != null ? v.id : v.name
}
// complex handler...
// NOTE: this can contain several key bindings...
if(typeof(v) == typeof({})){
for(var m in v){
id = v[m].id != null ? v[m].id : v[m].name
if(bindings[id] == null){
bindings[id] = []
}
bindings[id].push((m=='default'?'':m+'+') + toKeyName(k))
} }
continue
var id
var v = mode_bindings[k]
// alias...
while (typeof(v) == typeof(123)) {
v = mode_bindings[v]
}
// Array, lisp style with docs...
if(typeof(v) == typeof([]) && v.constructor.name == 'Array'){
// XXX what do we do here???
}
// function...
if(typeof(v) == typeof(function(){})){
id = v.id != null ? v.id : v.name
}
// complex handler...
// NOTE: this can contain several key bindings...
if(typeof(v) == typeof({})){
for(var m in v){
id = v[m].id != null ? v[m].id : v[m].name
if(bindings[id] == null){
bindings[id] = []
}
bindings[id].push((m=='default'?'':m+'+') + toKeyName(k))
}
continue
}
if(bindings[id] == null){
bindings[id] = []
}
bindings[id].push(toKeyName(k))
} }
if(bindings[id] == null){
bindings[id] = []
}
bindings[id].push(toKeyName(k))
} }
showOptionsUI(ImageGrid.actions, showOptionsUI(ImageGrid.actions,
function(e){ function(e){

View File

@ -1,110 +1,136 @@
/*********************************************************************/ /*********************************************************************/
// NOTE: use String.fromCharCode(code)... // NOTE: use String.fromCharCode(code)...
// list of keys to be ignored by handler but still handled by the browser... // list of keys to be ignored by handler but still handled by the browser...
var ignorekeys = [
116, // F5
123, // F12
]
var keybindings = { var keybindings = {
// togglable modes and options... '.overlay-mode': {
191: { title: 'Overlay mode',
'default': ImageGrid.showKeyboardBindings, // ? doc: 'overlay mode key bindings.',
'ctrl': ImageGrid.showSetup, // ctrl+?
ignore: [
37, // Left
39, // Right
36, // Home
32, // Space
35, // End
38, // Up
40, // Down
],
27: ImageGrid.closeOverlay, // Esc
}, },
80: ImageGrid.showSetup, // p
70: ImageGrid.toggleSingleImageMode, // f
13: 70, // Enter
83: ImageGrid.toggleSingleRibbonMode, // s
84: ImageGrid.toggleSingleImageModeTransitions, // t
65: ImageGrid.toggleTransitions, // a
9: ImageGrid.toggleControls, // tab
66: ImageGrid.toggleBackgroundModes, // b
73: ImageGrid.toggleCurrentRibbonOpacity, // i
77: toggleMarkers, // m
87: ImageGrid.saveState, // w
27: ImageGrid.closeOverlay, // Esc //'*': {
// everything except overlays...
'.viewer *:not(.overlay-mode *)': {
title: 'ALL',
doc: 'global key bindings.',
// zooming... ignore: [
187: ImageGrid.scaleContainerUp, // + 116, // F5
189: ImageGrid.scaleContainerDown, // - 123, // F12
// zoom presets... ],
48: {
'default': ImageGrid.centerCurrentImage, // 0 // togglable modes and options...
191: {
'default': ImageGrid.showKeyboardBindings, // ?
'ctrl': ImageGrid.showSetup, // ctrl+?
},
80: ImageGrid.showSetup, // p
70: ImageGrid.toggleSingleImageMode, // f
13: 70, // Enter
83: ImageGrid.toggleSingleRibbonMode, // s
84: ImageGrid.toggleSingleImageModeTransitions, // t
65: ImageGrid.toggleTransitions, // a
9: ImageGrid.toggleControls, // tab
66: ImageGrid.toggleBackgroundModes, // b
73: ImageGrid.toggleCurrentRibbonOpacity, // i
77: toggleMarkers, // m
87: ImageGrid.saveState, // w
27: ImageGrid.closeOverlay, // Esc
// zooming...
187: ImageGrid.scaleContainerUp, // +
189: ImageGrid.scaleContainerDown, // -
// zoom presets...
48: {
'default': ImageGrid.centerCurrentImage, // 0
// XXX make this into a real action...
'ctrl': ImageGrid.fitImage, // ctrl+0
},
49: ImageGrid.fitImage, // 1
50: ImageGrid.fitTwoImages, // 2
51: ImageGrid.fitThreeImages, // 3
52: ImageGrid.fitFourImages, // 4
53: ImageGrid.fitFiveImages, // 5
54: ImageGrid.fitSixImages, // 6
55: ImageGrid.fitSevenImages, // 7
56: ImageGrid.fitEightImages, // 8
57: ImageGrid.fitNineImages, // 9
// navigation...
36: ImageGrid.firstImage, // Home
219: 36, // [
35: ImageGrid.lastImage, // End
221: 35, // ]
37: {
'default': ImageGrid.prevImage, // Right
'ctrl': ImageGrid.prevScreenImages, // ctrl-Right
'alt': ImageGrid.prevScreenImages, // alt-Right
},
8: 37, // BkSp
188: 37, // <
39: {
'default': ImageGrid.nextImage, // Left
'ctrl': ImageGrid.nextScreenImages, // ctrl-Left
'alt': ImageGrid.nextScreenImages, // alt-Left
},
32: 39, // Space
190: 39, // >
186: ImageGrid.prevScreenImages, // ;
222: ImageGrid.nextScreenImages, // '
// move view...
// XXX should these be s-up, s-down, ... ??
75: ImageGrid.moveViewUp, // k
74: ImageGrid.moveViewDown, // j
72: ImageGrid.moveViewLeft, // h
76: ImageGrid.moveViewRight, // l
// XXX use this to open...
//79: ImageGrid.centerCurrentImage, // o
// combined navigation with actions..
38: {
'default': ImageGrid.focusAboveRibbon, // Up
'shift': ImageGrid.shiftImageUp, // shift-Up
'ctrl+shift': ImageGrid.shiftImageUpNewRibbon // ctrl-shift-Up
},
40: {
'default': ImageGrid.focusBelowRibbon, // Down
'shift': ImageGrid.shiftImageDown, // shift-Down
'ctrl+shift': ImageGrid.shiftImageDownNewRibbon // ctrl-shift-Down
},
// misc actions...
82: ImageGrid.reverseImageOrder, // r
// ignore the modifiers (shift, alt, ctrl, caps)...
16: function(){},
17: 16,
18: 16,
20: 16, // Caps Lock
// refresh...
// XXX make this into a real action... // XXX make this into a real action...
'ctrl': ImageGrid.fitImage, // ctrl+0 116: function(){ return DEBUG?true:false }, // F5
}, 112: 116, // F12
49: ImageGrid.fitImage, // 1 }
50: ImageGrid.fitTwoImages, // 2
51: ImageGrid.fitThreeImages, // 3
52: ImageGrid.fitFourImages, // 4
53: ImageGrid.fitFiveImages, // 5
54: ImageGrid.fitSixImages, // 6
55: ImageGrid.fitSevenImages, // 7
56: ImageGrid.fitEightImages, // 8
57: ImageGrid.fitNineImages, // 9
// navigation...
36: ImageGrid.firstImage, // Home
219: 36, // [
35: ImageGrid.lastImage, // End
221: 35, // ]
37: {
'default': ImageGrid.prevImage, // Right
'ctrl': ImageGrid.prevScreenImages, // ctrl-Right
'alt': ImageGrid.prevScreenImages, // alt-Right
},
8: 37, // BkSp
188: 37, // <
39: {
'default': ImageGrid.nextImage, // Left
'ctrl': ImageGrid.nextScreenImages, // ctrl-Left
'alt': ImageGrid.nextScreenImages, // alt-Left
},
32: 39, // Space
190: 39, // >
186: ImageGrid.prevScreenImages, // ;
222: ImageGrid.nextScreenImages, // '
// move view...
// XXX should these be s-up, s-down, ... ??
75: ImageGrid.moveViewUp, // k
74: ImageGrid.moveViewDown, // j
72: ImageGrid.moveViewLeft, // h
76: ImageGrid.moveViewRight, // l
// XXX use this to open...
//79: ImageGrid.centerCurrentImage, // o
// combined navigation with actions..
40: {
'default': ImageGrid.focusBelowRibbon, // Down
'shift': ImageGrid.shiftImageDown, // shift-Down
'ctrl+shift': ImageGrid.shiftImageDownNewRibbon // ctrl-shift-Down
},
38: {
'default': ImageGrid.focusAboveRibbon, // Up
'shift': ImageGrid.shiftImageUp, // shift-Up
'ctrl+shift': ImageGrid.shiftImageUpNewRibbon // ctrl-shift-Up
},
// misc actions...
82: ImageGrid.reverseImageOrder, // r
// ignore the modifiers (shift, alt, ctrl, caps)...
16: function(){},
17: 16,
18: 16,
20: 16, // Caps Lock
// refresh...
// XXX make this into a real action...
116: function(){ return DEBUG?true:false }, // F5
112: 116, // F12
} }