| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var toggler = require('../toggler') | 
					
						
							|  |  |  | var keyboard = require('../keyboard') | 
					
						
							|  |  |  | var object = require('../object') | 
					
						
							|  |  |  | var widget = require('./widget') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2019-02-05 18:25:23 +03:00
										 |  |  | // Helpers...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | // Collect a list of literal values and "make(..) calls" into an array...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	collectItems(context, items)
 | 
					
						
							|  |  |  | //		-> values
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // items format:
 | 
					
						
							|  |  |  | // 	[
 | 
					
						
							|  |  |  | // 		// explicit value...
 | 
					
						
							|  |  |  | // 		value,
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// literal make call...
 | 
					
						
							|  |  |  | // 		make(..),
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		...
 | 
					
						
							|  |  |  | // 	]
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-02-05 18:25:23 +03:00
										 |  |  | // NOTE: this will remove the made via make(..) items from .items thus the
 | 
					
						
							|  |  |  | // 		caller is responsible for adding them back...
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | // NOTE: this uses the make(..) return value to implicitly infer the items
 | 
					
						
							|  |  |  | // 		to collect, thus the items must already be constructed and in 
 | 
					
						
							|  |  |  | // 		the same order as they are present in .items
 | 
					
						
							|  |  |  | // 		...also, considering that this implicitly identifies the items 
 | 
					
						
							|  |  |  | // 		passing the make function without calling it can trick the system
 | 
					
						
							|  |  |  | // 		and lead to unexpected results.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX would be nice to have a better check/test...
 | 
					
						
							|  |  |  | // 		...this could be done by chaining instances of make instead of 
 | 
					
						
							|  |  |  | // 		returning an actual function, i.e. each make call would return 
 | 
					
						
							|  |  |  | // 		a "new" function that would reference the actual item (.item())
 | 
					
						
							|  |  |  | // 		and the previous item created (.prevItem()), ... etc.
 | 
					
						
							|  |  |  | // 		...this would enable us to uniquely identify the actual items 
 | 
					
						
							|  |  |  | // 		and prevent allot of specific errors...
 | 
					
						
							|  |  |  | var collectItems = function(context, items){ | 
					
						
							| 
									
										
										
										
											2019-02-05 18:25:23 +03:00
										 |  |  | 	var made = items | 
					
						
							|  |  |  | 		.filter(function(e){ | 
					
						
							|  |  |  | 			return e === context }) | 
					
						
							|  |  |  | 	// constructed item list...
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 	// ...remove each instance from .items
 | 
					
						
							|  |  |  | 	made = context.items.splice( | 
					
						
							|  |  |  | 		context.items.length - made.length,  | 
					
						
							|  |  |  | 		made.length) | 
					
						
							| 
									
										
										
										
											2019-02-05 18:25:23 +03:00
										 |  |  | 	// get the actual item values...
 | 
					
						
							|  |  |  | 	return items | 
					
						
							|  |  |  | 		.map(function(e){ | 
					
						
							|  |  |  | 			return e === context ? | 
					
						
							|  |  |  | 				made.shift() | 
					
						
							|  |  |  | 				: e }) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | // XXX general design:
 | 
					
						
							|  |  |  | // 		- each of these can take either a value or a function (constructor)
 | 
					
						
							|  |  |  | //		- the function has access to Items.* and context
 | 
					
						
							|  |  |  | //		- the constructor can be called from two contexts:
 | 
					
						
							|  |  |  | //			- external
 | 
					
						
							|  |  |  | //				called from the module or as a function...
 | 
					
						
							|  |  |  | //				calls the passed constructor (passing context)
 | 
					
						
							|  |  |  | //				builds the container
 | 
					
						
							|  |  |  | //			- nested
 | 
					
						
							|  |  |  | //				called from constructor function...
 | 
					
						
							|  |  |  | //				calls constructor (if applicable)
 | 
					
						
							|  |  |  | //				builds item(s)
 | 
					
						
							|  |  |  | // XXX need a way to pass container constructors (a-la ui-widgets dialog containers)
 | 
					
						
							|  |  |  | // 		- passing through the context (this) makes this more flexible...
 | 
					
						
							|  |  |  | // 		- passing via args fixes the signature which is a good thing...
 | 
					
						
							|  |  |  | //		
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX
 | 
					
						
							| 
									
										
										
										
											2019-02-10 18:09:08 +03:00
										 |  |  | // XXX can't use Object.assign(..) here as it will not copy props...
 | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | var Items = module.items = function(){} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | // placeholders...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | Items.dialog = null | 
					
						
							|  |  |  | Items.items = null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-04 14:18:00 +03:00
										 |  |  | // Last item created...
 | 
					
						
							|  |  |  | // XXX not sure about this...
 | 
					
						
							|  |  |  | // XXX should this be a prop???
 | 
					
						
							|  |  |  | Items.last = function(){ | 
					
						
							|  |  |  | 	return (this.items || [])[this.items.length - 1] } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 07:10:49 +03:00
										 |  |  | // Focus last created item...
 | 
					
						
							|  |  |  | Items.focus = function(){ | 
					
						
							| 
									
										
										
										
											2019-02-10 18:09:08 +03:00
										 |  |  | 	this.last().current = true } | 
					
						
							| 
									
										
										
										
											2019-01-23 05:45:50 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-04 14:18:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | // Group a set of items...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	.group(make(..), ..)
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | //	.group([make(..), ..])
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | //		-> make
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | // Example:
 | 
					
						
							|  |  |  | // 	make.group(
 | 
					
						
							| 
									
										
										
										
											2019-02-02 18:45:14 +03:00
										 |  |  | // 		make('made item'),
 | 
					
						
							| 
									
										
										
										
											2019-02-05 18:25:23 +03:00
										 |  |  | // 		'literal item',
 | 
					
						
							|  |  |  | // 		...)
 | 
					
						
							| 
									
										
										
										
											2019-01-23 05:45:50 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // NOTE: see notes to collectItems(..) for more info...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | // XXX do we need to pass options to groups???
 | 
					
						
							|  |  |  | Items.group = function(...items){ | 
					
						
							| 
									
										
										
										
											2019-01-26 22:34:56 +03:00
										 |  |  | 	var that = this | 
					
						
							| 
									
										
										
										
											2019-02-04 14:18:00 +03:00
										 |  |  | 	items = items.length == 1 && items[0] instanceof Array ? | 
					
						
							|  |  |  | 		items[0] | 
					
						
							|  |  |  | 		: items | 
					
						
							| 
									
										
										
										
											2019-01-26 22:34:56 +03:00
										 |  |  | 	// replace the items with the group...
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 	this.items.splice(this.items.length, 0, ...collectItems(this, items)) | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	return this | 
					
						
							| 
									
										
										
										
											2019-01-23 05:45:50 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-22 07:10:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Place list in a sub-list of item...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | Items.nest = function(item, list, options){ | 
					
						
							|  |  |  | 	options = options || {} | 
					
						
							| 
									
										
										
										
											2019-02-04 14:18:00 +03:00
										 |  |  | 	options.sublist = list instanceof Array ? | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		collectItems(this, list) | 
					
						
							| 
									
										
										
										
											2019-02-04 14:18:00 +03:00
										 |  |  | 		: list | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	return this(item, options) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 07:10:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // wrappers...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 18:11:36 +03:00
										 |  |  | Items.Item = function(value, options){} | 
					
						
							|  |  |  | Items.Action = function(value, options){} | 
					
						
							|  |  |  | Items.Heading = function(value, options){} | 
					
						
							| 
									
										
										
										
											2019-01-20 05:39:47 +03:00
										 |  |  | Items.Empty = function(value){} | 
					
						
							|  |  |  | Items.Separator = function(value){} | 
					
						
							|  |  |  | Items.Spinner = function(value){} | 
					
						
							|  |  |  | Items.Selected = function(value){} | 
					
						
							|  |  |  | Items.Editable = function(value){} | 
					
						
							|  |  |  | Items.ConfirmAction = function(value){} | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // lists...
 | 
					
						
							| 
									
										
										
										
											2019-02-05 18:11:36 +03:00
										 |  |  | Items.List = function(values){} | 
					
						
							| 
									
										
										
										
											2019-01-20 05:39:47 +03:00
										 |  |  | Items.EditableList = function(values){} | 
					
						
							|  |  |  | Items.EditablePinnedList = function(values){} | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-20 05:39:47 +03:00
										 |  |  | // Special list components...
 | 
					
						
							|  |  |  | Items.ListPath = function(){} | 
					
						
							|  |  |  | Items.ListTitle = function(){} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-25 03:34:21 +03:00
										 |  |  | // Generate an event method...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Trigger an event
 | 
					
						
							|  |  |  | //	.event()
 | 
					
						
							|  |  |  | //	.event(arg, ..)
 | 
					
						
							|  |  |  | //		-> this
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Bind an event handler...
 | 
					
						
							|  |  |  | //	.event(func)
 | 
					
						
							|  |  |  | //		-> this
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX should this be simply a shorthand to .trigger(..) ???
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | var makeEventMethod = function(event, handler){ | 
					
						
							|  |  |  | 	return function(item){ | 
					
						
							|  |  |  | 		if(item instanceof Function){ | 
					
						
							|  |  |  | 			return this.on(event, item)  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 		// XXX STUG: event object...
 | 
					
						
							|  |  |  | 		// XXX can we generate this in one spot???
 | 
					
						
							|  |  |  | 		// 		...currently it is generated here and in .trigger(..)
 | 
					
						
							|  |  |  | 		var evt = { | 
					
						
							|  |  |  | 			name: event, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		// XXX handle more of the API???
 | 
					
						
							| 
									
										
										
										
											2019-02-26 01:38:47 +03:00
										 |  |  | 		handler | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 			&& handler.call(this, evt, ...arguments) | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 		// XXX we should get the actual item and pass it on...
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 		this.trigger(evt, ...arguments) | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-25 03:34:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | var BaseBrowserClassPrototype = { | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | // XXX need a way to identify items...
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | var BaseBrowserPrototype = { | 
					
						
							|  |  |  | 	// XXX should we mix item/list options or separate them into sub-objects???
 | 
					
						
							|  |  |  | 	options: null, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	[
 | 
					
						
							|  |  |  | 	// 		<item> | <browser>,
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	]
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// <item> format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							| 
									
										
										
										
											2019-01-25 20:19:33 +03:00
										 |  |  | 	// 		value: ...,
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// NOTE: this can't be a map/dict as we need both order manipulation 
 | 
					
						
							|  |  |  | 	// 		and nested structures which would overcomplicate things, as 
 | 
					
						
							|  |  |  | 	// 		a compromise we use .item_index blow for item identification.
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	__items: null, | 
					
						
							|  |  |  | 	get items(){ | 
					
						
							|  |  |  | 		this.__items | 
					
						
							|  |  |  | 			|| this.make() | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		return this.__items }, | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	set items(value){ | 
					
						
							|  |  |  | 		this.__items = value }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		<key>: <item>,
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX need to maintain this over item add/remove/change...
 | 
					
						
							|  |  |  | 	// XXX Q: should we be able to add/remove/change items outside of .__list__(..)???
 | 
					
						
							|  |  |  | 	// 		...only some item updates (how .collapsed is handled) make 
 | 
					
						
							| 
									
										
										
										
											2019-02-20 16:30:40 +03:00
										 |  |  | 	// 		sense at this time -- need to think about this more 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// 		carefully + strictly document the result...
 | 
					
						
							|  |  |  | 	item_index: null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-28 20:13:01 +03:00
										 |  |  | 	// XXX what should these return??? (item, id, ...)
 | 
					
						
							|  |  |  | 	__focused: undefined, | 
					
						
							|  |  |  | 	get focused(){ | 
					
						
							|  |  |  | 		return this.__focused  | 
					
						
							|  |  |  | 			|| (this.__focused = this | 
					
						
							|  |  |  | 				// XXX should we simple bailout when we find an item???
 | 
					
						
							|  |  |  | 				.filter(function(e){ | 
					
						
							|  |  |  | 					return e.focused })[0]) }, | 
					
						
							|  |  |  | 	set focused(value){ | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__selected: null, | 
					
						
							|  |  |  | 	get selected(){ | 
					
						
							|  |  |  | 		return this.__selected  | 
					
						
							|  |  |  | 			|| (this.__selected = this | 
					
						
							|  |  |  | 				.filter(function(e){ | 
					
						
							|  |  |  | 					return e.selected })) }, | 
					
						
							|  |  |  | 	set selected(value){ | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// Item list constructor...
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	// 	.__list__(make, options)
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 	// 		-> undefined
 | 
					
						
							|  |  |  | 	// 		-> list
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// 	Item constructor:
 | 
					
						
							|  |  |  | 	// 		make(value)
 | 
					
						
							|  |  |  | 	// 		make(value, options)
 | 
					
						
							|  |  |  | 	// 			-> make
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// There are two modes of operation:
 | 
					
						
							|  |  |  | 	// 	1) call make(..) to create items
 | 
					
						
							|  |  |  | 	// 	2) return a list of items
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// The if make(..) is called at least once the return value is 
 | 
					
						
							|  |  |  | 	// ignored (mode #1), otherwise, the returned list is used as the 
 | 
					
						
							|  |  |  | 	// .items structure.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// When calling make(..) (mode #1) the item is built by combining 
 | 
					
						
							|  |  |  | 	// the following in order:
 | 
					
						
							|  |  |  | 	// 	- original item (.items[key]) if present,
 | 
					
						
							|  |  |  | 	// 	- options passed to .make(<options>) method calling .__list__(..),
 | 
					
						
							|  |  |  | 	// 	- options passed to make(.., <options>) constructing the item,
 | 
					
						
							|  |  |  | 	// 	- {value: <value>} where <value> passed to make(<value>, ..)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Each of the above will override values of the previous sections.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// The resulting item is stored in:
 | 
					
						
							|  |  |  | 	// 	.items
 | 
					
						
							|  |  |  | 	// 	.item_index (keyed via .id or JSONified .value)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Each of the above structures is reset on each call to .make(..)
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Example:
 | 
					
						
							|  |  |  | 	// 	XXX
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// In mode #2 XXX
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	// NOTE: this is not designed to be called directly...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 	__list__: function(make, options){ | 
					
						
							|  |  |  | 		throw new Error('.__list__(..): Not implemented.') }, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 06:12:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	// Make .items...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.make()
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// 	.make(options)
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	// 		-> this
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 	// The items are constructed by passing a make function to .__list__(..)
 | 
					
						
							|  |  |  | 	// which in turn will call this make(..) per item created.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// For more doc on item construction see: .__init__(..)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: each call to this will reset both .items and .item_index
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 	// XXX revise options handling for .__list__(..)
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	make: function(options){ | 
					
						
							|  |  |  | 		var items = this.items = [] | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 		var old_index = this.item_index || {} | 
					
						
							|  |  |  | 		var new_index = this.item_index = {}  | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		// item constructor...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2019-02-23 04:00:56 +03:00
										 |  |  | 		// 	make(value[, options])
 | 
					
						
							| 
									
										
										
										
											2019-02-20 16:56:36 +03:00
										 |  |  | 		// 	make(value, func[, options])
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		// 		-> make
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 		var make_called = false | 
					
						
							| 
									
										
										
										
											2019-01-24 06:12:04 +03:00
										 |  |  | 		var make = function(value, opts){ | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 			make_called = true | 
					
						
							| 
									
										
										
										
											2019-02-20 16:56:36 +03:00
										 |  |  | 			var args = [...arguments] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 			opts = opts || {} | 
					
						
							| 
									
										
										
										
											2019-02-20 16:56:36 +03:00
										 |  |  | 			// handle: make(.., func, ..)
 | 
					
						
							|  |  |  | 			opts = opts instanceof Function ? | 
					
						
							|  |  |  | 				{open: opts} | 
					
						
							|  |  |  | 				: opts | 
					
						
							|  |  |  | 			// handle trailing options...
 | 
					
						
							|  |  |  | 			opts = args.length > 2 ? | 
					
						
							|  |  |  | 				Object.assign({}, | 
					
						
							|  |  |  | 					args.pop(), | 
					
						
							|  |  |  | 					opts) | 
					
						
							|  |  |  | 				: opts | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-21 13:52:31 +03:00
										 |  |  | 			// item id...
 | 
					
						
							| 
									
										
										
										
											2019-02-23 04:00:56 +03:00
										 |  |  | 			// XXX do a better id...
 | 
					
						
							|  |  |  | 			// XXX should these include the path???
 | 
					
						
							| 
									
										
										
										
											2019-02-22 09:18:37 +03:00
										 |  |  | 			var key = opts.id  | 
					
						
							|  |  |  | 				// value is a browser -> generate an unique id...
 | 
					
						
							| 
									
										
										
										
											2019-02-23 04:00:56 +03:00
										 |  |  | 				// XXX identify via structure...
 | 
					
						
							| 
									
										
										
										
											2019-02-22 09:18:37 +03:00
										 |  |  | 				|| (value instanceof Browser  | 
					
						
							|  |  |  | 					&& Date.now()) | 
					
						
							|  |  |  | 				|| JSON.stringify(value) | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-20 16:56:36 +03:00
										 |  |  | 			// no duplicate keys...
 | 
					
						
							|  |  |  | 			if(key in new_index){ | 
					
						
							|  |  |  | 				throw new Error(`make(..): duplicate key "${key}": ` | 
					
						
							|  |  |  | 					+`can't create multiple items with the same key.`) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 			// build the item...
 | 
					
						
							|  |  |  | 			var item = Object.assign({},  | 
					
						
							|  |  |  | 				// get the old item values...
 | 
					
						
							|  |  |  | 				old_index[key] || {}, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 				options || {}, | 
					
						
							| 
									
										
										
										
											2019-02-16 04:25:16 +03:00
										 |  |  | 				opts,  | 
					
						
							|  |  |  | 				{value: value}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// store the item...
 | 
					
						
							|  |  |  | 			items.push(item) | 
					
						
							|  |  |  | 			new_index[key] = item | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 			return make | 
					
						
							|  |  |  | 		}.bind(this) | 
					
						
							|  |  |  | 		make.__proto__ = Items | 
					
						
							|  |  |  | 		make.dialog = this | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 		make.items = items | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 		//var res = this.__list__(make)
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 		// XXX not sure about this -- options handling...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 		var res = this.__list__(make,  | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 			options ?  | 
					
						
							|  |  |  | 				Object.assign( | 
					
						
							|  |  |  | 					Object.create(this.options || {}),  | 
					
						
							|  |  |  | 					options || {})  | 
					
						
							|  |  |  | 				: null) | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 		// if make was not called use the .__list__(..) return value...
 | 
					
						
							|  |  |  | 		this.items = make_called ?  | 
					
						
							|  |  |  | 			this.items  | 
					
						
							|  |  |  | 			: res | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:48:36 +03:00
										 |  |  | 	// Renderers...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-14 02:24:36 +03:00
										 |  |  | 	// 	.renderList(items, context)
 | 
					
						
							|  |  |  | 	// 	.renderNested(header, sublist, item, context)
 | 
					
						
							|  |  |  | 	// 	.renderNestedHeader(item, i, context)
 | 
					
						
							|  |  |  | 	// 	.renderItem(item, i, context)
 | 
					
						
							|  |  |  | 	// 	.renderGroup(items, context)
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderList: function(items, context){ | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 		return items }, | 
					
						
							| 
									
										
										
										
											2019-01-26 04:48:36 +03:00
										 |  |  | 	// NOTE: to skip rendering an item/list return null...
 | 
					
						
							| 
									
										
										
										
											2019-01-31 07:49:50 +03:00
										 |  |  | 	// XXX should this take an empty sublist???
 | 
					
						
							|  |  |  | 	// 		...this would make it simpler to expand/collapse without 
 | 
					
						
							|  |  |  | 	// 		re-rendering the whole list...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderNested: function(header, sublist, item, context){ | 
					
						
							| 
									
										
										
										
											2019-01-31 07:49:50 +03:00
										 |  |  | 		return header ?  | 
					
						
							|  |  |  | 			this.renderGroup([ | 
					
						
							|  |  |  | 				header,  | 
					
						
							|  |  |  | 				sublist, | 
					
						
							|  |  |  | 			]) | 
					
						
							|  |  |  |    			: sublist }, | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 	renderNestedHeader: function(item, i, context){ | 
					
						
							|  |  |  | 		return this.renderItem(item, i, context) }, | 
					
						
							| 
									
										
										
										
											2019-01-26 04:48:36 +03:00
										 |  |  | 	// NOTE: to skip rendering an item/list return null...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderItem: function(item, i, context){ | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 		return item }, | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderGroup: function(items, context){ | 
					
						
							| 
									
										
										
										
											2019-01-30 06:04:55 +03:00
										 |  |  | 		return items }, | 
					
						
							| 
									
										
										
										
											2019-01-24 06:12:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	// Render state...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.render()
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 	//	.render(options)
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	//	.render(context)
 | 
					
						
							|  |  |  | 	//		-> state
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 	// context format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		root: <root-browser>,
 | 
					
						
							|  |  |  | 	// 		options: <options>,
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 	// NOTE: currently options and context are distinguished only via 
 | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 	// 		the .options attribute...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 	render: function(options){ | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-17 04:48:34 +03:00
										 |  |  | 		// XXX Q: should options and context be distinguished only via 
 | 
					
						
							|  |  |  | 		// 		the .options attr as is the case now???
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 		var context = (options == null || options.options == null) ? | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					root: this, | 
					
						
							|  |  |  | 					// NOTE: we are not combining this with .options as nested 
 | 
					
						
							|  |  |  | 					// 		lists can have their own unique sets of options 
 | 
					
						
							|  |  |  | 					// 		independently of the root list...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 					options: options || this.options || {}, | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			: options | 
					
						
							|  |  |  | 		options = context.options | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// render the items...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 		var _render | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 		// XXX should we control render parameters (range, start, end, ...)
 | 
					
						
							|  |  |  | 		// 		from outside render and pass this info down to nested lists???
 | 
					
						
							|  |  |  | 		// 		...if yes how??
 | 
					
						
							|  |  |  | 		// 			- options
 | 
					
						
							|  |  |  | 		// 			- arg threading
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 		var items = this.items | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 			.map(_render = function(item, i){ | 
					
						
							|  |  |  | 				return ( | 
					
						
							|  |  |  | 					// group...
 | 
					
						
							|  |  |  | 					item instanceof Array ? | 
					
						
							|  |  |  | 						that.renderGroup( | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 							item.map(_render), context) | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 					// renderable item...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 22:34:56 +03:00
										 |  |  | 					: item.render instanceof Function ? | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 						item.render(context)  | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 					// renderable value -- embedded list...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 22:34:56 +03:00
										 |  |  | 					: (item.value || {}).render instanceof Function ? | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 						item.value.render(context)  | 
					
						
							| 
									
										
										
										
											2019-01-26 22:34:56 +03:00
										 |  |  | 					// .sublist -- nested list...
 | 
					
						
							|  |  |  | 					: item.sublist ? | 
					
						
							| 
									
										
										
										
											2019-02-01 06:08:48 +03:00
										 |  |  | 						that.renderNested( | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 							that.renderNestedHeader(item, i, context), | 
					
						
							| 
									
										
										
										
											2019-02-01 06:08:48 +03:00
										 |  |  | 							// collapsed...
 | 
					
						
							|  |  |  | 							(item.collapsed ? | 
					
						
							|  |  |  | 									null | 
					
						
							|  |  |  | 							// renderable...
 | 
					
						
							|  |  |  | 							:item.sublist.render instanceof Function ? | 
					
						
							|  |  |  | 								item.sublist.render(context) | 
					
						
							|  |  |  | 							// list of items...
 | 
					
						
							|  |  |  | 							: item.sublist.map(_render)), | 
					
						
							|  |  |  | 							item,  | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 							context) | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 					// basic item...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 					: that.renderItem(item, i, context)) })  | 
					
						
							| 
									
										
										
										
											2019-01-26 04:48:36 +03:00
										 |  |  | 			.filter(function(e){ | 
					
						
							|  |  |  | 				return e != null }) | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// determine the render mode...
 | 
					
						
							| 
									
										
										
										
											2019-01-26 04:38:11 +03:00
										 |  |  | 		return context.root === this ? | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 			// root context -> render list and return this...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 			this.renderList(items, context) | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 			// non-root context -> return items as-is...
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 			// XXX should this be a list of the return value of a 
 | 
					
						
							|  |  |  | 			// 		renderer like .renderNested(..) ???
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 			: items | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 06:12:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | 	// Update state (make then render)...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.update()
 | 
					
						
							|  |  |  | 	// 		-> state
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX options here are a relatively blunt means of overriding options
 | 
					
						
							|  |  |  | 	// 		in the tree...
 | 
					
						
							|  |  |  | 	// 		...do we need this???
 | 
					
						
							|  |  |  | 	update: function(options){ | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 			.make(options) | 
					
						
							| 
									
										
										
										
											2019-02-09 02:20:31 +03:00
										 |  |  | 			.render(options) }, | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-24 12:45:56 +03:00
										 |  |  | 	// XXX item API...
 | 
					
						
							|  |  |  | 	get: function(){}, | 
					
						
							|  |  |  | 	set: function(){}, | 
					
						
							|  |  |  | 	remove: function(){}, | 
					
						
							|  |  |  | 	sort: function(){}, | 
					
						
							|  |  |  | 	splice: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 03:35:03 +03:00
										 |  |  | 	// Events...
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		// XXX add tagged event support...
 | 
					
						
							|  |  |  | 	// 		<event-name>: [
 | 
					
						
							|  |  |  | 	// 			<handler>,
 | 
					
						
							|  |  |  | 	// 			...
 | 
					
						
							|  |  |  | 	// 		],
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	__event_handlers: null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	// generic event infrastructure...
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 	// XXX add support for tagged events...
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 	// XXX should these be defined on this level or should we use DOM???
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	// XXX add support for item events...
 | 
					
						
							|  |  |  | 	// 		e.g. item.focus(..) -> root.focus(..)
 | 
					
						
							| 
									
										
										
										
											2019-02-27 03:35:03 +03:00
										 |  |  | 	// XXX also need to design a means for this system to interact both 
 | 
					
						
							|  |  |  | 	// 		ways with DOM events...
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 	on: function(evt, handler){ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 		var handlers = this.__event_handlers = this.__event_handlers || {} | 
					
						
							|  |  |  | 		handlers = handlers[evt] = handlers[evt] || [] | 
					
						
							|  |  |  | 		handlers.push(handler) | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	one: function(evt, handler){ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 		var func = function(...args){ | 
					
						
							|  |  |  | 			handler.call(this, ...args) | 
					
						
							|  |  |  | 			this.off(evt, func) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		this.on(evt, func) | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	off: function(evt, handler){ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 		// remove all handlers
 | 
					
						
							|  |  |  | 		if(handler == '*' || handler == 'all'){ | 
					
						
							|  |  |  | 			delete (this.__event_handlers || {})[evt] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove only the specific handler...
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var handlers = (this.__event_handlers || {})[evt] || [] | 
					
						
							|  |  |  | 			do{ | 
					
						
							|  |  |  | 				var i = handlers.indexOf(handler) | 
					
						
							|  |  |  | 				i > -1 | 
					
						
							|  |  |  | 					&& handlers.splice(i, 1) | 
					
						
							|  |  |  | 			} while(i > -1) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	trigger: function(evt, ...args){ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 		var evt = typeof(evt) == typeof('str') ? | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 			// XXX construct this in one place...
 | 
					
						
							|  |  |  | 			// 		...currently it is constructed here and in makeEventMethod(..)
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 				name: evt, | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			: evt | 
					
						
							|  |  |  | 		;((this.__event_handlers || {})[evt.name] || []) | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 			// prevent .off(..) from affecting the call loop...
 | 
					
						
							|  |  |  | 			.slice() | 
					
						
							| 
									
										
										
										
											2019-02-26 04:13:00 +03:00
										 |  |  | 			.forEach(function(handler){ | 
					
						
							| 
									
										
										
										
											2019-02-26 04:20:05 +03:00
										 |  |  | 				handler.call(that, evt, ...args) }) | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	// domain events/actions...
 | 
					
						
							|  |  |  | 	// XXX call item-specific events where applicable...
 | 
					
						
							|  |  |  | 	focus: makeEventMethod('focus', function(evt, item){ | 
					
						
							|  |  |  | 		// XXX exclusively set item.focused...
 | 
					
						
							|  |  |  | 		// XXX call item.focus handlers...
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:51:35 +03:00
										 |  |  | 	}), | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	select: makeEventMethod('select', function(evt, item){ | 
					
						
							| 
									
										
										
										
											2019-02-24 12:45:56 +03:00
										 |  |  | 		// XXX set item.selected...
 | 
					
						
							| 
									
										
										
										
											2019-02-26 01:38:47 +03:00
										 |  |  | 	}), | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	open: makeEventMethod('open', function(evt, item){}), | 
					
						
							|  |  |  | 	enter: makeEventMethod('enter', function(evt, item){}), | 
					
						
							|  |  |  | 	// XXX can/should we unify these???
 | 
					
						
							|  |  |  | 	collapse: makeEventMethod('collapse', function(evt, item){}), | 
					
						
							|  |  |  | 	expand: makeEventMethod('expand', function(evt, item){}), | 
					
						
							| 
									
										
										
										
											2019-02-23 06:38:46 +03:00
										 |  |  | 	// XXX target can be item or path...
 | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	load: makeEventMethod('load', function(evt, item){}), | 
					
						
							|  |  |  | 	close: makeEventMethod('close', function(evt, reason){}), | 
					
						
							| 
									
										
										
										
											2019-02-23 06:38:46 +03:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2019-01-26 21:32:14 +03:00
										 |  |  | 	// XXX should there return an array or a .constructor(..) instance??
 | 
					
						
							|  |  |  | 	forEach: function(){}, | 
					
						
							|  |  |  | 	map: function(){}, | 
					
						
							|  |  |  | 	filter: function(){}, | 
					
						
							|  |  |  | 	reduce: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 	// XXX should we update on on init....
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 	__init__: function(func, options){ | 
					
						
							| 
									
										
										
										
											2019-01-26 20:09:36 +03:00
										 |  |  | 		this.__list__ = func | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 		this.options = Object.assign( | 
					
						
							|  |  |  | 			{},  | 
					
						
							|  |  |  | 			this.options || {},  | 
					
						
							|  |  |  | 			options || {}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		// XXX should this be here or should this be optional???
 | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 		//this.update()
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var BaseBrowser =  | 
					
						
							|  |  |  | module.BaseBrowser =  | 
					
						
							|  |  |  | object.makeConstructor('BaseBrowser',  | 
					
						
							|  |  |  | 		BaseBrowserClassPrototype,  | 
					
						
							|  |  |  | 		BaseBrowserPrototype) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 20:19:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var BrowserClassPrototype = { | 
					
						
							|  |  |  | 	__proto__: BaseBrowser, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | // XXX TODO:
 | 
					
						
							| 
									
										
										
										
											2019-02-10 18:27:08 +03:00
										 |  |  | // 		- need a way to update some stuff on .update() / .make() -- a way 
 | 
					
						
							|  |  |  | // 			to selectively merge the old state with the new...
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | // 		- event handler signature -- pass the item + optionally render...
 | 
					
						
							|  |  |  | // 		- keyboard handling...
 | 
					
						
							|  |  |  | // XXX render of nested lists does not affect the parent list(s)...
 | 
					
						
							| 
									
										
										
										
											2019-02-20 16:30:40 +03:00
										 |  |  | // 		...need to render lists and items both as a whole or independently...
 | 
					
						
							| 
									
										
										
										
											2019-02-08 03:21:50 +03:00
										 |  |  | // XXX should this use vanilla DOM or jQuery???
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | var BrowserPrototype = { | 
					
						
							|  |  |  | 	__proto__: BaseBrowser.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	options: { | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		hideListHeader: false, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		renderHidden: false, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		localEvents: [ | 
					
						
							| 
									
										
										
										
											2019-02-10 19:28:10 +03:00
										 |  |  | 			// XXX STUB???
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 			'click', | 
					
						
							| 
									
										
										
										
											2019-02-10 19:28:10 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// XXX keyboard stuff...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX custom events...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		], | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 		//buttonLocalEvents: [
 | 
					
						
							|  |  |  | 		//],
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Format:
 | 
					
						
							|  |  |  | 		// 	[
 | 
					
						
							|  |  |  | 		// 		['html', <handler>],
 | 
					
						
							|  |  |  | 		// 		...
 | 
					
						
							|  |  |  | 		// 	]
 | 
					
						
							|  |  |  | 		itemButtons: [ | 
					
						
							|  |  |  | 		], | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 		// XXX need to mix these into the header only...
 | 
					
						
							|  |  |  | 		headerItemButtons: [ | 
					
						
							|  |  |  | 		], | 
					
						
							| 
									
										
										
										
											2019-02-27 03:35:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Shorthand elements...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Format:
 | 
					
						
							|  |  |  | 		// 	{
 | 
					
						
							|  |  |  | 		// 		<key>: {
 | 
					
						
							|  |  |  | 		// 			class: <element-class-str>,
 | 
					
						
							|  |  |  | 		// 			html: <element-html-str>,
 | 
					
						
							|  |  |  | 		// 		},
 | 
					
						
							|  |  |  | 		// 		...
 | 
					
						
							|  |  |  | 		// 	}
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// If make(..) gets passed <key> it will construct and element
 | 
					
						
							|  |  |  | 		// via <element-html-str> with an optional <element-class-str>
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: .class is optional...
 | 
					
						
							|  |  |  | 		// NOTE: set this to null to disable shorthands...
 | 
					
						
							|  |  |  | 		elementShorthand: { | 
					
						
							|  |  |  | 			'---': { | 
					
						
							|  |  |  | 				'class': 'separator', | 
					
						
							|  |  |  | 				'html': '<hr>' | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			'...': { | 
					
						
							|  |  |  | 				'class': 'separator', | 
					
						
							|  |  |  | 				'html': '<center><div class="loader"/></center>', | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-02-09 02:20:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 03:42:34 +03:00
										 |  |  | 	// parent element (optional)...
 | 
					
						
							| 
									
										
										
										
											2019-02-09 02:20:31 +03:00
										 |  |  | 	get parent(){ | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		return this.__parent  | 
					
						
							|  |  |  | 			|| (this.__dom ?  | 
					
						
							|  |  |  | 				this.__dom.parentElement  | 
					
						
							|  |  |  | 				: undefined) }, | 
					
						
							| 
									
										
										
										
											2019-02-09 02:20:31 +03:00
										 |  |  | 	set parent(value){ | 
					
						
							|  |  |  | 		var dom = this.dom | 
					
						
							|  |  |  | 		this.__parent = value | 
					
						
							|  |  |  | 		// transfer the dom to the new parent...
 | 
					
						
							|  |  |  | 		dom && (this.dom = dom) | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 03:42:34 +03:00
										 |  |  | 	// browser dom...
 | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 	get dom(){ | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		return this.__dom }, | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 	set dom(value){ | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		this.parent  | 
					
						
							|  |  |  | 			&& (this.__dom ? | 
					
						
							|  |  |  | 				this.parent.replaceChild(value, this.__dom)  | 
					
						
							|  |  |  | 				: this.parent.appendChild(value)) | 
					
						
							|  |  |  | 		this.__dom = value }, | 
					
						
							| 
									
										
										
										
											2019-02-09 02:20:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 	// Element renderers...
 | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Foramt:
 | 
					
						
							|  |  |  | 	// 	<div class="browse-widget" tabindex="0">
 | 
					
						
							|  |  |  | 	// 		<!-- header -->
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 		<!-- list -->
 | 
					
						
							|  |  |  | 	// 		<div class="list v-block">
 | 
					
						
							|  |  |  | 	// 			<!-- items -->
 | 
					
						
							|  |  |  | 	// 			...
 | 
					
						
							|  |  |  | 	// 		</div>
 | 
					
						
							|  |  |  | 	// 	</div>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 	// XXX instrument interactions...
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 	// XXX register event handlers...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderList: function(items, context){ | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 		var options = context.options || this.options | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		// dialog (container)...
 | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		var dialog = document.createElement('div') | 
					
						
							|  |  |  | 		dialog.classList.add('browse-widget') | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 		dialog.setAttribute('tabindex', '0') | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		// header...
 | 
					
						
							|  |  |  | 		options.hideListHeader | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 			|| dialog.appendChild(this.renderListHeader(context)) | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// list...
 | 
					
						
							|  |  |  | 		var list = document.createElement('div') | 
					
						
							|  |  |  | 		list.classList.add('list', 'v-block') | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		items | 
					
						
							|  |  |  | 			.forEach(function(item){ | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 				list.appendChild(item instanceof Array ?  | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 					that.renderGroup(item)  | 
					
						
							|  |  |  | 					: item) }) | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		dialog.appendChild(list) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 		// XXX event handlers...
 | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		return dialog  | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Foramt:
 | 
					
						
							|  |  |  | 	//	<div class="path v-block">
 | 
					
						
							|  |  |  | 	//		<div class="dir" tabindex="0">dir</div>
 | 
					
						
							|  |  |  | 	//		...
 | 
					
						
							|  |  |  | 	//		<div class="dir cur" tabindex="0">dir</div>
 | 
					
						
							|  |  |  | 	//	</div>
 | 
					
						
							|  |  |  | 	// 	
 | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 	// XXX populate this...
 | 
					
						
							| 
									
										
										
										
											2019-02-09 03:42:34 +03:00
										 |  |  | 	// XXX make this an item???
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderListHeader: function(context){ | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 		var header = document.createElement('div') | 
					
						
							|  |  |  | 		header.classList.add('path', 'v-block') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		// XXX path/search...
 | 
					
						
							| 
									
										
										
										
											2019-02-08 13:04:08 +03:00
										 |  |  | 		var dir = document.createElement('div') | 
					
						
							|  |  |  | 		dir.classList.add('dir', 'cur') | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 		dir.setAttribute('tabindex', '0') | 
					
						
							| 
									
										
										
										
											2019-02-08 13:04:08 +03:00
										 |  |  | 		header.appendChild(dir) | 
					
						
							| 
									
										
										
										
											2019-02-07 01:30:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return header | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	<div class="list">
 | 
					
						
							|  |  |  | 	// 		<!-- header (optional) -->
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 		<!-- sublist (optional) -->
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	</div>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 	// XXX register event handlers...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderNested: function(header, sublist, item, context){ | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 		var options = context.options || this.options | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// container...
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		var e = document.createElement('div') | 
					
						
							|  |  |  | 		e.classList.add('list') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		// localize events...
 | 
					
						
							| 
									
										
										
										
											2019-02-10 17:44:42 +03:00
										 |  |  | 		var stopPropagation = function(evt){ evt.stopPropagation() } | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 		;(options.localEvents || []) | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 			.forEach(function(evt){ | 
					
						
							| 
									
										
										
										
											2019-02-10 17:44:42 +03:00
										 |  |  | 				e.addEventListener(evt, stopPropagation) }) | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		// header...
 | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 		header | 
					
						
							|  |  |  | 			&& e.appendChild(header) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// items...
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		sublist instanceof Node ? | 
					
						
							|  |  |  | 			e.appendChild(sublist) | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 		// XXX should this add the items to a container???
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		: sublist instanceof Array ? | 
					
						
							|  |  |  | 			sublist | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 				.forEach(function(item){ | 
					
						
							|  |  |  | 					e.appendChild(item) }) | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		: null | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 		// XXX event handlers... (???)
 | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		item.dom = e | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return e | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 	// NOTE: this is the similar to .renderItem(..)
 | 
					
						
							|  |  |  | 	// XXX make collapse action overloadable....
 | 
					
						
							|  |  |  | 	renderNestedHeader: function(item, i, context){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return this.renderItem(item, i, context) | 
					
						
							|  |  |  | 			// update dom...
 | 
					
						
							|  |  |  | 			.run(function(){ | 
					
						
							|  |  |  | 				// class...
 | 
					
						
							|  |  |  | 				// XXX should be done here or in the config???
 | 
					
						
							|  |  |  | 				this.classList.add('sub-list-header') | 
					
						
							|  |  |  | 				item.collapsed | 
					
						
							|  |  |  | 					&& this.classList.add('collapsed') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// collapse action handler...
 | 
					
						
							|  |  |  | 				// XXX make this overloadable...
 | 
					
						
							|  |  |  | 				$(this).on('open', function(evt){ | 
					
						
							|  |  |  | 					item.collapsed = !item.collapsed | 
					
						
							|  |  |  | 					that.render(context) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}) }, | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	<div class="group">
 | 
					
						
							|  |  |  | 	// 		..
 | 
					
						
							|  |  |  | 	// 	</div>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 	// XXX this does not seem to get called by .render(..)...
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	renderGroup: function(items, context){ | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		var e = document.createElement('div') | 
					
						
							|  |  |  | 		e.classList.add('group') | 
					
						
							|  |  |  | 		items | 
					
						
							|  |  |  | 			// XXX is this wrong???
 | 
					
						
							|  |  |  | 			.flat(Infinity) | 
					
						
							|  |  |  | 			.forEach(function(item){ | 
					
						
							|  |  |  | 				e.appendChild(item) }) | 
					
						
							|  |  |  | 		return e }, | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	<div value="value_json" class="item .." tabindex="0" ..>
 | 
					
						
							|  |  |  | 	// 		<!-- value -->
 | 
					
						
							|  |  |  | 	// 		<div class="text">value_a</div>
 | 
					
						
							|  |  |  | 	// 		<div class="text">value_b</div>
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 		<!-- buttons (optional) -->
 | 
					
						
							|  |  |  | 	// 		<div class="button">button_a_html</div>
 | 
					
						
							|  |  |  | 	// 		<div class="button">button_b_html</div>
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	</div>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 	// XXX add custom events:
 | 
					
						
							|  |  |  | 	// 		- open
 | 
					
						
							|  |  |  | 	// 		- select
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 	// 		- update
 | 
					
						
							|  |  |  | 	renderItem: function(item, i, context){ | 
					
						
							|  |  |  | 		var options = context.options || this.options | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		if(options.hidden && !options.renderHidden){ | 
					
						
							|  |  |  | 			return null | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-27 03:35:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:52:10 +03:00
										 |  |  | 		// special-case: item shorthands...
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 		if(item.value in options.elementShorthand){ | 
					
						
							|  |  |  | 			item = options.elementShorthand[item.value] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:52:10 +03:00
										 |  |  | 			// NOTE: this is a bit of a cheat, but it saves us from either 
 | 
					
						
							|  |  |  | 			// 		parsing or restricting the format...
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 			var elem = $(item.html)[0] | 
					
						
							| 
									
										
										
										
											2019-02-27 06:52:10 +03:00
										 |  |  | 			elem.classList.add( | 
					
						
							|  |  |  | 				...(item['class'] instanceof Array ? | 
					
						
							|  |  |  | 					item['class'] | 
					
						
							|  |  |  | 					: item['class'].split(/\s+/g))) | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return elem  | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-27 03:35:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:52:10 +03:00
										 |  |  | 		// Base DOM...
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		var elem = document.createElement('div') | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 		var text = JSON.stringify(item.value || item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		// classes...
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		elem.classList.add(...['item'] | 
					
						
							|  |  |  | 			// user classes...
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 			.concat(item['class'] || item.cls || []) | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 			// special classes...
 | 
					
						
							|  |  |  | 			.concat([ | 
					
						
							|  |  |  | 				'selected', | 
					
						
							|  |  |  | 				'disabled', | 
					
						
							|  |  |  | 				'hidden', | 
					
						
							|  |  |  | 			].filter(function(cls){  | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 				return !!item[cls] }))) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// attrs...
 | 
					
						
							| 
									
										
										
										
											2019-02-12 02:34:11 +03:00
										 |  |  | 		item.disabled | 
					
						
							|  |  |  | 			|| elem.setAttribute('tabindex', '0') | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 		Object.entries(item.attrs || {}) | 
					
						
							|  |  |  | 			.forEach(function([key, value]){ | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 				elem.setAttribute(key, value) }) | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 		elem.setAttribute('value', text) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// values...
 | 
					
						
							| 
									
										
										
										
											2019-02-27 06:47:41 +03:00
										 |  |  | 		text | 
					
						
							|  |  |  | 			&& (item.value instanceof Array ? item.value : [item.value]) | 
					
						
							|  |  |  | 				// XXX handle $keys and other stuff...
 | 
					
						
							|  |  |  | 				.map(function(v){ | 
					
						
							|  |  |  | 					var value = document.createElement('span') | 
					
						
							|  |  |  | 					value.classList.add('text') | 
					
						
							|  |  |  | 					value.innerHTML = v || item || '' | 
					
						
							|  |  |  | 					elem.appendChild(value) | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		// events...
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 		// XXX revise signature...
 | 
					
						
							|  |  |  | 		elem.addEventListener('click',  | 
					
						
							|  |  |  | 			function(){ $(elem).trigger('open', [text, item, elem]) }) | 
					
						
							|  |  |  | 		//elem.addEventListener('tap', function(){ $(elem).trigger('open', [text, item, elem]) })
 | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 		Object.entries(item.events || {}) | 
					
						
							|  |  |  | 			// shorthand events...
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 			.concat([ | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 					'click', | 
					
						
							|  |  |  | 				].map(function(evt){  | 
					
						
							|  |  |  | 					return [evt, item[evt]] })) | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 			// setup the handlers...
 | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 			.forEach(function([evt, handler]){ | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 				handler | 
					
						
							| 
									
										
										
										
											2019-02-09 01:39:13 +03:00
										 |  |  | 					&& elem.addEventListener(evt, handler) }) | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:06:36 +03:00
										 |  |  | 		// buttons...
 | 
					
						
							|  |  |  | 		// XXX migrate the default buttons functionality and button inheritance...
 | 
					
						
							|  |  |  | 		var buttons = (item.buttons || options.itemButtons || []) | 
					
						
							|  |  |  | 			.slice() | 
					
						
							|  |  |  | 			// NOTE: keep the order unsurprising...
 | 
					
						
							|  |  |  | 			.reverse() | 
					
						
							|  |  |  | 		var stopPropagation = function(evt){ evt.stopPropagation() } | 
					
						
							|  |  |  | 		buttons | 
					
						
							|  |  |  | 			.forEach(function([html, handler]){ | 
					
						
							|  |  |  | 				var button = document.createElement('div') | 
					
						
							|  |  |  | 				button.classList.add('button') | 
					
						
							|  |  |  | 				button.innerHTML = html | 
					
						
							|  |  |  | 				if(!item.disabled){ | 
					
						
							|  |  |  | 					button.setAttribute('tabindex', '0') | 
					
						
							|  |  |  | 					;(options.buttonLocalEvents || options.localEvents || []) | 
					
						
							|  |  |  | 						.forEach(function(evt){ | 
					
						
							|  |  |  | 							button.addEventListener(evt, stopPropagation) }) | 
					
						
							|  |  |  | 					handler | 
					
						
							|  |  |  | 						&& button.addEventListener('click', handler) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				elem.appendChild(button) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		item.dom = elem | 
					
						
							| 
									
										
										
										
											2019-02-05 22:12:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 21:21:36 +03:00
										 |  |  | 		return elem  | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 	// This does tow additional things:
 | 
					
						
							|  |  |  | 	// 	- save the rendered state to .dom 
 | 
					
						
							|  |  |  | 	// 	- wrap a list of nodes (nested list) in a div
 | 
					
						
							| 
									
										
										
										
											2019-02-09 03:42:34 +03:00
										 |  |  | 	render: function(options){ | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		var d = object.parent(BrowserPrototype.render, this).call(this, ...arguments) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// wrap the list (nested list) of nodes in a div...
 | 
					
						
							|  |  |  | 		if(d instanceof Array){ | 
					
						
							|  |  |  | 			var c = document.createElement('div') | 
					
						
							|  |  |  | 			d.forEach(function(e){ | 
					
						
							|  |  |  | 				c.appendChild(e) }) | 
					
						
							|  |  |  | 			d = c | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		this.dom = d | 
					
						
							| 
									
										
										
										
											2019-01-24 06:12:04 +03:00
										 |  |  | 		return this.dom | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 05:19:57 +03:00
										 |  |  | 	// Custom events...
 | 
					
						
							|  |  |  | 	// 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...
 | 
					
						
							|  |  |  | 	open: function(func){ | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 	filter: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 	select: function(){}, | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 	get: function(){}, | 
					
						
							| 
									
										
										
										
											2019-02-26 04:40:38 +03:00
										 |  |  | 	//focus: function(){},
 | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Navigation...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	up: function(){}, | 
					
						
							|  |  |  | 	down: function(){}, | 
					
						
							|  |  |  | 	left: function(){}, | 
					
						
							|  |  |  | 	right: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	next: function(){}, | 
					
						
							|  |  |  | 	prev: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-13 16:11:14 +03:00
										 |  |  | 	collapse: function(){}, | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 	// XXX scroll...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:56:37 +03:00
										 |  |  | // XXX should this be a Widget too???
 | 
					
						
							| 
									
										
										
										
											2019-01-24 05:32:21 +03:00
										 |  |  | var Browser =  | 
					
						
							|  |  |  | module.Browser =  | 
					
						
							|  |  |  | object.makeConstructor('Browser',  | 
					
						
							|  |  |  | 		BrowserClassPrototype,  | 
					
						
							|  |  |  | 		BrowserPrototype) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Text tree renderer...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This is mainly designed for testing.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-30 05:51:18 +03:00
										 |  |  | // XXX Q: how should the header item and it's sub-list be linked???
 | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var TextBrowserClassPrototype = { | 
					
						
							|  |  |  | 	__proto__: BaseBrowser, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var TextBrowserPrototype = { | 
					
						
							|  |  |  | 	__proto__: BaseBrowser.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	options: { | 
					
						
							|  |  |  | 		renderIndent: '\t', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2019-01-29 04:35:39 +03:00
										 |  |  | 	// NOTE: we do not need .renderGroup(..) here as a group is not 
 | 
					
						
							|  |  |  | 	// 		visible in text...
 | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | 	renderList: function(items, options){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 		return this.renderNested(null, items, null, null, options) | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | 			.join('\n') }, | 
					
						
							| 
									
										
										
										
											2019-01-30 06:04:55 +03:00
										 |  |  | 	renderItem: function(item, i, options){ | 
					
						
							|  |  |  | 		var value = item.value || item | 
					
						
							|  |  |  | 		return item.current ? | 
					
						
							|  |  |  | 			`[ ${value} ]` | 
					
						
							|  |  |  |    			: value }, | 
					
						
							| 
									
										
										
										
											2019-02-10 03:02:08 +03:00
										 |  |  | 	renderNested: function(header, sublist, context, item, options){ | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2019-02-01 06:08:48 +03:00
										 |  |  | 		var nested = sublist  | 
					
						
							|  |  |  | 			&& sublist | 
					
						
							|  |  |  | 				.flat() | 
					
						
							|  |  |  | 				.map(function(e){ | 
					
						
							|  |  |  | 					return e instanceof Array ? | 
					
						
							|  |  |  | 						e.map(function(e){  | 
					
						
							|  |  |  | 							return (that.options.renderIndent || '  ') + e }) | 
					
						
							|  |  |  | 						: e }) | 
					
						
							|  |  |  | 				.flat()  | 
					
						
							|  |  |  | 		return ( | 
					
						
							|  |  |  | 			// expanded...
 | 
					
						
							|  |  |  | 			header && nested ? | 
					
						
							|  |  |  | 				[ | 
					
						
							| 
									
										
										
										
											2019-02-23 22:06:42 +03:00
										 |  |  | 					'- ' + header, | 
					
						
							| 
									
										
										
										
											2019-02-01 06:08:48 +03:00
										 |  |  | 					nested, | 
					
						
							|  |  |  | 				] | 
					
						
							|  |  |  | 			// collapsed...
 | 
					
						
							|  |  |  | 			: header ? | 
					
						
							| 
									
										
										
										
											2019-02-23 22:06:42 +03:00
										 |  |  | 				[ '+ ' + header ] | 
					
						
							| 
									
										
										
										
											2019-02-01 06:08:48 +03:00
										 |  |  | 			// headerless...
 | 
					
						
							|  |  |  | 			: nested )}, | 
					
						
							| 
									
										
										
										
											2019-01-28 18:10:01 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var TextBrowser =  | 
					
						
							|  |  |  | module.TextBrowser =  | 
					
						
							|  |  |  | object.makeConstructor('TextBrowser',  | 
					
						
							|  |  |  | 		TextBrowserClassPrototype,  | 
					
						
							|  |  |  | 		TextBrowserPrototype) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-21 05:29:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-20 04:39:03 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |