mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +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