| 
									
										
										
										
											2014-07-20 03:02:18 +04: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
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2014-07-20 03:02:18 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-01 16:12:10 +03:00
										 |  |  | var sha1 = require('ext-lib/sha1') | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 07:42:07 +03:00
										 |  |  | var object = require('lib/object') | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | var util = require('lib/util') | 
					
						
							| 
									
										
										
										
											2014-11-18 20:20:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // decide to use a hashing function...
 | 
					
						
							|  |  |  | if(typeof(sha1) != 'undefined'){ | 
					
						
							|  |  |  | 	var hash = sha1.hash.bind(sha1) | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  | 	var hash = function(g){ return g } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-20 03:02:18 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 17:09:25 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 19:42:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 03:37:50 +03:00
										 |  |  | var PLACEHOLDER =  | 
					
						
							|  |  |  | module.PLACEHOLDER =  | 
					
						
							|  |  |  | 	'./images/placeholder.svg' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var MISSING =  | 
					
						
							|  |  |  | module.MISSING =  | 
					
						
							|  |  |  | 	'./images/missing.svg' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | // A stub image, also here for documentation...
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | var IMAGE_DATA = | 
					
						
							|  |  |  | module.IMAGE_DATA = { | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 	// Entity GID...
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	id: 'GID', | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Entity type
 | 
					
						
							|  |  |  | 	type: 'image', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Entity state
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- 'single'
 | 
					
						
							|  |  |  | 	// 	- 'grouped'
 | 
					
						
							|  |  |  | 	// 	- 'hidden'
 | 
					
						
							|  |  |  | 	// 	- ...
 | 
					
						
							|  |  |  | 	state: 'single', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Creation time...
 | 
					
						
							|  |  |  | 	ctime: 0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Original path...
 | 
					
						
							| 
									
										
										
										
											2020-05-21 03:37:50 +03:00
										 |  |  | 	//path: './images/900px/SIZE.jpg',
 | 
					
						
							|  |  |  | 	path: PLACEHOLDER, | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Previews...
 | 
					
						
							|  |  |  | 	// NOTE: the actual values depend on specific image and can be
 | 
					
						
							|  |  |  | 	// 		any size...
 | 
					
						
							| 
									
										
										
										
											2020-05-21 03:37:50 +03:00
										 |  |  | 	//preview: {
 | 
					
						
							|  |  |  | 	//	'150px': './images/150px/SIZE.jpg',
 | 
					
						
							|  |  |  | 	//	'350px': './images/350px/SIZE.jpg',
 | 
					
						
							|  |  |  | 	//	'900px': './images/900px/SIZE.jpg',
 | 
					
						
							|  |  |  | 	//},
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Classes
 | 
					
						
							|  |  |  | 	// XXX currently unused...
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	//classes: '',
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Image orientation (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined	- same as 0
 | 
					
						
							|  |  |  | 	// 	- 0 (default)		- load as-is
 | 
					
						
							|  |  |  | 	// 	- 90				- rotate 90deg CW
 | 
					
						
							|  |  |  | 	// 	- 180				- rotate 180deg CW
 | 
					
						
							|  |  |  | 	// 	- 270				- rotate 270deg CW (90deg CCW)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: use orientationExif2ImageGrid(..) to convert from EXIF 
 | 
					
						
							|  |  |  | 	// 		orientation format to ImageGrid format...
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	//orientation: 0,
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Image flip state (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined
 | 
					
						
							|  |  |  | 	// 	- array
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can contain:
 | 
					
						
							|  |  |  | 	// 	- 'vertical'
 | 
					
						
							|  |  |  | 	// 	- 'horizontal'
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: use orientationExif2ImageGrid(..) to convert from EXIF 
 | 
					
						
							|  |  |  | 	// 		orientation format to ImageGrid format...
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	//flipped: null,
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Image comment (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined
 | 
					
						
							|  |  |  | 	// 	- string
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	//comment: null,
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// List of image tags (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined
 | 
					
						
							|  |  |  | 	// 	- array
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 	//tags: null,
 | 
					
						
							| 
									
										
										
										
											2014-07-28 17:28:03 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | var GROUP_DATA = | 
					
						
							|  |  |  | module.GROUP_DATA = { | 
					
						
							|  |  |  | 	// Entity GID...
 | 
					
						
							|  |  |  | 	id: 'GID', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Entity type
 | 
					
						
							|  |  |  | 	type: 'group', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Entity state
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- 'single'
 | 
					
						
							|  |  |  | 	// 	- 'grouped'
 | 
					
						
							|  |  |  | 	// 	- 'hidden'
 | 
					
						
							|  |  |  | 	// 	- ...
 | 
					
						
							|  |  |  | 	state: 'single', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// image used to represent/display group...
 | 
					
						
							|  |  |  | 	cover: 'GID', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// list of group contents, including .cover
 | 
					
						
							|  |  |  | 	items: [ | 
					
						
							|  |  |  | 		'GID', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Classes
 | 
					
						
							|  |  |  | 	// XXX currently unused...
 | 
					
						
							|  |  |  | 	//classes: '',
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Image comment (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined
 | 
					
						
							|  |  |  | 	// 	- string
 | 
					
						
							|  |  |  | 	//comment: null,
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// List of image tags (optional)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// can be:
 | 
					
						
							|  |  |  | 	// 	- null/undefined
 | 
					
						
							|  |  |  | 	// 	- array
 | 
					
						
							|  |  |  | 	//tags: null,
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | // Calculate relative rotation angle...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Calculate rotation angle relative to from:
 | 
					
						
							|  |  |  | // 	calcRelativeRotation(from, 'cw')
 | 
					
						
							|  |  |  | // 	calcRelativeRotation(from, 'ccw')
 | 
					
						
							|  |  |  | // 		-> 0 | 90 | 180 | 270
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Validate an angle:
 | 
					
						
							|  |  |  | // 	calcRelativeRotation(angle)
 | 
					
						
							|  |  |  | // 	calcRelativeRotation(from, angle)
 | 
					
						
							|  |  |  | // 		-> 0 | 90 | 180 | 270
 | 
					
						
							|  |  |  | // 		-> null
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | module.calcRelativeRotation = function(from, to){ | 
					
						
							|  |  |  | 	if(to == null){ | 
					
						
							|  |  |  | 		to = from | 
					
						
							|  |  |  | 		from = 0 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 	to = to == 'cw' ?  | 
					
						
							|  |  |  | 			1  | 
					
						
							|  |  |  | 		: to == 'ccw' ?  | 
					
						
							|  |  |  | 			-1 | 
					
						
							|  |  |  | 		: [0, 90, 180, 270].includes(to*1) ?  | 
					
						
							|  |  |  | 			to*1 | 
					
						
							|  |  |  | 		: [-90, -180, -270].includes(to*1) ?  | 
					
						
							|  |  |  | 			360+(to*1) | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 		: null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// relative rotation...
 | 
					
						
							|  |  |  | 	if(to == 1 || to == -1){ | 
					
						
							|  |  |  | 		var res = from | 
					
						
							|  |  |  | 		res = res == null ? 0 : res*1 | 
					
						
							|  |  |  | 		res += 90*to | 
					
						
							|  |  |  | 		res = res < 0 ? 270  | 
					
						
							|  |  |  | 			: res > 270 ? 0 | 
					
						
							|  |  |  | 			: res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// explicit direction...
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		var res = to | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 	return res } | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-02 02:55:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | // cmp functions...
 | 
					
						
							|  |  |  | // XXX is this the right way to seporate these???
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.makeImageDateCmp = function(data, get){ | 
					
						
							|  |  |  | 	return function(a, b){ | 
					
						
							|  |  |  | 		if(get != null){ | 
					
						
							|  |  |  | 			a = get(a) | 
					
						
							|  |  |  | 			b = get(b) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		b = data[b].ctime | 
					
						
							|  |  |  | 		a = data[a].ctime | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(a == b){ | 
					
						
							|  |  |  | 			return 0 | 
					
						
							|  |  |  | 		} else if(a < b){ | 
					
						
							|  |  |  | 			return -1 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return +1 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NOTE: this expects gids...
 | 
					
						
							|  |  |  | module.makeImageNameCmp = function(data, get){ | 
					
						
							|  |  |  | 	return function(a, b){ | 
					
						
							|  |  |  | 		if(get != null){ | 
					
						
							|  |  |  | 			a = get(a) | 
					
						
							|  |  |  | 			b = get(b) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		a = data.getImageFileName(a) | 
					
						
							|  |  |  | 		b = data.getImageFileName(b) | 
					
						
							|  |  |  | 		if(a == b){ | 
					
						
							|  |  |  | 			return 0 | 
					
						
							|  |  |  | 		} else if(a < b){ | 
					
						
							|  |  |  | 			return -1 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return +1 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.makeImageSeqOrNameCmp = function(data, get, seq){ | 
					
						
							|  |  |  | 	seq = seq == null ? data.getImageNameSeq : seq | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return function(a, b){ | 
					
						
							|  |  |  | 		// XXX this is ugly and non-generic...
 | 
					
						
							|  |  |  | 		if(get != null){ | 
					
						
							|  |  |  | 			a = get(a) | 
					
						
							|  |  |  | 			b = get(b) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// XXX this is ugly and non-generic...
 | 
					
						
							|  |  |  | 		var aa = seq.call(data, a) | 
					
						
							|  |  |  | 		var bb = seq.call(data, b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// special case: seq, name
 | 
					
						
							|  |  |  | 		if(typeof(aa) == typeof(123) && typeof(bb) == typeof('str')){ return -1 } | 
					
						
							|  |  |  | 		// special case: name, seq
 | 
					
						
							|  |  |  | 		if(typeof(aa) == typeof('str') && typeof(bb) == typeof(123)){ return +1 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// get the names if there are no sequence numbers...
 | 
					
						
							|  |  |  | 		// NOTE: at this point both a and b are either numbers or NaN's...
 | 
					
						
							|  |  |  | 		a = isNaN(aa) ? data.getImageFileName(a) : aa | 
					
						
							|  |  |  | 		b = isNaN(bb) ? data.getImageFileName(b) : bb | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// do the actual comparison
 | 
					
						
							|  |  |  | 		if(a == b){ | 
					
						
							|  |  |  | 			return 0 | 
					
						
							|  |  |  | 		} else if(a < b){ | 
					
						
							|  |  |  | 			return -1 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return +1 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-11 04:29:08 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | // XXX Image base class...
 | 
					
						
							|  |  |  | // 		...not sure if we need this... (???)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ImageClassPrototype = | 
					
						
							|  |  |  | module.ImageClassPrototype = { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ImagePrototype = | 
					
						
							|  |  |  | module.ImagePrototype = { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Image =  | 
					
						
							|  |  |  | module.Image =  | 
					
						
							| 
									
										
										
										
											2019-07-17 00:07:24 +03:00
										 |  |  | 	object.Constructor('Image',  | 
					
						
							| 
									
										
										
										
											2016-01-11 04:29:08 +03:00
										 |  |  | 		ImageClassPrototype,  | 
					
						
							|  |  |  | 		ImagePrototype) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-20 03:02:18 +04:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-12 04:29:55 +03:00
										 |  |  | // XXX depends on jli.quoteRegExp(..)
 | 
					
						
							| 
									
										
										
										
											2014-07-24 16:05:59 +04:00
										 |  |  | var ImagesClassPrototype = | 
					
						
							|  |  |  | module.ImagesClassPrototype = { | 
					
						
							| 
									
										
										
										
											2014-11-17 00:12:29 +03:00
										 |  |  | 	// XXX populate the image doc better...
 | 
					
						
							| 
									
										
										
										
											2015-12-06 06:21:37 +03:00
										 |  |  | 	// NOTE: if base is given then it will be set as .base_path and 
 | 
					
						
							|  |  |  | 	// 		removed from each url if present...
 | 
					
						
							|  |  |  | 	fromArray: function(data, base){ | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 		var images = new this() | 
					
						
							|  |  |  | 		// XXX stub...
 | 
					
						
							|  |  |  | 		var i = 0 | 
					
						
							| 
									
										
										
										
											2015-12-12 04:29:55 +03:00
										 |  |  | 		//var base_pattern = base ? RegExp('^' + base) : null 
 | 
					
						
							| 
									
										
										
										
											2016-05-28 02:47:52 +03:00
										 |  |  | 		var base_pattern = base ? RegExp('^' + RegExp.quoteRegExp(base)) : null  | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 		data.forEach(function(path){ | 
					
						
							| 
									
										
										
										
											2015-12-29 01:02:57 +03:00
										 |  |  | 			// XXX need to normalize path...
 | 
					
						
							| 
									
										
										
										
											2017-06-16 19:41:27 +03:00
										 |  |  | 			var p = path.startsWith('data') ?  | 
					
						
							|  |  |  | 				path  | 
					
						
							|  |  |  | 				: (base_pattern ? path.replace(base_pattern, './') : path) | 
					
						
							| 
									
										
										
										
											2015-12-29 01:02:57 +03:00
										 |  |  | 					.replace(/([\/\\])\1+/g, '/') | 
					
						
							|  |  |  | 			// XXXX
 | 
					
						
							|  |  |  | 			var gid = hash('I'+i+':'+p) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 16:17:12 +03:00
										 |  |  | 			var name = (p | 
					
						
							|  |  |  | 					// basename...
 | 
					
						
							|  |  |  | 					.split(/[\\\/]/g).pop() || '') | 
					
						
							|  |  |  | 					// ext...
 | 
					
						
							|  |  |  | 					.split(/(\.[^\.]*$)/) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-17 00:12:29 +03:00
										 |  |  | 			// XXX populate the image doc better...
 | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 			images[gid] = { | 
					
						
							|  |  |  | 				id: gid, | 
					
						
							| 
									
										
										
										
											2015-12-29 01:02:57 +03:00
										 |  |  | 				path: p, | 
					
						
							| 
									
										
										
										
											2016-04-20 16:17:12 +03:00
										 |  |  | 				// basename...
 | 
					
						
							|  |  |  | 				name: name[0], | 
					
						
							|  |  |  | 				// ext with leading '.'
 | 
					
						
							|  |  |  | 				ext: name[1], | 
					
						
							| 
									
										
										
										
											2015-12-06 06:21:37 +03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-29 01:02:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 05:27:31 +03:00
										 |  |  | 			// remove only if base path is given and in path...
 | 
					
						
							| 
									
										
										
										
											2015-12-06 06:21:37 +03:00
										 |  |  | 			if(base && base_pattern.test(path)){ | 
					
						
							|  |  |  | 				images[gid].base_path = base | 
					
						
							| 
									
										
										
										
											2014-11-14 21:57:55 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			i += 1 | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		return images | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	fromJSON: function(data){ | 
					
						
							| 
									
										
										
										
											2018-12-05 18:15:37 +03:00
										 |  |  | 		return new this().load(data) | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2014-07-24 16:05:59 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ImagesPrototype = | 
					
						
							|  |  |  | module.ImagesPrototype = { | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 	//version: '3.1',
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-16 04:40:32 +03:00
										 |  |  | 	get length(){ | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 		return this.keys().length }, | 
					
						
							| 
									
										
										
										
											2014-11-16 04:40:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 	get gids(){ | 
					
						
							|  |  |  | 		return this.keys() }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 20:19:39 +04:00
										 |  |  | 	// Generic iterators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// function format:
 | 
					
						
							|  |  |  | 	// 		function(key, value, index, object)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2014-11-07 02:02:55 +03:00
										 |  |  | 	// reduce function format:
 | 
					
						
							|  |  |  | 	// 		function(value1, value2, key, index, object)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-06 23:09:41 +03:00
										 |  |  | 	filter: function(func){ | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2015-12-07 04:56:19 +03:00
										 |  |  | 		var res = new this.constructor() | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		this.forEach(function(key, i){ | 
					
						
							|  |  |  | 			if(func.call(that[key], key, that[key], i++, that)){ | 
					
						
							|  |  |  | 				res[key] = that[key] } }) | 
					
						
							| 
									
										
										
										
											2020-12-02 03:32:53 +03:00
										 |  |  | 		return res }, | 
					
						
							| 
									
										
										
										
											2015-12-06 23:09:41 +03:00
										 |  |  | 	// NOTE: .map(..) and .reduce(..) will not return Images objects...
 | 
					
						
							|  |  |  | 	map: function(func){ | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		return this.gids | 
					
						
							|  |  |  | 			.map(function(key, i){ | 
					
						
							|  |  |  | 				return that[key] instanceof Function ? | 
					
						
							|  |  |  | 					[] | 
					
						
							|  |  |  | 					: [func.call(that[key], key, that[key], i++, that)] }) | 
					
						
							|  |  |  | 			.flat() }, | 
					
						
							| 
									
										
										
										
											2014-11-07 02:02:55 +03:00
										 |  |  | 	reduce: function(func, initial){ | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2014-11-07 02:02:55 +03:00
										 |  |  | 		var res = initial | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		this.forEach(function(key, i){ | 
					
						
							|  |  |  | 			res = func.call(that[key], res, that[key], key, i++, that) }) | 
					
						
							| 
									
										
										
										
											2020-12-02 03:32:53 +03:00
										 |  |  | 		return res }, | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 	forEach: function(func){ | 
					
						
							|  |  |  | 		this.map(func) | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2020-12-02 03:32:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 03:40:34 +03:00
										 |  |  | 	// make images iterable...
 | 
					
						
							|  |  |  | 	[Symbol.iterator]: function*(){ | 
					
						
							| 
									
										
										
										
											2020-12-02 03:32:53 +03:00
										 |  |  | 		for(var key in this){ | 
					
						
							|  |  |  | 			// reject non images...
 | 
					
						
							|  |  |  | 			// XXX make this cleaner...
 | 
					
						
							|  |  |  | 			if(key == 'length'  | 
					
						
							|  |  |  | 					|| key == 'version'  | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 					|| key == 'gids'  | 
					
						
							| 
									
										
										
										
											2020-12-02 03:32:53 +03:00
										 |  |  | 					|| this[key] instanceof Function){ | 
					
						
							|  |  |  | 				continue } | 
					
						
							|  |  |  | 			yield [key, this[key]] } }, | 
					
						
							| 
									
										
										
										
											2020-12-02 03:40:34 +03:00
										 |  |  | 	iter: function*(){ | 
					
						
							| 
									
										
										
										
											2020-12-02 06:12:39 +03:00
										 |  |  | 		yield* this }, | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 05:32:15 +03:00
										 |  |  | 	// XXX do we need a .values() / .entries() here too???
 | 
					
						
							| 
									
										
										
										
											2014-07-25 20:19:39 +04:00
										 |  |  | 	keys: function(){ | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 		var keys = Object.keys(this) | 
					
						
							| 
									
										
										
										
											2020-12-02 04:47:53 +03:00
										 |  |  | 		var i = keys.lastIndexOf('version') | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 		i >= 0 | 
					
						
							|  |  |  | 			&& keys.splice(i, 1) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 		return keys }, | 
					
						
							| 
									
										
										
										
											2014-07-25 20:19:39 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Build an image index relative to an attribute...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		<attr-value> : [
 | 
					
						
							|  |  |  | 	// 			<gid>,
 | 
					
						
							|  |  |  | 	// 			...
 | 
					
						
							|  |  |  | 	// 		],
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX test out the attr list functionality...
 | 
					
						
							|  |  |  | 	makeIndex: function(attr){ | 
					
						
							|  |  |  | 		var res = {} | 
					
						
							| 
									
										
										
										
											2014-10-22 01:23:56 +04:00
										 |  |  | 		attr = attr.constructor !== Array ? [attr] : attr | 
					
						
							| 
									
										
										
										
											2014-07-25 20:19:39 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// buld the index...
 | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		this.forEach(function(key){ | 
					
						
							|  |  |  | 			var n = attr.map(function(n){ return that[n] }) | 
					
						
							|  |  |  | 			n = JSON.stringify(n.length == 1 ? n[0] : n) | 
					
						
							|  |  |  | 				// XXX is this the right way to go?
 | 
					
						
							|  |  |  | 				.replace(/^"(.*)"$/g, '$1') | 
					
						
							|  |  |  | 			res[n] = n in res ? res[n].concat(key) : [key] | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return res | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Image data helpers...
 | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	getImagePath: function(gid, path){ | 
					
						
							|  |  |  | 		var img = this[gid] || IMAGE_DATA | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 		return (img.base_path || path) ?  | 
					
						
							|  |  |  | 			[img.base_path || path, img.path].join('/') | 
					
						
							| 
									
										
										
										
											2017-11-22 07:26:28 +03:00
										 |  |  | 			: util.path2url(img.path || IMAGE_DATA.path) | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-11-17 02:45:44 +03:00
										 |  |  | 	// NOTE: actual URL decoding and encoding is not done here to keep
 | 
					
						
							|  |  |  | 	// 		things consistent, rather it is done the the latest possible 
 | 
					
						
							|  |  |  | 	// 		stage, in images._loadImagePreviewURL(..)
 | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 	// XXX see: ribbons.js for details...
 | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 	// XXX this is the same (in part) as .getImagePath(..) 
 | 
					
						
							| 
									
										
										
										
											2015-11-23 22:00:19 +03:00
										 |  |  | 	getBestPreview: function(gid, size, img_data, full_path){ | 
					
						
							|  |  |  | 		if(img_data === true){ | 
					
						
							|  |  |  | 			full_path = true | 
					
						
							|  |  |  | 			img_data = null | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-07-28 19:45:51 +04:00
										 |  |  | 		//gid = gid == null ? getImageGID(): gid
 | 
					
						
							|  |  |  | 		//size = size == null ? getVisibleImageSize('max') : size
 | 
					
						
							|  |  |  | 		img_data = img_data == null ? this[gid] : img_data | 
					
						
							| 
									
										
										
										
											2019-10-09 03:04:46 +03:00
										 |  |  | 		img_data = img_data || IMAGE_DATA | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// if path is explicitly null there are no previews...
 | 
					
						
							|  |  |  | 		if(img_data.path === null){ | 
					
						
							|  |  |  | 			return undefined | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-11-15 18:48:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-24 04:02:01 +03:00
										 |  |  | 		// if no usable images are available use STUB data...
 | 
					
						
							| 
									
										
										
										
											2017-11-22 07:26:28 +03:00
										 |  |  | 		if(!img_data  | 
					
						
							|  |  |  | 				|| (img_data.preview == null  | 
					
						
							| 
									
										
										
										
											2014-11-15 18:48:45 +03:00
										 |  |  | 					|| Object.keys(img_data.preview).length == 0) | 
					
						
							|  |  |  | 				&& img_data.path == null){ | 
					
						
							| 
									
										
										
										
											2014-11-22 18:02:22 +03:00
										 |  |  | 			img_data = IMAGE_DATA | 
					
						
							| 
									
										
										
										
											2014-11-15 18:48:45 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 		// get minimal element bigger than size or if size is null get 
 | 
					
						
							|  |  |  | 		// the greatest element...
 | 
					
						
							|  |  |  | 		var path = img_data.path | 
					
						
							|  |  |  | 		var preview = img_data.preview || {} | 
					
						
							|  |  |  | 		var p = [null, 0] | 
					
						
							|  |  |  | 		for(var s in preview){ | 
					
						
							|  |  |  | 			var v = parseInt(s) | 
					
						
							|  |  |  | 			p = (size == null || (v < size && p[1] < size)) ? | 
					
						
							|  |  |  | 					(v < p[1] ? p : [s, v]) | 
					
						
							|  |  |  | 				: (p[1] >= size && (v > p[1] || v < size)) ?  | 
					
						
							|  |  |  | 					p | 
					
						
							| 
									
										
										
										
											2020-05-21 03:00:00 +03:00
										 |  |  | 				: [s, v] } | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// get the original if it exists and smaller than size...
 | 
					
						
							|  |  |  | 		if(path && (size == null || p[1] < size)){ | 
					
						
							|  |  |  | 			var url = path | 
					
						
							|  |  |  | 			var preview_size = 'Original' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// get the largest preview...
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var url = preview[p[0]] | 
					
						
							|  |  |  | 			var preview_size = p[0] | 
					
						
							| 
									
										
										
										
											2014-07-28 19:45:51 +04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// XXX LEGACY...
 | 
					
						
							|  |  |  | 		//url = url.indexOf('%20') >= 0 ? decodeURI(url) : url
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-28 19:45:51 +04:00
										 |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2015-11-23 22:00:19 +03:00
										 |  |  | 			url: (full_path && img_data.base_path ? | 
					
						
							| 
									
										
										
										
											2017-11-17 02:45:44 +03:00
										 |  |  | 				  	img_data.base_path + '/'  | 
					
						
							| 
									
										
										
										
											2015-11-23 22:00:19 +03:00
										 |  |  | 					: '')  | 
					
						
							|  |  |  | 				+ url, | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 			size: preview_size, | 
					
						
							| 
									
										
										
										
											2020-10-26 17:30:47 +03:00
										 |  |  | 		} }, | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 04:47:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	// Get image filename...
 | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this will default to gid if not filename (.path) is set... (???)
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	getImageFileName: function(gid, do_unescape){ | 
					
						
							|  |  |  | 		do_unescape = do_unescape == null ? true : do_unescape | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 		if(!this[gid] || !this[gid].path){ | 
					
						
							| 
									
										
										
										
											2020-10-26 17:30:47 +03:00
										 |  |  | 			return gid } | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 		if(do_unescape){ | 
					
						
							|  |  |  | 			return unescape(this[gid].path.split('/').pop()) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-10-26 17:30:47 +03:00
										 |  |  | 			return this[gid].path.split('/').pop() } }, | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	// Get the first sequence of numbers in the file name...
 | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if no filenmae (.path) is set, this will return gid... (???)
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	getImageNameSeq: function(gid){ | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 		if(!this[gid] || !this[gid].path){ | 
					
						
							|  |  |  | 			return gid | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 		var n = this.getImageFileName(gid) | 
					
						
							|  |  |  | 		var r = /([0-9]+)/m.exec(n) | 
					
						
							|  |  |  | 		return r == null ? n : parseInt(r[1]) | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	// Get the sequence of numbers in the file name but only if it is 
 | 
					
						
							|  |  |  | 	// at the filename start...
 | 
					
						
							|  |  |  | 	getImageNameLeadingSeq: function(gid){ | 
					
						
							| 
									
										
										
										
											2017-08-21 20:29:17 +03:00
										 |  |  | 		if(!this[gid] || !this[gid].path){ | 
					
						
							|  |  |  | 			return gid | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 		var n = this.getImageFileName(gid) | 
					
						
							|  |  |  | 		var r = /^([0-9]+)/g.exec(n) | 
					
						
							|  |  |  | 		return r == null ? n : parseInt(r[1]) | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 07:09:06 +03:00
										 |  |  | 	// Replace image gid...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	replaceGid: function(from, to){ | 
					
						
							|  |  |  | 		var img = this[from] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX is the test needed here???
 | 
					
						
							|  |  |  | 		if(img != null){ | 
					
						
							|  |  |  | 			delete this[from] | 
					
						
							|  |  |  | 			this[to] = img | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 04:47:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	// Gid sorters...
 | 
					
						
							| 
									
										
										
										
											2020-12-02 04:47:53 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2014-07-25 20:19:39 +04:00
										 |  |  | 	// XXX might be a good idea to add caching...
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	// XXX chainCmp(..) is loaded from lib/jli.js
 | 
					
						
							|  |  |  | 	sortImages: function(gids, cmp, reverse){ | 
					
						
							|  |  |  | 		gids = gids == null ? Object.keys(this) : gids | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cmp = cmp == null ? module.makeImageDateCmp(this) : cmp | 
					
						
							| 
									
										
										
										
											2014-10-22 01:23:56 +04:00
										 |  |  | 		cmp = cmp.constructor === Array ? chainCmp(cmp) : cmp | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		gids = gids.sort(cmp) | 
					
						
							|  |  |  | 		gids = reverse ? gids.reverse() : gids | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return gids | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	// Shorthands...
 | 
					
						
							|  |  |  | 	// XXX 
 | 
					
						
							|  |  |  | 	sortedImagesByFileNameSeqWithOverflow: function(gids, reverse){ | 
					
						
							| 
									
										
										
										
											2014-11-25 15:56:59 +03:00
										 |  |  | 		gids = gids == null ? Object.keys(this) : gids | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 14:58:52 +04:00
										 |  |  | 		// XXX see ../ui/sort.js
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 04:47:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 	// Actions...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Rotate image...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Rotate image clockwise:
 | 
					
						
							|  |  |  | 	//	.rotateImage(target, 'cw')
 | 
					
						
							|  |  |  | 	//		-> images
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Rotate image counterclockwise:
 | 
					
						
							|  |  |  | 	//	.rotateImage(target, 'ccw')
 | 
					
						
							|  |  |  | 	//		-> images
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Set explicit image rotation angle:
 | 
					
						
							|  |  |  | 	//	.rotateImage(target, 0|90|180|270)
 | 
					
						
							|  |  |  | 	//	.rotateImage(target, -90|-180|-270)
 | 
					
						
							|  |  |  | 	//		-> images
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: target can be a gid or a list of gids...
 | 
					
						
							|  |  |  | 	rotateImage: function(gids, direction){ | 
					
						
							| 
									
										
										
										
											2014-10-22 01:23:56 +04:00
										 |  |  | 		gids = gids.constructor !== Array ? [gids] : gids | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 		// validate direction...
 | 
					
						
							|  |  |  | 		if(module.calcRelativeRotation(direction) == null){ | 
					
						
							|  |  |  | 			return this | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		gids.forEach(function(key){ | 
					
						
							|  |  |  | 			var img = that[key] | 
					
						
							| 
									
										
										
										
											2014-11-15 18:48:45 +03:00
										 |  |  | 			if(img == null){ | 
					
						
							|  |  |  | 				img = that[key] = {} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			var o = direction == 'cw' || direction == 'ccw'  | 
					
						
							|  |  |  | 				? module.calcRelativeRotation(img.orientation, direction)  | 
					
						
							|  |  |  | 				: direction*1 | 
					
						
							| 
									
										
										
										
											2016-10-10 05:45:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* XXX seting orientation to undefined does not save correctly (BUG?)  | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			if(o == 0){ | 
					
						
							|  |  |  | 				delete img.orientation | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				img.orientation = o | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-10-10 05:45:55 +03:00
										 |  |  | 			//*/
 | 
					
						
							|  |  |  | 			img.orientation = o | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			// account for proportions...
 | 
					
						
							|  |  |  | 			//that.correctImageProportionsForRotation(img)
 | 
					
						
							|  |  |  | 			// XXX this is a bit of an overkill but it will update the 
 | 
					
						
							|  |  |  | 			// 		preview if needed...
 | 
					
						
							|  |  |  | 			//that.updateImage(img)
 | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Flip image...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.flipImage(target, 'horizontal')
 | 
					
						
							|  |  |  | 	//	.flipImage(target, 'vertical')
 | 
					
						
							|  |  |  | 	//		-> images
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2014-11-07 02:02:55 +03:00
										 |  |  | 	flipImage: function(gids, direction, reference){ | 
					
						
							| 
									
										
										
										
											2014-10-22 01:23:56 +04:00
										 |  |  | 		gids = gids.constructor !== Array ? [gids] : gids | 
					
						
							| 
									
										
										
										
											2014-11-25 03:34:46 +03:00
										 |  |  | 		reference = reference || 'view' | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		gids.forEach(function(key){ | 
					
						
							|  |  |  | 			var img = that[key] | 
					
						
							| 
									
										
										
										
											2016-12-31 07:10:28 +03:00
										 |  |  | 			if(img == null){ | 
					
						
							|  |  |  | 				img = that[key] = {} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-11-25 03:34:46 +03:00
										 |  |  | 			var o = img.orientation | 
					
						
							|  |  |  | 			var d = direction | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// flip relative to 
 | 
					
						
							|  |  |  | 			if(reference == 'view' && (o == 90 || o == 270)){ | 
					
						
							|  |  |  | 				d = d == 'horizontal' ? 'vertical' : 'horizontal' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-15 18:48:45 +03:00
										 |  |  | 			if(img == null){ | 
					
						
							|  |  |  | 				img = that[key] = {} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			var state = img.flipped | 
					
						
							|  |  |  | 			state = state == null ? [] : state | 
					
						
							|  |  |  | 			// toggle the specific state...
 | 
					
						
							| 
									
										
										
										
											2014-11-25 03:34:46 +03:00
										 |  |  | 			var i = state.indexOf(d) | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			if(i >= 0){ | 
					
						
							|  |  |  | 				state.splice(i, 1) | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-11-25 03:34:46 +03:00
										 |  |  | 				state.push(d) | 
					
						
							| 
									
										
										
										
											2014-07-28 06:36:02 +04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if(state.length == 0){ | 
					
						
							|  |  |  | 				delete img.flipped | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				img.flipped = state | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-28 04:55:51 +03:00
										 |  |  | 	clone: function(){ | 
					
						
							| 
									
										
										
										
											2018-12-05 18:15:37 +03:00
										 |  |  | 		return (new Images()).load(this.json()) }, | 
					
						
							| 
									
										
										
										
											2015-11-28 04:55:51 +03:00
										 |  |  | 	// NOTE: this will join the other data into the current object in-place,
 | 
					
						
							|  |  |  | 	// 		use .clone() to preserve current data...
 | 
					
						
							|  |  |  | 	join: function(other){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		other.forEach(function(gid, img){ | 
					
						
							|  |  |  | 			that[gid] = img | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 	// serialization...
 | 
					
						
							| 
									
										
										
										
											2018-12-05 18:15:37 +03:00
										 |  |  | 	load: function(data){ | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 		data = typeof(data) == typeof('str')  | 
					
						
							|  |  |  | 			? JSON.parse(data)  | 
					
						
							|  |  |  | 			: JSON.parse(JSON.stringify(data)) | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 		var version = data.versio | 
					
						
							| 
									
										
										
										
											2014-07-25 02:00:50 +04:00
										 |  |  | 		for(var k in data){ | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 			var img = this[k] = data[k] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// keep the preview paths decoded...
 | 
					
						
							|  |  |  | 			//
 | 
					
						
							|  |  |  | 			// NOTE: updating from legacy format...
 | 
					
						
							|  |  |  | 			// XXX move this to version conversion... (???)
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 			version == null | 
					
						
							|  |  |  | 				&& Object.keys(img && img.preview || {}) | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 					.forEach(function(res){ | 
					
						
							|  |  |  | 						var p = img.preview[res] | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 						img.preview[res] =  | 
					
						
							|  |  |  | 							p.includes(k+'%20-%20') ?  | 
					
						
							|  |  |  | 								decodeURI(p)  | 
					
						
							|  |  |  | 								: p }) } | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 	// XXX this is really odd: renaming this to 'toJSON' breaks JavaScript
 | 
					
						
							| 
									
										
										
										
											2014-12-31 19:18:03 +03:00
										 |  |  | 	// 		making chrome/node just say: "<error>" and a filename...
 | 
					
						
							| 
									
										
										
										
											2018-12-05 18:15:37 +03:00
										 |  |  | 	json: function(data){ | 
					
						
							| 
									
										
										
										
											2017-11-17 18:00:34 +03:00
										 |  |  | 		var res = JSON.parse(JSON.stringify(this)) | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 		res.version = '3.0' | 
					
						
							|  |  |  | 		return res | 
					
						
							| 
									
										
										
										
											2014-07-24 16:05:59 +04:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_reset: function(){ | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX is this a good name for this??? (see: object.js)
 | 
					
						
							|  |  |  | 	__init__: function(json){ | 
					
						
							|  |  |  | 		// load initial state...
 | 
					
						
							|  |  |  | 		if(json != null){ | 
					
						
							| 
									
										
										
										
											2018-12-05 18:15:37 +03:00
										 |  |  | 			this.load(json) | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			this._reset() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2014-07-24 16:05:59 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Main Images object...
 | 
					
						
							|  |  |  | var Images =  | 
					
						
							| 
									
										
										
										
											2014-11-18 20:20:35 +03:00
										 |  |  | module.Images =  | 
					
						
							| 
									
										
										
										
											2019-07-17 00:07:24 +03:00
										 |  |  | 	object.Constructor('Images',  | 
					
						
							| 
									
										
										
										
											2014-11-18 20:20:35 +03:00
										 |  |  | 		ImagesClassPrototype,  | 
					
						
							|  |  |  | 		ImagesPrototype) | 
					
						
							| 
									
										
										
										
											2014-07-20 03:02:18 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |