mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 19:00:09 +00:00 
			
		
		
		
	some refactoring, tweaking and fixes...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									c455c21230
								
							
						
					
					
						commit
						2d19efaef7
					
				| @ -20,6 +20,7 @@ require('features/history') | |||||||
| require('features/app') | require('features/app') | ||||||
| require('features/peer') | require('features/peer') | ||||||
| require('features/ui') | require('features/ui') | ||||||
|  | require('features/ui-partial-ribbons-precache') | ||||||
| require('features/ui-partial-ribbons') | require('features/ui-partial-ribbons') | ||||||
| require('features/ui-partial-ribbons-2') | require('features/ui-partial-ribbons-2') | ||||||
| require('features/ui-single-image') | require('features/ui-single-image') | ||||||
|  | |||||||
| @ -21,15 +21,21 @@ var core = require('features/core') | |||||||
| 
 | 
 | ||||||
| var PartialRibbonsActions = actions.Actions({ | var PartialRibbonsActions = actions.Actions({ | ||||||
| 	config: { | 	config: { | ||||||
|  | 		// Number of screen widths to load...
 | ||||||
| 		'ribbon-size-screens': 7, | 		'ribbon-size-screens': 7, | ||||||
| 
 | 
 | ||||||
| 		// the amount of screen widths to keep around the current image...
 | 		// Amount of screen widths to keep around the current image...
 | ||||||
| 		'ribbon-update-threshold': 1.2, | 		'ribbon-update-threshold': 1.2, | ||||||
| 
 | 
 | ||||||
| 		// the oversize multiplier limit when we resize the ribbon down...
 | 		// Oversize multiplier limit when we resize the ribbon down...
 | ||||||
| 		'ribbon-resize-threshold': 2, | 		'ribbon-resize-threshold': 2, | ||||||
|  | 
 | ||||||
|  | 		// Sets size of ribbons in single image mode...
 | ||||||
|  | 		'ribbons-resize-single-image': 13, | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
|  | 	// XXX preload???
 | ||||||
|  | 
 | ||||||
| 	updateRibbon: ['- Interface/Update partial ribbon size',  | 	updateRibbon: ['- Interface/Update partial ribbon size',  | ||||||
| 		function(target, w, size, threshold){ | 		function(target, w, size, threshold){ | ||||||
| 			target = target instanceof jQuery  | 			target = target instanceof jQuery  | ||||||
| @ -73,15 +79,52 @@ var PartialRibbonsActions = actions.Actions({ | |||||||
| 			var na = gids.slice(gids.indexOf(target)+1).length | 			var na = gids.slice(gids.indexOf(target)+1).length | ||||||
| 			var pa = gids.slice(0, gids.indexOf(target)).length | 			var pa = gids.slice(0, gids.indexOf(target)).length | ||||||
| 
 | 
 | ||||||
| 			//console.log(`-- loaded: ${loaded} size: ${size}`)
 |  | ||||||
| 
 |  | ||||||
| 			// full resize...
 | 			// full resize...
 | ||||||
|  | 			if(threshold == 0 | ||||||
| 					// ribbon not loaded...
 | 					// ribbon not loaded...
 | ||||||
| 			if(r.length == 0 | 					|| img.length == 0 | ||||||
| 					// ribbon shorter than we expect...
 | 					// ribbon shorter than we expect...
 | ||||||
| 					|| (loaded < size && na + pa > loaded) | 					|| (loaded < size && na + pa > loaded) | ||||||
|  | 					// ribbon too long...
 | ||||||
| 					|| loaded > size * threshold){ | 					|| loaded > size * threshold){ | ||||||
|  | 				console.log('RESIZE') | ||||||
| 				this.resizeRibbon(target, size) | 				this.resizeRibbon(target, size) | ||||||
|  | 			//*/
 | ||||||
|  | 
 | ||||||
|  | 			/*/ XXX long jump condition...... | ||||||
|  | 			if(img.length != 0  | ||||||
|  | 					&& (r.length == 0 | ||||||
|  | 						// ribbon shorter than we expect...
 | ||||||
|  | 						|| (loaded < size && na + pa > loaded) | ||||||
|  | 						// ribbon too long...
 | ||||||
|  | 						|| loaded > size * threshold)){ | ||||||
|  | 				console.log('RESIZE') | ||||||
|  | 				this.resizeRibbon(target, size) | ||||||
|  | 
 | ||||||
|  | 			// image is off screen -- align off then animate...
 | ||||||
|  | 			// 		1) initial state
 | ||||||
|  | 			// 			T	<-	[---|---x---|---------------]
 | ||||||
|  | 			// 		2) load new state but align off screen 
 | ||||||
|  | 			// 					[-------T-------|-------|---]
 | ||||||
|  | 			// 		3) animate
 | ||||||
|  | 			// 					[---|---T---|---------------]
 | ||||||
|  | 			// XXX this makes the draw worse...
 | ||||||
|  | 			} else if(img.length == 0 ){ | ||||||
|  | 				console.log('LONG-JUMP') | ||||||
|  | 				r.length == 0 ? | ||||||
|  | 					// ribbon not loaded...
 | ||||||
|  | 					this.resizeRibbon(target, size) | ||||||
|  | 					// simply update...
 | ||||||
|  | 					: this.ribbons | ||||||
|  | 						.preventTransitions(r) | ||||||
|  | 						.updateRibbonInPlace( | ||||||
|  | 							gids, | ||||||
|  | 							r_gid,  | ||||||
|  | 							data.getImageOrder(this.current) > data.getImageOrder(target) ? | ||||||
|  | 								gids[gids.length - w] | ||||||
|  | 								: gids[w]) | ||||||
|  | 						.restoreTransitions(r, true) | ||||||
|  | 			//*/
 | ||||||
| 
 | 
 | ||||||
| 			// in-place update...
 | 			// in-place update...
 | ||||||
| 			// passed threshold on the right...
 | 			// passed threshold on the right...
 | ||||||
| @ -90,6 +133,7 @@ var PartialRibbonsActions = actions.Actions({ | |||||||
| 					|| (pl < update_threshold && pa > pl)  | 					|| (pl < update_threshold && pa > pl)  | ||||||
| 					// loaded more than we need by threshold...
 | 					// loaded more than we need by threshold...
 | ||||||
| 					|| nl + pl + 1 > size + update_threshold){ | 					|| nl + pl + 1 > size + update_threshold){ | ||||||
|  | 				console.log('UPDATE') | ||||||
| 				r.length == 0 ? | 				r.length == 0 ? | ||||||
| 					// ribbon not loaded...
 | 					// ribbon not loaded...
 | ||||||
| 					this.resizeRibbon(target, size) | 					this.resizeRibbon(target, size) | ||||||
| @ -113,36 +157,6 @@ var PartialRibbonsActions = actions.Actions({ | |||||||
| 						.restoreTransitions(r, true) | 						.restoreTransitions(r, true) | ||||||
| 			} | 			} | ||||||
| 		}], | 		}], | ||||||
| 	resizeRibbon: ['- Interface/Resize ribbon to n images', |  | ||||||
| 		function(target, size){ |  | ||||||
| 			size = size  |  | ||||||
| 				|| (this.config['ribbon-size-screens'] * this.screenwidth) |  | ||||||
| 				|| (5 * this.screenwidth) |  | ||||||
| 			var data = this.data |  | ||||||
| 			var ribbons = this.ribbons |  | ||||||
| 
 |  | ||||||
| 			// localize transition prevention... 
 |  | ||||||
| 			// NOTE: we can't get ribbon via target directly here as
 |  | ||||||
| 			// 		the target might not be loaded...
 |  | ||||||
| 			var r_gid = data.getRibbon(target) |  | ||||||
| 			if(r_gid == null){ |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			// NOTE: for the initial load this may be empty...
 |  | ||||||
| 			var r = ribbons.getRibbon(r_gid) |  | ||||||
| 
 |  | ||||||
| 			// XXX do we need to for example ignore unloaded (r.length == 0)
 |  | ||||||
| 			// 		ribbons here, for example not load ribbons too far off 
 |  | ||||||
| 			// 		screen??
 |  | ||||||
| 			 |  | ||||||
| 			ribbons |  | ||||||
| 				.preventTransitions(r) |  | ||||||
| 				.updateRibbon( |  | ||||||
| 					data.getImages(target, size, 'total'),  |  | ||||||
| 					r_gid, |  | ||||||
| 					target) |  | ||||||
| 				.restoreTransitions(r, true) |  | ||||||
| 		}], |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| var PartialRibbons =  | var PartialRibbons =  | ||||||
| @ -157,6 +171,9 @@ module.PartialRibbons = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'ui', | 		'ui', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-partial-ribbons-precache', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: PartialRibbonsActions,  | 	actions: PartialRibbonsActions,  | ||||||
| 
 | 
 | ||||||
| @ -172,7 +189,13 @@ module.PartialRibbons = core.ImageGridFeatures.Feature({ | |||||||
| 			}], | 			}], | ||||||
| 		['resizing.post', | 		['resizing.post', | ||||||
| 			function(_, unit, size){ | 			function(_, unit, size){ | ||||||
| 				if(unit == 'scale'){ | 				// keep constant size in single image...
 | ||||||
|  | 				if(this.toggleSingleImage && this.toggleSingleImage('?') == 'on'){ | ||||||
|  | 					this.updateRibbon( | ||||||
|  | 						'current',  | ||||||
|  | 						this.config['ribbons-resize-single-image'] || 13) | ||||||
|  | 
 | ||||||
|  | 				} else if(unit == 'scale'){ | ||||||
| 					this.updateRibbon('current', this.screenwidth / size || 1) | 					this.updateRibbon('current', this.screenwidth / size || 1) | ||||||
| 
 | 
 | ||||||
| 				} else if(unit == 'screenwidth'){ | 				} else if(unit == 'screenwidth'){ | ||||||
|  | |||||||
							
								
								
									
										245
									
								
								ui (gen4)/features/ui-partial-ribbons-precache.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										245
									
								
								ui (gen4)/features/ui-partial-ribbons-precache.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,245 @@ | |||||||
|  | /********************************************************************** | ||||||
|  | *  | ||||||
|  | * | ||||||
|  | * | ||||||
|  | **********************************************************************/ | ||||||
|  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | ||||||
|  | (function(require){ var module={} // make module AMD/node compatible...
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | var actions = require('lib/actions') | ||||||
|  | var features = require('lib/features') | ||||||
|  | 
 | ||||||
|  | var core = require('features/core') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | var PreCacheActions = actions.Actions({ | ||||||
|  | 	config: { | ||||||
|  | 		// How many non-adjacent images to preload...
 | ||||||
|  | 		'preload-radius': 5, | ||||||
|  | 
 | ||||||
|  | 		// Sources to preload...
 | ||||||
|  | 		'preload-sources': ['bookmark', 'selected'], | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	// NOTE: this will not work from chrome when loading from a local fs...
 | ||||||
|  | 	// XXX experimental...
 | ||||||
|  | 	startCacheWorker: ['Interface/', | ||||||
|  | 		function(){ | ||||||
|  | 			// a worker is started already...
 | ||||||
|  | 			if(this.cacheWorker != null){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			var b = new Blob([[ | ||||||
|  | 				'addEventListener(\'message\', function(e) {', | ||||||
|  | 				'	var urls = e.data', | ||||||
|  | 				'	urls = urls.constructor !== Array ? [urls] : urls', | ||||||
|  | 				'	var l = urls.length', | ||||||
|  | 				'	urls.forEach(function(url){', | ||||||
|  | 				'		var xhr = new XMLHttpRequest()', | ||||||
|  | 				'		xhr.responseType = \'blob\'', | ||||||
|  | 				/* | ||||||
|  | 				'		xhr.onload = xhr.onerror = function(){', | ||||||
|  | 				'			l -= 1', | ||||||
|  | 				'			if(l <= 0){', | ||||||
|  | 				'				postMessage({status: \'done.\', urls: urls})', | ||||||
|  | 				'			}', | ||||||
|  | 				'		}', | ||||||
|  | 				*/ | ||||||
|  | 				'		xhr.open(\'GET\', url, true)', | ||||||
|  | 				'		xhr.send()', | ||||||
|  | 				'	})', | ||||||
|  | 				'}, false)', | ||||||
|  | 			].join('\n')]) | ||||||
|  | 
 | ||||||
|  | 			var url = URL.createObjectURL(b) | ||||||
|  | 
 | ||||||
|  | 			this.cacheWorker = new Worker(url) | ||||||
|  | 			this.cacheWorker.url = url | ||||||
|  | 		}], | ||||||
|  | 	stopCacheWorker: ['Interface/', | ||||||
|  | 		function(){ | ||||||
|  | 			if(this.cacheWorker){ | ||||||
|  | 				this.cacheWorker.terminate() | ||||||
|  | 				URL.revokeObjectURL(this.cacheWorker.url) | ||||||
|  | 				delete this.cacheWorker | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// Pre-load images...
 | ||||||
|  | 	//
 | ||||||
|  | 	// Sources supported:
 | ||||||
|  | 	// 	<tag>			- pre-load images tagged with <tag> 
 | ||||||
|  | 	// 					  (default: ['bookmark', 'selected']) 
 | ||||||
|  | 	// 	<ribbon-gid>	- pre-cache from a specific ribbon
 | ||||||
|  | 	// 	'ribbon'		- pre-cache from current ribbon
 | ||||||
|  | 	// 	'order'			- pre-cache from images in order
 | ||||||
|  | 	//
 | ||||||
|  | 	// NOTE: workers when loaded from file:// in a browser context 
 | ||||||
|  | 	// 		will not have access to local images...
 | ||||||
|  | 	//
 | ||||||
|  | 	// XXX need a clear strategy to run this...
 | ||||||
|  | 	// XXX might be a good idea to make the worker queue the lists...
 | ||||||
|  | 	// 		...this will need careful prioritization logic...
 | ||||||
|  | 	// 			- avoid loading the same url too often
 | ||||||
|  | 	// 			- load the most probable urls first
 | ||||||
|  | 	// 				- next targets
 | ||||||
|  | 	// 					- next/prev
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, 'ribbon', this.screenwidth)
 | ||||||
|  | 	// 					- next/prev marked/bookmarked/order
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, 'marked')
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, 'bookmarked')
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, 'order')
 | ||||||
|  | 	// 					- next/prev screen
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, 'ribbon',
 | ||||||
|  | 	// 							this.config['preload-radius'] * this.screenwidth)
 | ||||||
|  | 	// 					- next/prev ribbon
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, this.data.getRibbon(target, 1))
 | ||||||
|  | 	// 						.preCacheJumpTargets(target, this.data.getRibbon(target, -1))
 | ||||||
|  | 	// 				- next blocks
 | ||||||
|  | 	// 					- what resize ribbon does...
 | ||||||
|  | 	// XXX coordinate this with .resizeRibbon(..)
 | ||||||
|  | 	// XXX make this support an explicit list of gids....
 | ||||||
|  | 	// XXX should this be here???
 | ||||||
|  | 	preCacheJumpTargets: ['- Interface/Pre-cache potential jump target images', | ||||||
|  | 		function(target, sources, radius, size){ | ||||||
|  | 			target = target instanceof jQuery  | ||||||
|  | 				? this.ribbons.getElemGID(target) | ||||||
|  | 				// NOTE: data.getImage(..) can return null at start or end
 | ||||||
|  | 				// 		of ribbon, thus we need to account for this...
 | ||||||
|  | 				: (this.data.getImage(target) | ||||||
|  | 					|| this.data.getImage(target, 'after')) | ||||||
|  | 
 | ||||||
|  | 			sources = sources || this.config['preload-sources'] || ['bookmark', 'selected'] | ||||||
|  | 			sources = sources.constructor !== Array ? [sources] : sources | ||||||
|  | 			radius = radius || this.config['preload-radius'] || 9 | ||||||
|  | 
 | ||||||
|  | 			var that = this | ||||||
|  | 
 | ||||||
|  | 			// get preview...
 | ||||||
|  | 			var _getPreview = function(c){ | ||||||
|  | 				return that.images[c]  | ||||||
|  | 					&& that.images.getBestPreview(c, size, true).url | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// get a set of paths...
 | ||||||
|  | 			// NOTE: we are also ordering the resulting gids by their 
 | ||||||
|  | 			// 		distance from target...
 | ||||||
|  | 			var _get = function(i, lst, source, radius, oddity, step){ | ||||||
|  | 				var found = oddity | ||||||
|  | 				var max = source.length  | ||||||
|  | 
 | ||||||
|  | 				for(var j = i+step; (step > 0 && j < max) || (step < 0 && j >= 0); j += step){ | ||||||
|  | 					var c = source[j] | ||||||
|  | 
 | ||||||
|  | 					if(c == null || that.images[c] == null){ | ||||||
|  | 						continue | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// build the URL...
 | ||||||
|  | 					lst[found] = _getPreview(c) | ||||||
|  | 
 | ||||||
|  | 					found += 2 | ||||||
|  | 					if(found >= radius*2){ | ||||||
|  | 						break | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// run the actual preload...
 | ||||||
|  | 			var _run = function(){ | ||||||
|  | 				sources.forEach(function(tag){ | ||||||
|  | 					// order...
 | ||||||
|  | 					if(tag == 'order'){ | ||||||
|  | 						var source = that.data.order | ||||||
|  | 
 | ||||||
|  | 					// current ribbon...
 | ||||||
|  | 					}else if(tag == 'ribbon'){ | ||||||
|  | 						var source = that.data.ribbons[that.data.getRibbon()] | ||||||
|  | 
 | ||||||
|  | 					// ribbon-gid...
 | ||||||
|  | 					} else if(tag in that.data.ribbons){ | ||||||
|  | 						var source = that.data.ribbons[tag] | ||||||
|  | 				 | ||||||
|  | 					// nothing tagged then nothing to do...
 | ||||||
|  | 					} else if(that.data.tags == null  | ||||||
|  | 							|| that.data.tags[tag] == null  | ||||||
|  | 							|| that.data.tags[tag].length == 0){ | ||||||
|  | 						return  | ||||||
|  | 
 | ||||||
|  | 					// tag...
 | ||||||
|  | 					} else { | ||||||
|  | 						var source = that.data.tags[tag] | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					size = size || that.ribbons.getVisibleImageSize()  | ||||||
|  | 
 | ||||||
|  | 					var i = that.data.order.indexOf(target) | ||||||
|  | 					var lst = [] | ||||||
|  | 
 | ||||||
|  | 					// get the list of URLs before and after current...
 | ||||||
|  | 					_get(i ,lst, source, radius, 0, 1) | ||||||
|  | 					_get(i, lst, source, radius, 1, -1) | ||||||
|  | 
 | ||||||
|  | 					// get target preview in case the target is not loaded...
 | ||||||
|  | 					var p = _getPreview(that.data.getImage(target)) | ||||||
|  | 					p && lst.splice(0, 0, p) | ||||||
|  | 
 | ||||||
|  | 					// web worker...
 | ||||||
|  | 					if(that.cacheWorker != null){ | ||||||
|  | 						that.cacheWorker.postMessage(lst) | ||||||
|  | 
 | ||||||
|  | 					// async inline...
 | ||||||
|  | 					} else { | ||||||
|  | 						// do the actual preloading...
 | ||||||
|  | 						lst.forEach(function(url){ | ||||||
|  | 							var img = new Image() | ||||||
|  | 							img.src = url | ||||||
|  | 						}) | ||||||
|  | 					} | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(that.cacheWorker != null){ | ||||||
|  | 				_run() | ||||||
|  | 
 | ||||||
|  | 			} else { | ||||||
|  | 				setTimeout(_run, 0) | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var PreCache =  | ||||||
|  | module.PreCache = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-partial-ribbons-precache', | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: PreCacheActions,  | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		['focusImage.post',  | ||||||
|  | 			function(_, target){  | ||||||
|  | 				this.preCacheJumpTargets(target) }], | ||||||
|  | 		/*/ | ||||||
|  | 		['resizing.pre', | ||||||
|  | 			function(unit, size){  | ||||||
|  | 				this.preCacheJumpTargets() }], | ||||||
|  | 		//*/
 | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /********************************************************************** | ||||||
|  | * vim:set ts=4 sw=4 :                               */ return module }) | ||||||
| @ -24,212 +24,18 @@ var core = require('features/core') | |||||||
| // XXX updateRibbon(..) is not signature compatible with data.updateRibbon(..)
 | // XXX updateRibbon(..) is not signature compatible with data.updateRibbon(..)
 | ||||||
| var PartialRibbonsActions = actions.Actions({ | var PartialRibbonsActions = actions.Actions({ | ||||||
| 	config: { | 	config: { | ||||||
| 		// number of screen widths to load...
 | 		// Number of screen widths to load...
 | ||||||
| 		'ribbon-size-screens': 7, | 		'ribbon-size-screens': 7, | ||||||
| 
 | 
 | ||||||
| 		// number of screen widths to edge to trigger reload...
 | 		// Number of screen widths to edge to trigger reload...
 | ||||||
| 		'ribbon-resize-threshold': 1.5, | 		'ribbon-resize-threshold': 1.5, | ||||||
| 
 | 
 | ||||||
| 		// timeout before a non-forced ribbon size update happens after
 | 		// Timeout before a non-forced ribbon size update happens after
 | ||||||
| 		// the action...
 | 		// the action...
 | ||||||
| 		// NOTE: if set to null, the update will be sync...
 | 		// NOTE: if set to null, the update will be sync...
 | ||||||
| 		'ribbon-update-timeout': 120, | 		'ribbon-update-timeout': 120, | ||||||
| 
 |  | ||||||
| 		// how many non-adjacent images to preload...
 |  | ||||||
| 		'preload-radius': 5, |  | ||||||
| 
 |  | ||||||
| 		// sources to preload...
 |  | ||||||
| 		'preload-sources': ['bookmark', 'selected'], |  | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	// NOTE: this will not work from chrome when loading from a local fs...
 |  | ||||||
| 	// XXX experimental...
 |  | ||||||
| 	startCacheWorker: ['Interface/', |  | ||||||
| 		function(){ |  | ||||||
| 			// a worker is started already...
 |  | ||||||
| 			if(this.cacheWorker != null){ |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			var b = new Blob([[ |  | ||||||
| 				'addEventListener(\'message\', function(e) {', |  | ||||||
| 				'	var urls = e.data', |  | ||||||
| 				'	urls = urls.constructor !== Array ? [urls] : urls', |  | ||||||
| 				'	var l = urls.length', |  | ||||||
| 				'	urls.forEach(function(url){', |  | ||||||
| 				'		var xhr = new XMLHttpRequest()', |  | ||||||
| 				'		xhr.responseType = \'blob\'', |  | ||||||
| 				/* |  | ||||||
| 				'		xhr.onload = xhr.onerror = function(){', |  | ||||||
| 				'			l -= 1', |  | ||||||
| 				'			if(l <= 0){', |  | ||||||
| 				'				postMessage({status: \'done.\', urls: urls})', |  | ||||||
| 				'			}', |  | ||||||
| 				'		}', |  | ||||||
| 				*/ |  | ||||||
| 				'		xhr.open(\'GET\', url, true)', |  | ||||||
| 				'		xhr.send()', |  | ||||||
| 				'	})', |  | ||||||
| 				'}, false)', |  | ||||||
| 			].join('\n')]) |  | ||||||
| 
 |  | ||||||
| 			var url = URL.createObjectURL(b) |  | ||||||
| 
 |  | ||||||
| 			this.cacheWorker = new Worker(url) |  | ||||||
| 			this.cacheWorker.url = url |  | ||||||
| 		}], |  | ||||||
| 	stopCacheWorker: ['Interface/', |  | ||||||
| 		function(){ |  | ||||||
| 			if(this.cacheWorker){ |  | ||||||
| 				this.cacheWorker.terminate() |  | ||||||
| 				URL.revokeObjectURL(this.cacheWorker.url) |  | ||||||
| 				delete this.cacheWorker |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// Pre-load images...
 |  | ||||||
| 	//
 |  | ||||||
| 	// Sources supported:
 |  | ||||||
| 	// 	<tag>			- pre-load images tagged with <tag> 
 |  | ||||||
| 	// 					  (default: ['bookmark', 'selected']) 
 |  | ||||||
| 	// 	<ribbon-gid>	- pre-cache from a specific ribbon
 |  | ||||||
| 	// 	'ribbon'		- pre-cache from current ribbon
 |  | ||||||
| 	// 	'order'			- pre-cache from images in order
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: workers when loaded from file:// in a browser context 
 |  | ||||||
| 	// 		will not have access to local images...
 |  | ||||||
| 	//
 |  | ||||||
| 	// XXX need a clear strategy to run this...
 |  | ||||||
| 	// XXX might be a good idea to make the worker queue the lists...
 |  | ||||||
| 	// 		...this will need careful prioritization logic...
 |  | ||||||
| 	// 			- avoid loading the same url too often
 |  | ||||||
| 	// 			- load the most probable urls first
 |  | ||||||
| 	// 				- next targets
 |  | ||||||
| 	// 					- next/prev
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, 'ribbon', this.screenwidth)
 |  | ||||||
| 	// 					- next/prev marked/bookmarked/order
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, 'marked')
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, 'bookmarked')
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, 'order')
 |  | ||||||
| 	// 					- next/prev screen
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, 'ribbon',
 |  | ||||||
| 	// 							this.config['preload-radius'] * this.screenwidth)
 |  | ||||||
| 	// 					- next/prev ribbon
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, this.data.getRibbon(target, 1))
 |  | ||||||
| 	// 						.preCacheJumpTargets(target, this.data.getRibbon(target, -1))
 |  | ||||||
| 	// 				- next blocks
 |  | ||||||
| 	// 					- what resize ribbon does...
 |  | ||||||
| 	// XXX coordinate this with .resizeRibbon(..)
 |  | ||||||
| 	// XXX make this support an explicit list of gids....
 |  | ||||||
| 	// XXX should this be here???
 |  | ||||||
| 	preCacheJumpTargets: ['- Interface/Pre-cache potential jump target images', |  | ||||||
| 		function(target, sources, radius, size){ |  | ||||||
| 			target = target instanceof jQuery  |  | ||||||
| 				? this.ribbons.getElemGID(target) |  | ||||||
| 				// NOTE: data.getImage(..) can return null at start or end
 |  | ||||||
| 				// 		of ribbon, thus we need to account for this...
 |  | ||||||
| 				: (this.data.getImage(target) |  | ||||||
| 					|| this.data.getImage(target, 'after')) |  | ||||||
| 
 |  | ||||||
| 			sources = sources || this.config['preload-sources'] || ['bookmark', 'selected'] |  | ||||||
| 			sources = sources.constructor !== Array ? [sources] : sources |  | ||||||
| 			radius = radius || this.config['preload-radius'] || 9 |  | ||||||
| 
 |  | ||||||
| 			var that = this |  | ||||||
| 
 |  | ||||||
| 			// get preview...
 |  | ||||||
| 			var _getPreview = function(c){ |  | ||||||
| 				return that.images[c]  |  | ||||||
| 					&& that.images.getBestPreview(c, size, true).url |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// get a set of paths...
 |  | ||||||
| 			// NOTE: we are also ordering the resulting gids by their 
 |  | ||||||
| 			// 		distance from target...
 |  | ||||||
| 			var _get = function(i, lst, source, radius, oddity, step){ |  | ||||||
| 				var found = oddity |  | ||||||
| 				var max = source.length  |  | ||||||
| 
 |  | ||||||
| 				for(var j = i+step; (step > 0 && j < max) || (step < 0 && j >= 0); j += step){ |  | ||||||
| 					var c = source[j] |  | ||||||
| 
 |  | ||||||
| 					if(c == null || that.images[c] == null){ |  | ||||||
| 						continue |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					// build the URL...
 |  | ||||||
| 					lst[found] = _getPreview(c) |  | ||||||
| 
 |  | ||||||
| 					found += 2 |  | ||||||
| 					if(found >= radius*2){ |  | ||||||
| 						break |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// run the actual preload...
 |  | ||||||
| 			var _run = function(){ |  | ||||||
| 				sources.forEach(function(tag){ |  | ||||||
| 					// order...
 |  | ||||||
| 					if(tag == 'order'){ |  | ||||||
| 						var source = that.data.order |  | ||||||
| 
 |  | ||||||
| 					// current ribbon...
 |  | ||||||
| 					}else if(tag == 'ribbon'){ |  | ||||||
| 						var source = that.data.ribbons[that.data.getRibbon()] |  | ||||||
| 
 |  | ||||||
| 					// ribbon-gid...
 |  | ||||||
| 					} else if(tag in that.data.ribbons){ |  | ||||||
| 						var source = that.data.ribbons[tag] |  | ||||||
| 				 |  | ||||||
| 					// nothing tagged then nothing to do...
 |  | ||||||
| 					} else if(that.data.tags == null  |  | ||||||
| 							|| that.data.tags[tag] == null  |  | ||||||
| 							|| that.data.tags[tag].length == 0){ |  | ||||||
| 						return  |  | ||||||
| 
 |  | ||||||
| 					// tag...
 |  | ||||||
| 					} else { |  | ||||||
| 						var source = that.data.tags[tag] |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					size = size || that.ribbons.getVisibleImageSize()  |  | ||||||
| 
 |  | ||||||
| 					var i = that.data.order.indexOf(target) |  | ||||||
| 					var lst = [] |  | ||||||
| 
 |  | ||||||
| 					// get the list of URLs before and after current...
 |  | ||||||
| 					_get(i ,lst, source, radius, 0, 1) |  | ||||||
| 					_get(i, lst, source, radius, 1, -1) |  | ||||||
| 
 |  | ||||||
| 					// get target preview in case the target is not loaded...
 |  | ||||||
| 					var p = _getPreview(that.data.getImage(target)) |  | ||||||
| 					p && lst.splice(0, 0, p) |  | ||||||
| 
 |  | ||||||
| 					// web worker...
 |  | ||||||
| 					if(that.cacheWorker != null){ |  | ||||||
| 						that.cacheWorker.postMessage(lst) |  | ||||||
| 
 |  | ||||||
| 					// async inline...
 |  | ||||||
| 					} else { |  | ||||||
| 						// do the actual preloading...
 |  | ||||||
| 						lst.forEach(function(url){ |  | ||||||
| 							var img = new Image() |  | ||||||
| 							img.src = url |  | ||||||
| 						}) |  | ||||||
| 					} |  | ||||||
| 				}) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if(that.cacheWorker != null){ |  | ||||||
| 				_run() |  | ||||||
| 
 |  | ||||||
| 			} else { |  | ||||||
| 				setTimeout(_run, 0) |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	// NOTE: this will force sync resize if one of the following is true:
 | 	// NOTE: this will force sync resize if one of the following is true:
 | ||||||
| 	// 		- the target is not loaded
 | 	// 		- the target is not loaded
 | ||||||
| 	// 		- we are less than screen width from the edge
 | 	// 		- we are less than screen width from the edge
 | ||||||
| @ -312,39 +118,6 @@ var PartialRibbonsActions = actions.Actions({ | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}], | 		}], | ||||||
| 	// XXX do we handle off-screen ribbons here???
 |  | ||||||
| 	resizeRibbon: ['- Interface/Resize ribbon to n images', |  | ||||||
| 		function(target, size){ |  | ||||||
| 			size = size  |  | ||||||
| 				|| (this.config['ribbon-size-screens'] * this.screenwidth) |  | ||||||
| 				|| (5 * this.screenwidth) |  | ||||||
| 			var data = this.data |  | ||||||
| 			var ribbons = this.ribbons |  | ||||||
| 
 |  | ||||||
| 			// NOTE: we can't get ribbon via target directly here as
 |  | ||||||
| 			// 		the target might not be loaded...
 |  | ||||||
| 			var r_gid = data.getRibbon(target) |  | ||||||
| 
 |  | ||||||
| 			if(r_gid == null){ |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// localize transition prevention... 
 |  | ||||||
| 			// NOTE: for the initial load this may be empty...
 |  | ||||||
| 			var r = ribbons.getRibbon(r_gid) |  | ||||||
| 
 |  | ||||||
| 			// XXX do we need to for example ignore unloaded (r.length == 0)
 |  | ||||||
| 			// 		ribbons here, for example not load ribbons too far off 
 |  | ||||||
| 			// 		screen??
 |  | ||||||
| 			 |  | ||||||
| 			ribbons |  | ||||||
| 				.preventTransitions(r) |  | ||||||
| 				.updateRibbon( |  | ||||||
| 					data.getImages(target, size),  |  | ||||||
| 					r_gid, |  | ||||||
| 					target) |  | ||||||
| 				.restoreTransitions(r, true) |  | ||||||
| 		}] |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| // NOTE: I do not fully understand it yet, but PartialRibbons must be 
 | // NOTE: I do not fully understand it yet, but PartialRibbons must be 
 | ||||||
| @ -370,6 +143,9 @@ module.PartialRibbons = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'ui' | 		'ui' | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-partial-ribbons-precache', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	actions: PartialRibbonsActions, | 	actions: PartialRibbonsActions, | ||||||
| @ -384,14 +160,15 @@ module.PartialRibbons = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 				this.updateRibbon(target) | 				this.updateRibbon(target) | ||||||
| 			}], | 			}], | ||||||
| 		['focusImage.post',  |  | ||||||
| 			function(_, target){ |  | ||||||
| 				this.preCacheJumpTargets(target) |  | ||||||
| 			}], |  | ||||||
| 
 |  | ||||||
| 		['resizing.pre', | 		['resizing.pre', | ||||||
| 			function(unit, size){ | 			function(unit, size){ | ||||||
| 				if(unit == 'scale'){ | 				// keep constant size in single image...
 | ||||||
|  | 				if(this.toggleSingleImage && this.toggleSingleImage('?') == 'on'){ | ||||||
|  | 					this.updateRibbon( | ||||||
|  | 						'current',  | ||||||
|  | 						this.config['ribbons-resize-single-image'] || 13) | ||||||
|  | 
 | ||||||
|  | 				} else if(unit == 'scale'){ | ||||||
| 					this.updateRibbon('current', this.screenwidth / size || 1) | 					this.updateRibbon('current', this.screenwidth / size || 1) | ||||||
| 
 | 
 | ||||||
| 				} else if(unit == 'screenwidth'){ | 				} else if(unit == 'screenwidth'){ | ||||||
| @ -412,8 +189,6 @@ module.PartialRibbons = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 					this.updateRibbon('current', nw) | 					this.updateRibbon('current', nw) | ||||||
| 				} | 				} | ||||||
| 
 |  | ||||||
| 				//this.preCacheJumpTargets()
 |  | ||||||
| 			}], | 			}], | ||||||
| 	], | 	], | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -426,6 +426,41 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		})], | 		})], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 	// NOTE: this not used directly, mainly designed as a utility to be 
 | ||||||
|  | 	// 		used for various partial ribbon implementations...
 | ||||||
|  | 	// XXX do we handle off-screen ribbons here???
 | ||||||
|  | 	resizeRibbon: ['- Interface/Resize ribbon to n images', | ||||||
|  | 		function(target, size){ | ||||||
|  | 			size = size  | ||||||
|  | 				|| (this.config['ribbon-size-screens'] * this.screenwidth) | ||||||
|  | 				|| (5 * this.screenwidth) | ||||||
|  | 			var data = this.data | ||||||
|  | 			var ribbons = this.ribbons | ||||||
|  | 
 | ||||||
|  | 			// localize transition prevention... 
 | ||||||
|  | 			// NOTE: we can't get ribbon via target directly here as
 | ||||||
|  | 			// 		the target might not be loaded...
 | ||||||
|  | 			var r_gid = data.getRibbon(target) | ||||||
|  | 			if(r_gid == null){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			// NOTE: for the initial load this may be empty...
 | ||||||
|  | 			var r = ribbons.getRibbon(r_gid) | ||||||
|  | 
 | ||||||
|  | 			// XXX do we need to for example ignore unloaded (r.length == 0)
 | ||||||
|  | 			// 		ribbons here, for example not load ribbons too far off 
 | ||||||
|  | 			// 		screen??
 | ||||||
|  | 			 | ||||||
|  | 			ribbons | ||||||
|  | 				.preventTransitions(r) | ||||||
|  | 				.updateRibbon( | ||||||
|  | 					data.getImages(target, size, 'total'),  | ||||||
|  | 					r_gid, | ||||||
|  | 					target) | ||||||
|  | 				.restoreTransitions(r, true) | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	// General UI stuff...
 | 	// General UI stuff...
 | ||||||
| 	// NOTE: this is applicable to all uses...
 | 	// NOTE: this is applicable to all uses...
 | ||||||
| 	toggleTheme: ['Interface/Theme/Viewer theme',  | 	toggleTheme: ['Interface/Theme/Viewer theme',  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user