mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
working on DOM navigation...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
14e711400a
commit
878c866f3f
@ -23,6 +23,7 @@ var collections = require('features/collections')
|
|||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
|
// XXX might be a good idea to normalize key spec values here...
|
||||||
var GLOBAL_KEYBOARD =
|
var GLOBAL_KEYBOARD =
|
||||||
module.GLOBAL_KEYBOARD = {
|
module.GLOBAL_KEYBOARD = {
|
||||||
// NOTE: the order of sections is important, it determines in what
|
// NOTE: the order of sections is important, it determines in what
|
||||||
@ -417,6 +418,7 @@ module.GLOBAL_KEYBOARD = {
|
|||||||
|
|
||||||
// marking...
|
// marking...
|
||||||
M: 'toggleMark',
|
M: 'toggleMark',
|
||||||
|
Ins: 'toggleMark',
|
||||||
ctrl_A: 'markRibbon!',
|
ctrl_A: 'markRibbon!',
|
||||||
ctrl_shift_A: 'markLoaded!',
|
ctrl_shift_A: 'markLoaded!',
|
||||||
ctrl_D: 'unmarkRibbon!',
|
ctrl_D: 'unmarkRibbon!',
|
||||||
|
|||||||
@ -511,6 +511,8 @@ var KeyboardPrototype = {
|
|||||||
return this.__keyboard instanceof Function ?
|
return this.__keyboard instanceof Function ?
|
||||||
this.__keyboard()
|
this.__keyboard()
|
||||||
: this.__keyboard },
|
: this.__keyboard },
|
||||||
|
// XXX might be a good idea to normalize the value here...
|
||||||
|
// ...i.e. normalize key specs as they are input by humans...
|
||||||
set keyboard(value){
|
set keyboard(value){
|
||||||
if(this.__keyboard instanceof Function){
|
if(this.__keyboard instanceof Function){
|
||||||
this.__keyboard(value)
|
this.__keyboard(value)
|
||||||
@ -898,6 +900,8 @@ var KeyboardPrototype = {
|
|||||||
// - shifted keys first
|
// - shifted keys first
|
||||||
// - modifiers are skipped in order, left to right
|
// - modifiers are skipped in order, left to right
|
||||||
// XXX carefully revise key search order...
|
// XXX carefully revise key search order...
|
||||||
|
// XXX should we normalize what's in the bindings????
|
||||||
|
// ...currently we will match 'Ins' but not 'insert'
|
||||||
var keyCombinations = function(key, shift_key, remove_single_keys){
|
var keyCombinations = function(key, shift_key, remove_single_keys){
|
||||||
if(key.length <= 1){
|
if(key.length <= 1){
|
||||||
//return shift_key ? [key, shift_key] : [key]
|
//return shift_key ? [key, shift_key] : [key]
|
||||||
|
|||||||
@ -3451,6 +3451,11 @@ var BrowserPrototype = {
|
|||||||
// NOTE: when no element is selected, 'next' will select the
|
// NOTE: when no element is selected, 'next' will select the
|
||||||
// first, while 'prev' the last element's
|
// first, while 'prev' the last element's
|
||||||
//
|
//
|
||||||
|
// Navigate to element above/below current element...
|
||||||
|
// .navigate('up')
|
||||||
|
// .navigate('down')
|
||||||
|
// -> elem
|
||||||
|
//
|
||||||
// Deselect element...
|
// Deselect element...
|
||||||
// .navigate('none')
|
// .navigate('none')
|
||||||
// -> elem
|
// -> elem
|
||||||
|
|||||||
@ -1689,6 +1689,11 @@ var BaseBrowserPrototype = {
|
|||||||
// -> item
|
// -> item
|
||||||
// -> undefined
|
// -> undefined
|
||||||
//
|
//
|
||||||
|
// Get parent element relative to focused...
|
||||||
|
// .get('parent'[, func][, options])
|
||||||
|
// -> item
|
||||||
|
// -> undefined
|
||||||
|
//
|
||||||
// Get first item matching pattern...
|
// Get first item matching pattern...
|
||||||
// .get(pattern[, func][, options])
|
// .get(pattern[, func][, options])
|
||||||
// -> item
|
// -> item
|
||||||
@ -1756,12 +1761,57 @@ var BaseBrowserPrototype = {
|
|||||||
b.length > offset
|
b.length > offset
|
||||||
&& b.shift() },
|
&& b.shift() },
|
||||||
options)
|
options)
|
||||||
|
// get parent element...
|
||||||
|
: pattern == 'parent' ?
|
||||||
|
this.parentOf()
|
||||||
// base case -> get first match...
|
// base case -> get first match...
|
||||||
: this.search(pattern,
|
: this.search(pattern,
|
||||||
function(elem, i, path, stop){
|
function(elem, i, path, stop){
|
||||||
stop([func(elem, i, path)]) },
|
stop([func(elem, i, path)]) },
|
||||||
options) ].flat()[0] },
|
options) ].flat()[0] },
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get parent of .focused
|
||||||
|
// .parentOf()
|
||||||
|
// .parentOf('focused'[, ..])
|
||||||
|
// -> parent
|
||||||
|
// -> this
|
||||||
|
// -> undefined
|
||||||
|
//
|
||||||
|
// Get parent of elem
|
||||||
|
// .parentOf(elem[, ..])
|
||||||
|
// -> parent
|
||||||
|
// -> this
|
||||||
|
// -> undefined
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Return values:
|
||||||
|
// - element - actual parent element
|
||||||
|
// - this - input element is at root of browser
|
||||||
|
// - undefined - element not found
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// NOTE: this is signature compatible with .get(..) see that for more
|
||||||
|
// docs...
|
||||||
|
//
|
||||||
|
// XXX should this be a part of .get(..)???
|
||||||
|
parentOf: function(item, options){
|
||||||
|
var that = this
|
||||||
|
item = item || this.focused
|
||||||
|
|
||||||
|
var fargs = [...arguments].slice(1)
|
||||||
|
var args = fargs[0] instanceof Function ?
|
||||||
|
fargs.slice(1)
|
||||||
|
: fargs
|
||||||
|
|
||||||
|
return item ?
|
||||||
|
this.get(item,
|
||||||
|
function(e, i, p){
|
||||||
|
return p.length > 1 ?
|
||||||
|
that.get(p.slice(0, -1), ...fargs)
|
||||||
|
: that },
|
||||||
|
...args)
|
||||||
|
: undefined },
|
||||||
|
|
||||||
// Sublist map functions...
|
// Sublist map functions...
|
||||||
// XXX this does not include inlined sections, should it???
|
// XXX this does not include inlined sections, should it???
|
||||||
@ -2153,6 +2203,8 @@ var BaseBrowserPrototype = {
|
|||||||
// of actual rendering should lay on the renderer methods...
|
// of actual rendering should lay on the renderer methods...
|
||||||
// NOTE: currently options and context are distinguished only via
|
// NOTE: currently options and context are distinguished only via
|
||||||
// the .options attribute...
|
// the .options attribute...
|
||||||
|
//
|
||||||
|
// XXX use partial render for things like search....
|
||||||
render: function(options, renderer, context){
|
render: function(options, renderer, context){
|
||||||
context = context || {}
|
context = context || {}
|
||||||
renderer = renderer || this
|
renderer = renderer || this
|
||||||
@ -2723,6 +2775,7 @@ var BrowserPrototype = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// XXX STUB...
|
||||||
__keyboard_config: {
|
__keyboard_config: {
|
||||||
General: {
|
General: {
|
||||||
pattern: '*',
|
pattern: '*',
|
||||||
@ -2733,13 +2786,14 @@ var BrowserPrototype = {
|
|||||||
Down: 'next',
|
Down: 'next',
|
||||||
|
|
||||||
// XXX use left/right...
|
// XXX use left/right...
|
||||||
Left: 'collapse',
|
Left: 'left',
|
||||||
Right: 'expand',
|
Right: 'right',
|
||||||
|
|
||||||
Enter: 'open',
|
Enter: 'open',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
//__keyboard_config: null,
|
//__keyboard_config: null,
|
||||||
get keybindings(){
|
get keybindings(){
|
||||||
return this.__keyboard_config },
|
return this.__keyboard_config },
|
||||||
@ -2790,9 +2844,11 @@ var BrowserPrototype = {
|
|||||||
|
|
||||||
// Element renderers...
|
// Element renderers...
|
||||||
//
|
//
|
||||||
// This does tow additional things:
|
// This also does:
|
||||||
// - save the rendered state to .dom
|
// - save the rendered state to .dom
|
||||||
// - wrap a list of nodes (nested list) in a div
|
// - wrap a list of nodes (nested list) in a div
|
||||||
|
// - setup event handling
|
||||||
|
// - init state...
|
||||||
//
|
//
|
||||||
// Format:
|
// Format:
|
||||||
// if list of items passed:
|
// if list of items passed:
|
||||||
@ -2813,16 +2869,26 @@ var BrowserPrototype = {
|
|||||||
c.appendChild(e) })
|
c.appendChild(e) })
|
||||||
d = c
|
d = c
|
||||||
}
|
}
|
||||||
|
|
||||||
d.setAttribute('tabindex', '0')
|
d.setAttribute('tabindex', '0')
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
d.addEventListener('keydown',
|
d.addEventListener('keydown',
|
||||||
keyboard.makeKeyboardHandler(this.keyboard,
|
keyboard.makePausableKeyboardHandler(this.keyboard,
|
||||||
function(){ console.log('KEY:', ...arguments) },//null,
|
function(){ console.log('KEY:', ...arguments) },//null,
|
||||||
this))
|
this))
|
||||||
|
|
||||||
this.dom = d
|
this.dom = d
|
||||||
|
|
||||||
|
// keep focus where it is...
|
||||||
|
var focused = this.focused
|
||||||
|
focused
|
||||||
|
&& (focused.dom.classList.contains('list') ?
|
||||||
|
focused.dom.querySelector('.item')
|
||||||
|
: focused.dom)
|
||||||
|
// XXX this will trigger the focus event...
|
||||||
|
// ...can we do this without triggering new events???
|
||||||
|
.focus()
|
||||||
|
|
||||||
return this.dom
|
return this.dom
|
||||||
},
|
},
|
||||||
//
|
//
|
||||||
@ -3057,7 +3123,11 @@ var BrowserPrototype = {
|
|||||||
//elem.addEventListener('tap',
|
//elem.addEventListener('tap',
|
||||||
// function(){ $(elem).trigger('open', [text, item, elem]) })
|
// function(){ $(elem).trigger('open', [text, item, elem]) })
|
||||||
elem.addEventListener('focus',
|
elem.addEventListener('focus',
|
||||||
function(){ that.focus(item) })
|
function(){
|
||||||
|
// do not retrigger focus on an item if it's already focused...
|
||||||
|
// XXX do we handle focus after blur???
|
||||||
|
that.focused !== item
|
||||||
|
&& that.focus(item) })
|
||||||
// user events...
|
// user events...
|
||||||
Object.entries(item.events || {})
|
Object.entries(item.events || {})
|
||||||
// shorthand events...
|
// shorthand events...
|
||||||
@ -3099,38 +3169,101 @@ var BrowserPrototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// Custom events...
|
// Custom events handlers...
|
||||||
// XXX do we use jQuery event handling or vanilla?
|
//
|
||||||
// ...feels like jQuery here wins as it provides a far simpler
|
|
||||||
// API + it's a not time critical area...
|
|
||||||
// ....another idea is to force the user to use the provided API
|
|
||||||
// by not implementing ANY direct functionality in DOM -- I do
|
|
||||||
// not like this idea at this point as it violates POLS...
|
|
||||||
__focus__: function(evt, elem){
|
__focus__: function(evt, elem){
|
||||||
elem.dom.classList.contains('list') ?
|
;(elem.dom.classList.contains('list') ?
|
||||||
elem.dom.querySelector('.item').focus()
|
elem.dom.querySelector('.item')
|
||||||
: elem.dom.focus() },
|
: elem.dom)
|
||||||
__select__: function(){},
|
.focus() },
|
||||||
__deselect__: function(){},
|
|
||||||
__expand__: function(){
|
// XXX add support for pixel offset...
|
||||||
this.focused
|
// XXX
|
||||||
&& this.focus(this.focused) },
|
get: function(pattern){
|
||||||
__collapse__: function(){
|
var p = pattern
|
||||||
this.focused
|
pattern = arguments[0] =
|
||||||
&& this.focus(this.focused) },
|
// DOM element...
|
||||||
|
// XXX should we also check for content???
|
||||||
|
pattern instanceof HTMLElement ?
|
||||||
|
function(e){ return e.dom === p }
|
||||||
|
// jQuery object...
|
||||||
|
// XXX should we also check for content???
|
||||||
|
: (typeof(jQuery) != 'undefined' && pattern instanceof jQuery) ?
|
||||||
|
function(e){ return p.is(e.dom) }
|
||||||
|
: pattern
|
||||||
|
return pattern == 'pagetop' ?
|
||||||
|
// XXX
|
||||||
|
false
|
||||||
|
: pattern == 'pagebottom' ?
|
||||||
|
// XXX
|
||||||
|
false
|
||||||
|
// call parent...
|
||||||
|
: object.parent(BrowserPrototype.get, this).call(this, ...arguments) },
|
||||||
|
|
||||||
// Navigation...
|
// Navigation...
|
||||||
//
|
//
|
||||||
|
// hold key repeat on first/last elements...
|
||||||
|
next: function(){
|
||||||
|
object.parent(BrowserPrototype.next, this).call(this, ...arguments)
|
||||||
|
// hold repeat at last element...
|
||||||
|
this.focused === this.get('last')
|
||||||
|
&& this.keyboard.pauseRepeat
|
||||||
|
&& this.keyboard.pauseRepeat() },
|
||||||
|
prev: function(){
|
||||||
|
object.parent(BrowserPrototype.prev, this).call(this, ...arguments)
|
||||||
|
// hold repeat at first element...
|
||||||
|
this.focused === this.get('first')
|
||||||
|
&& this.keyboard.pauseRepeat
|
||||||
|
&& this.keyboard.pauseRepeat() },
|
||||||
|
|
||||||
|
// XXX focus element above/below...
|
||||||
up: function(){},
|
up: function(){},
|
||||||
down: function(){},
|
down: function(){},
|
||||||
left: function(){},
|
// XXX check if there are elements to the left...
|
||||||
right: function(){},
|
left: function(){
|
||||||
|
var focused = this.focused
|
||||||
|
var p
|
||||||
|
if(!focused){
|
||||||
|
return this.prev() }
|
||||||
|
// collapsable -> collapse...
|
||||||
|
;(focused.children && !focused.collapsed) ?
|
||||||
|
this.collapse()
|
||||||
|
// on a nested level -> go up one level...
|
||||||
|
: (p = this.parentOf()) && p !== this ?
|
||||||
|
this.focus(p)
|
||||||
|
// prev...
|
||||||
|
: this.prev()
|
||||||
|
},
|
||||||
|
// XXX check if there are elements to the right...
|
||||||
|
right: function(){
|
||||||
|
var focused = this.focused
|
||||||
|
if(!focused){
|
||||||
|
return this.next() }
|
||||||
|
focused.collapsed ?
|
||||||
|
this
|
||||||
|
.expand()
|
||||||
|
.next()
|
||||||
|
: this.next() },
|
||||||
|
|
||||||
//next: function(){},
|
// navigation relative to page...
|
||||||
//prev: function(){},
|
pageTop: function(){
|
||||||
|
this.focus(this.get('pagetop')) },
|
||||||
|
pageBottom: function(){
|
||||||
|
this.focus(this.get('pagebottom')) },
|
||||||
|
// XXX
|
||||||
|
pageUp: function(){
|
||||||
|
var ref = this.get('pagetop')
|
||||||
|
// XXX get element closest to pageHeight above top...
|
||||||
|
var target = null
|
||||||
|
this.scrollTo(target)
|
||||||
|
},
|
||||||
|
// XXX should we scroll to the bottom elem (current behavior) or to the one after it???
|
||||||
|
pageDown: function(){
|
||||||
|
this.scrollTo(this.get('pagebottom')) },
|
||||||
|
|
||||||
//collapse: function(){},
|
|
||||||
// XXX scroll...
|
// XXX scroll...
|
||||||
|
scrollTo: function(elem){
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user