| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 02:19:24 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							|  |  |  | var toggler = require('lib/toggler') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | var widgets = require('features/ui-widgets') | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var overlay = require('lib/widget/overlay') | 
					
						
							|  |  |  | var browse = require('lib/widget/browse') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 06:13:50 +03:00
										 |  |  | // XXX add sorting on load....
 | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | // XXX save sort cache??? 
 | 
					
						
							| 
									
										
										
										
											2017-05-14 02:29:47 +03:00
										 |  |  | // XXX should this be split into edit/view???
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | var SortActions =  | 
					
						
							|  |  |  | module.SortActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							|  |  |  | 		// Default sort method...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// this can be:
 | 
					
						
							|  |  |  | 		// 	- sort mode name		- as set in .config['sort-mode'] key
 | 
					
						
							|  |  |  | 		// 								Example: 'Date'
 | 
					
						
							|  |  |  | 		// 	- explicit sort method	- as set in .config['sort-mode'] value
 | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 		// 								Example: 'metadata.createDate birthtime ctime'
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		'default-sort': 'Date', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Default sort order...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// can be: 'default', 'reverse')
 | 
					
						
							|  |  |  | 		'default-sort-order': 'default', | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// Sort methods...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Format:
 | 
					
						
							|  |  |  | 		// 	The value is a space separated string of methods.
 | 
					
						
							|  |  |  | 		// 	A method is either a sort method defined in .__sort_methods__
 | 
					
						
							|  |  |  | 		// 	or a dot-separated image attribute path.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: 'Date' is descending by default
 | 
					
						
							|  |  |  | 		// NOTE: .toggleImageSort('?') may also show 'Manual' when 
 | 
					
						
							|  |  |  | 		// 		.data.manual_order is present.
 | 
					
						
							|  |  |  | 		// NOTE: 'Manual' mode is set after .shiftImageLeft(..)/.shiftImageRight(..)
 | 
					
						
							|  |  |  | 		// 		are called or when restoring a pre-existing .data.manual_order 
 | 
					
						
							|  |  |  | 		// 		via .toggleImageSort('Manual')
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:06:07 +03:00
										 |  |  | 		// NOTE: all sort methods are terminated with 'keep-position' so 
 | 
					
						
							|  |  |  | 		// 		as to prevent shuffling of images that are not usable with
 | 
					
						
							|  |  |  | 		// 		the previous methods in chain...
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		'sort-methods': { | 
					
						
							|  |  |  | 			'none': '', | 
					
						
							| 
									
										
										
										
											2016-05-08 14:30:35 +03:00
										 |  |  | 			// NOTE: for when date resolution is not good enough this 
 | 
					
						
							|  |  |  | 			// 		also takes into account file sequence number...
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			// NOTE: this is descending by default...
 | 
					
						
							| 
									
										
										
										
											2018-10-16 15:03:51 +03:00
										 |  |  | 			//
 | 
					
						
							| 
									
										
										
										
											2018-10-17 12:46:53 +03:00
										 |  |  | 			// XXX need a way to unify the non-metadata dates...
 | 
					
						
							| 
									
										
										
										
											2018-10-16 15:03:51 +03:00
										 |  |  | 			// 		i.e. the birthtime and friends and ctime and friends...
 | 
					
						
							|  |  |  | 			// 		...currently both flavors can exist at the same time,
 | 
					
						
							|  |  |  | 			// 		one is created with the legacy python indexing tools
 | 
					
						
							|  |  |  | 			// 		and the other is set via the current cation .readMetadata(..)...
 | 
					
						
							| 
									
										
										
										
											2018-10-17 12:46:53 +03:00
										 |  |  | 			// 		...might be a good idea to add an alias system or 
 | 
					
						
							|  |  |  | 			// 		a way to not list "alias" methods in the main list...
 | 
					
						
							| 
									
										
										
										
											2017-09-21 01:20:08 +03:00
										 |  |  | 			'Date':  | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 				'metadata.createDate birthtime ctime name-sequence keep-position reverse', | 
					
						
							| 
									
										
										
										
											2017-09-21 01:20:08 +03:00
										 |  |  | 			'File date':  | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 				'birthtime ctime keep-position reverse', | 
					
						
							| 
									
										
										
										
											2017-09-21 01:20:08 +03:00
										 |  |  | 			'File sequence number (with overflow)':  | 
					
						
							|  |  |  | 				'name-sequence-overflow name path keep-position', | 
					
						
							|  |  |  | 			'File sequence number':  | 
					
						
							|  |  |  | 				'name-sequence name path keep-position', | 
					
						
							|  |  |  | 			'Name':  | 
					
						
							|  |  |  | 				'name path keep-position', | 
					
						
							|  |  |  | 			'Name (natural number order)':  | 
					
						
							|  |  |  | 				'name-leading-sequence name path keep-position', | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	toggleDefaultSortOrder: ['- Edit|Sort/Default sort order', | 
					
						
							|  |  |  | 		core.makeConfigToggler('default-sort-order', ['default', 'reverse'])], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Custom sort methods...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 	// 		<method-name>: function(){
 | 
					
						
							|  |  |  | 	// 			...
 | 
					
						
							|  |  |  | 	// 			return function(a, b){ ... }
 | 
					
						
							|  |  |  | 	// 		},
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 	// The methods are cmp constructors rather than direct cmp functions
 | 
					
						
							|  |  |  | 	// to enable index construction and other more complicated sort 
 | 
					
						
							|  |  |  | 	// approaches...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// NOTE: the cmp function is called in the actions context.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 	// XXX add progress...
 | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 	// XXX add doc support -- make this an action-set???...
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	__sort_methods__: { | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 		// XXX make sequence sort methods compatible with repeating numbers,
 | 
					
						
							|  |  |  | 		// 		i.e. for file names like DSC_1234 sorting more than 10K files
 | 
					
						
							|  |  |  | 		// 		should split the repeating numbers by some other means, like
 | 
					
						
							|  |  |  | 		// 		date...
 | 
					
						
							|  |  |  | 		// NOTE: these will not sort items that have no seq in name...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 		'name-leading-sequence': function(){ | 
					
						
							|  |  |  | 			return function(a, b){ | 
					
						
							|  |  |  | 				a = this.images.getImageNameLeadingSeq(a) | 
					
						
							|  |  |  | 				a = typeof(a) == typeof('str') ? 0 : a | 
					
						
							|  |  |  | 				b = this.images.getImageNameLeadingSeq(b) | 
					
						
							|  |  |  | 				b = typeof(b) == typeof('str') ? 0 : b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return a - b | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 		'name-sequence': function(){ | 
					
						
							|  |  |  | 			return function(a, b){ | 
					
						
							|  |  |  | 				a = this.images.getImageNameSeq(a) | 
					
						
							|  |  |  | 				a = typeof(a) == typeof('str') ? 0 : a | 
					
						
							|  |  |  | 				b = this.images.getImageNameSeq(b) | 
					
						
							|  |  |  | 				b = typeof(b) == typeof('str') ? 0 : b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return a - b | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 		// NOTE: this will actually sort twice, stage one build sort index and
 | 
					
						
							|  |  |  | 		// 		second stage is a O(n) lookup cmp...
 | 
					
						
							|  |  |  | 		// 		XXX not sure if this is the best way to go...
 | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 		'name-sequence-overflow': function(){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-21 16:33:38 +03:00
										 |  |  | 			// gap and gap length...
 | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 			var gap = -1 | 
					
						
							| 
									
										
										
										
											2017-08-21 16:35:49 +03:00
										 |  |  | 			var l = 1 | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// XXX add progress reporting...
 | 
					
						
							|  |  |  | 			var lst = this.images | 
					
						
							|  |  |  | 				.map(function(gid){  | 
					
						
							|  |  |  | 					return [gid, that.images.getImageNameSeq(gid)] }) | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 				// keep only items with actual sequence numbers...
 | 
					
						
							|  |  |  | 				.filter(function(e){ | 
					
						
							|  |  |  | 					return typeof(e[1]) == typeof(123) }) | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 				// sort by sequence...
 | 
					
						
							|  |  |  | 				.sort(function(a, b){  | 
					
						
							|  |  |  | 					a = a[1] | 
					
						
							|  |  |  | 					a = typeof(a) == typeof('str') ? 0 : a | 
					
						
							|  |  |  | 					b = b[1] | 
					
						
							|  |  |  | 					b = typeof(b) == typeof('str') ? 0 : b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return a - b  | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 				// find largest gaps...
 | 
					
						
							|  |  |  | 				.map(function(e, i, lst){ | 
					
						
							|  |  |  | 					var c = (lst[i+1] || e)[1] - e[1] | 
					
						
							|  |  |  | 					if(c > l){ | 
					
						
							|  |  |  | 						l = c | 
					
						
							|  |  |  | 						gap = i | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					return e | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// rotate index blocks...
 | 
					
						
							| 
									
										
										
										
											2017-08-21 16:35:49 +03:00
										 |  |  | 			if(l > 1){ | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 				var tail = lst.splice(gap+1, lst.length) | 
					
						
							|  |  |  | 				lst = tail.concat(lst) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// build the actual lookup table...
 | 
					
						
							|  |  |  | 			var index = {} | 
					
						
							|  |  |  | 			lst.forEach(function(e, i){ | 
					
						
							|  |  |  | 				index[e[0]] = i | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// return the lookup cmp...
 | 
					
						
							|  |  |  | 			return function(a, b){ | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 				// XXX is 0 as alternative here the correct way to go???
 | 
					
						
							|  |  |  | 				return (index[a] || 0) - (index[b] || 0) } | 
					
						
							| 
									
										
										
										
											2017-08-19 01:01:28 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:06:07 +03:00
										 |  |  | 		// This is specifically designed to terminate sort methods to prevent
 | 
					
						
							|  |  |  | 		// images that are not relevant to the previous order to stay in place
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX need to test how will this affect a set of images where part
 | 
					
						
							|  |  |  | 		// 		of the set is sortable an part is not...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 		'keep-position': function(){ | 
					
						
							|  |  |  | 			return function(a, b){ | 
					
						
							|  |  |  | 				a = this.data.order.indexOf(a) | 
					
						
							|  |  |  | 				b = this.data.order.indexOf(b) | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 				return a - b | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 	// Sort images...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Sort using the default sort method
 | 
					
						
							|  |  |  | 	//	.sortImages()
 | 
					
						
							|  |  |  | 	//		NOTE: the actual sort method used is set via 
 | 
					
						
							|  |  |  | 	//			.config['default-sort'] and .config['default-sort-order']
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Sort using a specific method(s):
 | 
					
						
							|  |  |  | 	//	.sortImages(<method>)
 | 
					
						
							|  |  |  | 	//	.sortImages(<method>, <reverse>)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.sortImages('<method> ..')
 | 
					
						
							|  |  |  | 	//	.sortImages('<method> ..', <reverse>)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.sortImages([<method>, ..])
 | 
					
						
							|  |  |  | 	//	.sortImages([<method>, ..], <reverse>)
 | 
					
						
							|  |  |  | 	//		NOTE: <method> can either be one of:
 | 
					
						
							|  |  |  | 	//			1) method name (key) from .config['sort-methods']
 | 
					
						
							|  |  |  | 	//			2) a space separated string of methods or attribute paths
 | 
					
						
							|  |  |  | 	//				as in .config['sort-methods']'s values.
 | 
					
						
							|  |  |  | 	//			for more info se doc for: .config['sort-methods']
 | 
					
						
							|  |  |  | 	//		NOTE: if it is needed to reverse the method by default just
 | 
					
						
							|  |  |  | 	//			add 'reverse' to it's string.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Update current sort order:
 | 
					
						
							|  |  |  | 	//	.sortImages('update')
 | 
					
						
							|  |  |  | 	//		NOTE: unless the sort order (.data.order) is changed manually
 | 
					
						
							|  |  |  | 	//			this will have no effect.
 | 
					
						
							|  |  |  | 	//		NOTE: this is designed to facilitate manual sorting of 
 | 
					
						
							|  |  |  | 	//			.data.order
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Reverse image order:
 | 
					
						
							|  |  |  | 	//	.sortImages('reverse')
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 	// NOTE: if a sort method name contains a space it must be quoted either
 | 
					
						
							|  |  |  | 	// 		in '"'s or in "'"s.
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// NOTE: reverse is calculated by oddity -- if an odd number indicated
 | 
					
						
							|  |  |  | 	// 		then the result is reversed, otherwise it is not. 
 | 
					
						
							|  |  |  | 	// 		e.g. adding:
 | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 	// 		 	'metadata.createDate birthtime ctime' + ' reverse' 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// 		will reverse the result's order while:
 | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 	// 		 	'metadata.createDate birthtime ctime reverse' + ' reverese' 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// 		will cancel reversal.
 | 
					
						
							|  |  |  | 	// NOTE: with empty images this will not do anything.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX would be nice to be able to sort a list of gids or a section
 | 
					
						
							|  |  |  | 	// 		of images...
 | 
					
						
							|  |  |  | 	// XXX should this handle manual sort order???
 | 
					
						
							|  |  |  | 	sortImages: ['- Edit|Sort/Sort images', | 
					
						
							|  |  |  | 		function(method, reverse){  | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(method == 'reverse'){ | 
					
						
							|  |  |  | 				method = 'update' | 
					
						
							|  |  |  | 				reverse = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			reverse = reverse == null ? false  | 
					
						
							|  |  |  | 				: reverse == 'reverse'  | 
					
						
							|  |  |  | 				|| reverse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// special case: 'update'
 | 
					
						
							|  |  |  | 			method = method == 'update' ? [] : method | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// defaults...
 | 
					
						
							|  |  |  | 			method = method  | 
					
						
							| 
									
										
										
										
											2018-10-15 16:54:22 +03:00
										 |  |  | 				|| ((this.config['default-sort'] || 'birthtime' || 'ctime') | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 					+ (this.config['default-sort-order'] == 'reverse' ? ' reverse' : '')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// set sort method in data...
 | 
					
						
							|  |  |  | 			this.data.sort_method = typeof(method) == typeof('str') ? method : method.join(' ') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// expand method names...
 | 
					
						
							|  |  |  | 			// XXX should this be recursive???
 | 
					
						
							|  |  |  | 			method = typeof(method) == typeof('str') ?  | 
					
						
							|  |  |  | 				method | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 					.split(/'([^']*)'|"([^"]*)"| +/) | 
					
						
							|  |  |  | 						.filter(function(e){ return e && e.trim() != '' && !/['"]/.test(e) }) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 					.map(function(m){  | 
					
						
							|  |  |  | 						return that.config['sort-methods'][m] || m }) | 
					
						
							|  |  |  | 					.join(' ') | 
					
						
							|  |  |  | 				: method | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 			method = typeof(method) == typeof('str') ?  | 
					
						
							|  |  |  | 				method.split(/'([^']*)'|"([^"]*)"| +/) | 
					
						
							|  |  |  | 					.filter(function(e){ return e && e.trim() != '' && !/['"]/.test(e) }) | 
					
						
							|  |  |  | 				: method | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// get the reverse arity...
 | 
					
						
							|  |  |  | 			var i = method.indexOf('reverse') | 
					
						
							|  |  |  | 			while(i >=0){ | 
					
						
							|  |  |  | 				reverse = !reverse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				method.splice(i, 1) | 
					
						
							|  |  |  | 				i = method.indexOf('reverse') | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// can't sort if we know nothing about .images
 | 
					
						
							|  |  |  | 			if(method && method.length > 0 && (!this.images || this.images.length == 0)){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// build the compare routine...
 | 
					
						
							|  |  |  | 			method = method | 
					
						
							|  |  |  | 				// remove duplicate methods...
 | 
					
						
							|  |  |  | 				.unique() | 
					
						
							|  |  |  | 				.map(function(m){ | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 					return (SortActions.__sort_methods__[m] | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 						|| (that.__sort_methods__ && that.__sort_methods__[m]) | 
					
						
							|  |  |  | 						// sort by attr path...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 						|| function(){ | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 							var p = m.split(/\./g) | 
					
						
							|  |  |  | 							var _get = function(obj){ | 
					
						
							|  |  |  | 								if(obj == null){ | 
					
						
							|  |  |  | 									return null | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								for(var i=0; i<p.length; i++){ | 
					
						
							|  |  |  | 									obj = obj[p[i]] | 
					
						
							|  |  |  | 									if(obj === undefined){ | 
					
						
							|  |  |  | 										return null | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								return obj | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							return function(a, b){ | 
					
						
							|  |  |  | 								a = _get(this.images[a]) | 
					
						
							|  |  |  | 								b = _get(this.images[b]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 								// not enough data to compare items, test next...
 | 
					
						
							|  |  |  | 								if(a == null || b == null){ | 
					
						
							|  |  |  | 									return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								} else if(a == b){ | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 									return 0 | 
					
						
							|  |  |  | 								} else if(a < b){ | 
					
						
							|  |  |  | 									return -1 | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									return +1 | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 							}}).call(that)  | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// prepare the cmp function...
 | 
					
						
							|  |  |  | 			var cmp = method.length == 1 ?  | 
					
						
							|  |  |  | 				method[0]  | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 				// chain compare -- return first non equal (non-0) result...
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				: function(a, b){ | 
					
						
							|  |  |  | 					var res = 0 | 
					
						
							|  |  |  | 					for(var i=0; i < method.length; i++){ | 
					
						
							|  |  |  | 						res = method[i].call(that, a, b) | 
					
						
							|  |  |  | 						if(res != 0){ | 
					
						
							|  |  |  | 							return res | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					return res | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// do the sort (in place)...
 | 
					
						
							|  |  |  | 			if(method && method.length > 0 && this.images){ | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 				this.data.order = reverse ?  | 
					
						
							|  |  |  | 					this.data.order.slice().sort(cmp.bind(this)).reverse() | 
					
						
							|  |  |  | 					: this.data.order.slice().sort(cmp.bind(this)) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// just reverse...
 | 
					
						
							|  |  |  | 			} else if(method.length <= 0 && reverse) { | 
					
						
							|  |  |  | 				this.data.order.reverse() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.data.updateImagePositions() | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Toggle sort modes...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// This is similar to sort images but it will also maintain 
 | 
					
						
							|  |  |  | 	// .data.manual_order state.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: a state can be passed appended with reverse, e.g.
 | 
					
						
							|  |  |  | 	// 		.toggleImageSort('Date') and .toggleImageSort('Date reverse')
 | 
					
						
							|  |  |  | 	// 		both will set the sort method to 'Date' but the later will 
 | 
					
						
							|  |  |  | 	// 		also reverse it.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should we merge manual order handling with .sortImages(..)???
 | 
					
						
							|  |  |  | 	// XXX currently this will not toggle past 'none'
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	toggleImageSort: ['- Edit|Sort/Image sort method', | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		toggler.Toggler(null, | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 			function(){  | 
					
						
							|  |  |  | 				return (this.data  | 
					
						
							|  |  |  | 					&& this.data.sort_method | 
					
						
							|  |  |  | 					&& (this.data.sort_method | 
					
						
							|  |  |  | 						.split(/'([^']*)'|"([^"]*)"| +/) | 
					
						
							|  |  |  | 							.filter(function(e){ return e && e.trim() != '' && !/['"]/.test(e) })[0])) | 
					
						
							|  |  |  | 					|| 'none' }, | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			function(){  | 
					
						
							|  |  |  | 				return Object.keys(this.config['sort-methods']) | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 					// manual...
 | 
					
						
							|  |  |  | 					.concat(this.data.sort_method == 'Manual' ? ['Manual'] : []) | 
					
						
							|  |  |  | 					// list saved sorts...
 | 
					
						
							|  |  |  | 					.concat(Object.keys(this.data.sort_order || {})) | 
					
						
							|  |  |  | 					.unique()}, | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			// prevent setting 'none' as mode...
 | 
					
						
							|  |  |  | 			function(mode){  | 
					
						
							|  |  |  | 				return !!this.images  | 
					
						
							|  |  |  | 					&& (mode != 'none'  | 
					
						
							| 
									
										
										
										
											2017-02-12 21:10:05 +03:00
										 |  |  | 						|| (mode == 'Manual' && (this.data.sort_cache || {})['Manual'])) }, | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			// XXX need to refactor the toggler a bit to make the 
 | 
					
						
							|  |  |  | 			// 		signature simpler... (???)
 | 
					
						
							|  |  |  | 			function(mode, _, reverse){  | 
					
						
							|  |  |  | 				reverse = reverse == 'reverse' || reverse | 
					
						
							| 
									
										
										
										
											2017-02-12 21:10:05 +03:00
										 |  |  | 				var cache = this.data.sort_cache = this.data.sort_cache || {} | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 				var method = this.data.sort_method | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 				// cache sort order...
 | 
					
						
							|  |  |  | 				if(method == 'Manual'){ | 
					
						
							|  |  |  | 					this.saveOrder(method) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				} else if(method && !(method in cache)){ | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 					this.cacheOrder() | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 				var sort = `"${mode}"`+ (reverse ? ' reverse' : '') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// cached order...
 | 
					
						
							|  |  |  | 				// XXX use load cache action...
 | 
					
						
							|  |  |  | 				if(mode in cache | 
					
						
							|  |  |  | 						|| sort in cache){ | 
					
						
							|  |  |  | 					var order = (cache[mode] || cache[sort]).slice() | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 					// invalid cache -> sort...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 					if(order.length != this.data.order.length){ | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 						// drop the cached order...
 | 
					
						
							|  |  |  | 						delete cache[ mode in cache ? mode : sort ] | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 						this.sortImages(sort) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// load cache...
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						this.data.order = order  | 
					
						
							|  |  |  | 						this.sortImages('update' + (reverse ? ' reverse' : '')) | 
					
						
							|  |  |  | 						this.data.sort_method = mode | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 				// saved sort order...
 | 
					
						
							|  |  |  | 				} else if(this.data.sort_order  | 
					
						
							|  |  |  | 						&& mode in this.data.sort_order){ | 
					
						
							| 
									
										
										
										
											2017-02-14 00:23:41 +03:00
										 |  |  | 					this.loadOrder(mode, reverse) | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 					this.sortImages(sort) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			})], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 	// XXX add drop/load actions...
 | 
					
						
							|  |  |  | 	saveOrder: ['- Sort/', | 
					
						
							| 
									
										
										
										
											2017-02-14 00:23:41 +03:00
										 |  |  | 		function(title){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			title = title || 'Manual' | 
					
						
							|  |  |  | 			var cache = this.data.sort_order = this.data.sort_order || {} | 
					
						
							|  |  |  | 			cache[title] = this.data.order.slice() | 
					
						
							| 
									
										
										
										
											2017-02-14 00:23:41 +03:00
										 |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2017-08-23 19:57:27 +03:00
										 |  |  | 	loadOrder: ['- Sort/', | 
					
						
							| 
									
										
										
										
											2017-02-14 00:23:41 +03:00
										 |  |  | 		function(title, reverse){ | 
					
						
							|  |  |  | 			var order = (this.data.sort_order || {})[title] | 
					
						
							|  |  |  | 			if(order){ | 
					
						
							|  |  |  | 				this.data.order = order.slice() | 
					
						
							|  |  |  | 				this.sortImages('update' + (reverse ? ' reverse' : '')) | 
					
						
							| 
									
										
										
										
											2017-02-15 04:21:40 +03:00
										 |  |  | 				this.data.sort_method = title | 
					
						
							| 
									
										
										
										
											2017-02-13 20:54:15 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX add drop/load actions...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 06:56:08 +03:00
										 |  |  | 	cacheOrder: ['- Sort/', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			var method = this.data.sort_method | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(method){ | 
					
						
							|  |  |  | 				var cache = this.data.sort_cache = this.data.sort_cache || {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				cache[method] = this.data.order.slice() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// Store/load sort data:
 | 
					
						
							|  |  |  | 	// 	.data.sort_method		- current sort mode (optional)
 | 
					
						
							| 
									
										
										
										
											2017-02-15 04:21:40 +03:00
										 |  |  | 	// 	.data.sort_order		- saved sort order (optional)
 | 
					
						
							|  |  |  | 	// 	.data.sort_cache		- cached sort order (optional)
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	load: [function(data){ | 
					
						
							|  |  |  | 		return function(){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			data.data | 
					
						
							|  |  |  | 				&& ['sort_method', 'sort_order', 'sort_cache'] | 
					
						
							|  |  |  | 					.forEach(function(attr){ | 
					
						
							|  |  |  | 						if(data.data[attr]){ | 
					
						
							|  |  |  | 							that.data[attr] = data.data[attr] | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}], | 
					
						
							|  |  |  | 	json: [function(){ | 
					
						
							|  |  |  | 		return function(res){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			;['sort_method', 'sort_order', 'sort_cache'] | 
					
						
							|  |  |  | 				.forEach(function(attr){ | 
					
						
							|  |  |  | 					if(that.data[attr]){ | 
					
						
							|  |  |  | 						res.data[attr] = that.data[attr] | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			// special case: unsaved manual order...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 05:47:14 +03:00
										 |  |  | 			if(this.toggleImageSort('?') == 'Manual'){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 				res.data.sort_order = res.sort_order || {} | 
					
						
							|  |  |  | 				res.data.sort_order['Manual'] = this.data.order.slice() | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Sort = | 
					
						
							|  |  |  | module.Sort = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'sort', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'base', | 
					
						
							| 
									
										
										
										
											2017-05-14 02:29:47 +03:00
										 |  |  | 		// XXX should we split this to edit/view???
 | 
					
						
							|  |  |  | 		'edit', | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'ui-sort', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: SortActions, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		['shiftImageRight shiftImageLeft', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				this.data.sort_method = 'Manual' | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2017-02-13 05:47:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:43:39 +03:00
										 |  |  | 		// maintain .sort_order and .sort_cache separately from .data in
 | 
					
						
							|  |  |  | 		// the store...
 | 
					
						
							| 
									
										
										
										
											2017-02-13 05:47:14 +03:00
										 |  |  | 		['prepareIndexForWrite', | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var c = res.changes | 
					
						
							| 
									
										
										
										
											2017-02-15 03:28:18 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 01:35:09 +03:00
										 |  |  | 				if(!c){ | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:35:28 +03:00
										 |  |  | 				;['sort_order', 'sort_cache'] | 
					
						
							|  |  |  | 					.forEach(function(attr){ | 
					
						
							| 
									
										
										
										
											2017-12-13 17:14:58 +03:00
										 |  |  | 						if(!res.raw.data){ | 
					
						
							|  |  |  | 							return | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 						if((c === true || c[attr]) && res.raw.data[attr]){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:35:28 +03:00
										 |  |  | 							// full save...
 | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 							if(c === true){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:35:28 +03:00
										 |  |  | 								res.index[attr] = res.raw.data[attr]  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// build diff...
 | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								var diff = {} | 
					
						
							|  |  |  | 								c[attr].forEach(function(k){  | 
					
						
							|  |  |  | 									diff[k] = res.raw.data[attr][k] }) | 
					
						
							|  |  |  | 								res.index[attr +'-diff'] = diff | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-02-15 03:28:18 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 05:35:28 +03:00
										 |  |  | 							// cleanup...
 | 
					
						
							|  |  |  | 							delete res.index.data[attr] | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-02-13 05:47:14 +03:00
										 |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2018-02-04 06:23:31 +03:00
										 |  |  | 		['prepareIndexForLoad', | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			function(res){ | 
					
						
							| 
									
										
										
										
											2017-02-15 05:35:28 +03:00
										 |  |  | 				['sort_order', 'sort_cache'] | 
					
						
							|  |  |  | 					.forEach(function(attr){ | 
					
						
							|  |  |  | 						if(res[attr]){ | 
					
						
							|  |  |  | 							res.data[attr] = res[attr] | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-02-15 05:21:28 +03:00
										 |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2017-02-13 05:47:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// manage changes...
 | 
					
						
							|  |  |  | 		['sortImages', | 
					
						
							|  |  |  | 			function(_, target){ this.markChanged('data') }], | 
					
						
							| 
									
										
										
										
											2017-02-15 04:21:40 +03:00
										 |  |  | 		// NOTE: this always saves to 'Manual' this is correct regardless
 | 
					
						
							|  |  |  | 		// 		of save mode as in the current logic, the only mode that 
 | 
					
						
							|  |  |  | 		// 		results from a manual shift is a manual sort...
 | 
					
						
							|  |  |  | 		// 		XXX this may pose a problem with saved sorts, the question
 | 
					
						
							|  |  |  | 		// 			is whether a saved mode can be edited or just saved or
 | 
					
						
							|  |  |  | 		// 			updated...
 | 
					
						
							|  |  |  | 		['shiftImageOrder', | 
					
						
							|  |  |  | 			function(){ this.markChanged('sort_order', ['Manual']) }], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 03:28:18 +03:00
										 |  |  | 		['saveOrder',  | 
					
						
							|  |  |  | 			function(_, title){ this.markChanged('sort_order', [title]) }], | 
					
						
							|  |  |  | 		['cacheOrder',  | 
					
						
							|  |  |  | 			function(){ this.markChanged('sort_cache', [this.data.sort_method]) }], | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 06:13:50 +03:00
										 |  |  | // XXX add ability to partition ribbons in different modes...
 | 
					
						
							|  |  |  | // 		- by hour/day/month/year in date modes...
 | 
					
						
							|  |  |  | // 		- ???
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | var SortUIActions = actions.Actions({ | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 	showSortMethodDoc: ['- Sort/', | 
					
						
							|  |  |  | 		widgets.makeUIDialog(function(method){ | 
					
						
							|  |  |  | 			var data = this.config['sort-methods'][method] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return $('<div class="help-dialog">') | 
					
						
							|  |  |  | 				.append($('<div class="sort-method">') | 
					
						
							|  |  |  | 					.prop('tabindex', true) | 
					
						
							|  |  |  | 					.append($('<h2>') | 
					
						
							|  |  |  | 						.text(method)) | 
					
						
							|  |  |  | 					.append($('<hr>')) | 
					
						
							|  |  |  | 					// parse the action doc...
 | 
					
						
							|  |  |  | 					.append($('<pre>') | 
					
						
							|  |  |  | 						.text( | 
					
						
							|  |  |  | 							'Sort order:\n  ' | 
					
						
							|  |  |  | 							+data.replace(/\s+/g, '\n  ')))) | 
					
						
							|  |  |  | 		})], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	// XXX should we be able to edit modes??? 
 | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 	// XXX should this be a toggler???
 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	sortDialog: ['Edit|Sort/Sort images...', | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 		widgets.makeUIDialog(function(){ | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var dfl = this.config['default-sort']  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX might be a good idea to make this generic...
 | 
					
						
							|  |  |  | 			var _makeTogglHandler = function(toggler){ | 
					
						
							|  |  |  | 				return function(){ | 
					
						
							|  |  |  | 					var txt = $(this).find('.text').first().text() | 
					
						
							|  |  |  | 					that[toggler]() | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 					o.update() | 
					
						
							|  |  |  | 						.then(function(){ o.select(txt) }) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 					that.toggleSlideshow('?') == 'on'  | 
					
						
							| 
									
										
										
										
											2016-04-30 23:58:39 +03:00
										 |  |  | 						&& o.parent.close() | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 			var o = browse.makeLister(null, function(path, make){ | 
					
						
							|  |  |  | 				var lister = this | 
					
						
							|  |  |  | 				var cur = that.toggleImageSort('?') | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 				that.toggleImageSort('??').forEach(function(mode){ | 
					
						
							|  |  |  | 					// skip 'none'...
 | 
					
						
							|  |  |  | 					if(mode == 'none'){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 					make(mode, { | 
					
						
							|  |  |  | 						cls: [ | 
					
						
							|  |  |  | 							(mode == cur ? 'highlighted selected' : ''), | 
					
						
							|  |  |  | 							(mode == dfl ? 'default' : ''), | 
					
						
							|  |  |  | 						].join(' '), | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 						.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 							that.toggleImageSort(null, mode,  | 
					
						
							|  |  |  | 								that.config['default-sort-order'] == 'reverse') | 
					
						
							|  |  |  | 							lister.parent.close() | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 				})	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Commands...
 | 
					
						
							|  |  |  | 				make('---') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 02:10:35 +03:00
										 |  |  | 				make('$Reverse images') | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 					.on('open', function(){ | 
					
						
							|  |  |  | 						that.reverseImages() | 
					
						
							|  |  |  | 						lister.parent.close() | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Settings...
 | 
					
						
							|  |  |  | 				make('---') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				make(['Default order: ', that.config['default-sort-order'] || 'ascending']) | 
					
						
							|  |  |  | 					.on('open', _makeTogglHandler('toggleDefaultSortOrder')) | 
					
						
							|  |  |  | 					.addClass('item-value-view') | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 			.run(function(){ | 
					
						
							|  |  |  | 				// handle '?' button to browse path...
 | 
					
						
							|  |  |  | 				this.showDoc = function(){ | 
					
						
							|  |  |  | 					var method = this.select('!').text() | 
					
						
							|  |  |  | 					method  | 
					
						
							|  |  |  | 						&& method in that.config['sort-methods'] | 
					
						
							|  |  |  | 						&& that.showSortMethodDoc(method) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				this.keyboard.handler('General', '?', 'showDoc') | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return o | 
					
						
							| 
									
										
										
										
											2016-04-30 03:38:52 +03:00
										 |  |  | 		})]	 | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var SortUI =  | 
					
						
							|  |  |  | module.SortUI = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'ui-sort', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui', | 
					
						
							| 
									
										
										
										
											2016-05-11 05:00:40 +03:00
										 |  |  | 		'sort', | 
					
						
							| 
									
										
										
										
											2016-04-29 17:59:17 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: SortUIActions, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |