mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	refactoring of the ui/render/access -- started split of viewer into a renderer and viewer actions...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									796bd4d8cb
								
							
						
					
					
						commit
						22627468eb
					
				| @ -132,7 +132,7 @@ var AppControlActions = actions.Actions({ | |||||||
| 					this.ribbons.preventTransitions() | 					this.ribbons.preventTransitions() | ||||||
| 
 | 
 | ||||||
| 					// hide the viewer to hide any animation crimes...
 | 					// hide the viewer to hide any animation crimes...
 | ||||||
| 					this.ribbons.viewer[0].style.visibility = 'hidden' | 					this.dom[0].style.visibility = 'hidden' | ||||||
| 
 | 
 | ||||||
| 					// XXX async...
 | 					// XXX async...
 | ||||||
| 					// 		...this complicates things as we need to do the next
 | 					// 		...this complicates things as we need to do the next
 | ||||||
| @ -146,7 +146,7 @@ var AppControlActions = actions.Actions({ | |||||||
| 							.ribbons | 							.ribbons | ||||||
| 								.restoreTransitions() | 								.restoreTransitions() | ||||||
| 
 | 
 | ||||||
| 						that.ribbons.viewer[0].style.visibility = '' | 						that.dom[0].style.visibility = '' | ||||||
| 					}, 100) | 					}, 100) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| @ -292,7 +292,7 @@ module.AppButtons = core.ImageGridFeatures.Feature({ | |||||||
| 		['start toggleFullScreen',  | 		['start toggleFullScreen',  | ||||||
| 			function(){ | 			function(){ | ||||||
| 				var fullscreen = this.toggleFullScreen('?') | 				var fullscreen = this.toggleFullScreen('?') | ||||||
| 				var buttons = this.ribbons.viewer.find('.app-buttons') | 				var buttons = this.dom.find('.app-buttons') | ||||||
| 				 | 				 | ||||||
| 				// fullscreen button...
 | 				// fullscreen button...
 | ||||||
| 				buttons.find('.fullscreen.button') | 				buttons.find('.fullscreen.button') | ||||||
|  | |||||||
| @ -175,7 +175,7 @@ var ExternalEditorUIActions = actions.Actions({ | |||||||
| 								var path = e.find('.text').last().text() | 								var path = e.find('.text').last().text() | ||||||
| 								var txt = e.find('.text').first().text() | 								var txt = e.find('.text').first().text() | ||||||
| 
 | 
 | ||||||
| 								var b = overlay.Overlay(that.ribbons.viewer,  | 								var b = overlay.Overlay(that.dom,  | ||||||
| 									browseWalk.makeWalk(null, path,  | 									browseWalk.makeWalk(null, path,  | ||||||
| 											// XXX
 | 											// XXX
 | ||||||
| 											'*+(exe|cmd|ps1|sh)', | 											'*+(exe|cmd|ps1|sh)', | ||||||
| @ -291,7 +291,7 @@ var ExternalEditorUIActions = actions.Actions({ | |||||||
| 					make(['Add new editor...']) | 					make(['Add new editor...']) | ||||||
| 						.on('open', function(){ | 						.on('open', function(){ | ||||||
| 							closingPrevented = true | 							closingPrevented = true | ||||||
| 							var b = overlay.Overlay(that.ribbons.viewer,  | 							var b = overlay.Overlay(that.dom,  | ||||||
| 								browseWalk.makeWalk( | 								browseWalk.makeWalk( | ||||||
| 										null, '/',  | 										null, '/',  | ||||||
| 										// XXX
 | 										// XXX
 | ||||||
|  | |||||||
| @ -458,7 +458,7 @@ var KeyboardActions = actions.Actions({ | |||||||
| 							return that.__keyboard_config | 							return that.__keyboard_config | ||||||
| 						} | 						} | ||||||
| 					}, | 					}, | ||||||
| 					function(){ return that.ribbons.viewer }) | 					function(){ return that.dom }) | ||||||
| 		return kb }, | 		return kb }, | ||||||
| 
 | 
 | ||||||
| 	testKeyboardDoc: ['- Interface/', | 	testKeyboardDoc: ['- Interface/', | ||||||
| @ -718,9 +718,9 @@ var KeyboardActions = actions.Actions({ | |||||||
| 				// NOTE: the target element must be focusable...
 | 				// NOTE: the target element must be focusable...
 | ||||||
| 				var target = | 				var target = | ||||||
| 				this.__keyboard_event_source = | 				this.__keyboard_event_source = | ||||||
| 					this.config['keyboard-event-source'] == null ? this.ribbons.viewer  | 					this.config['keyboard-event-source'] == null ? this.dom  | ||||||
| 					: this.config['keyboard-event-source'] == 'window' ? $(window) | 					: this.config['keyboard-event-source'] == 'window' ? $(window) | ||||||
| 					: this.config['keyboard-event-source'] == 'viewer' ? this.ribbons.viewer | 					: this.config['keyboard-event-source'] == 'viewer' ? this.dom | ||||||
| 					: this.config['keyboard-event-source'] == 'document' ? $(document) | 					: this.config['keyboard-event-source'] == 'document' ? $(document) | ||||||
| 					: $(this.config['keyboard-event-source']) | 					: $(this.config['keyboard-event-source']) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -66,10 +66,14 @@ core.ImageGridFeatures.Feature('viewer-testing', [ | |||||||
| 	'ui', | 	'ui', | ||||||
| 	'keyboard', | 	'keyboard', | ||||||
| 
 | 
 | ||||||
|  | 	// XXX BUG?: should this be indicated as a missing dependency???
 | ||||||
|  | 	'missing-feature', | ||||||
|  | 
 | ||||||
| 	// XXX
 | 	// XXX
 | ||||||
| 	'ui-ribbons-render', | 	'ui-ribbons-render', | ||||||
| 	'ui-vdom-render', | 	'ui-vdom-render', | ||||||
| 	'ui-react-render', | 	//'ui-react-render',
 | ||||||
|  | 	//*/
 | ||||||
| 
 | 
 | ||||||
| 	// features...
 | 	// features...
 | ||||||
| 	'ui-cursor', | 	'ui-cursor', | ||||||
|  | |||||||
| @ -46,12 +46,12 @@ var BoundsIndicatorsActions = actions.Actions({ | |||||||
| 				bottom: '.bottom-indicator', | 				bottom: '.bottom-indicator', | ||||||
| 			}[direction] | 			}[direction] | ||||||
| 
 | 
 | ||||||
| 			var indicator = this.ribbons.viewer.find(cls) | 			var indicator = this.dom.find(cls) | ||||||
| 
 | 
 | ||||||
| 			if(indicator.length == 0){ | 			if(indicator.length == 0){ | ||||||
| 				indicator = $('<div>') | 				indicator = $('<div>') | ||||||
| 					.addClass(cls.replace('.', '')) | 					.addClass(cls.replace('.', '')) | ||||||
| 					.appendTo(this.ribbons.viewer) | 					.appendTo(this.dom) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return indicator | 			return indicator | ||||||
| @ -262,7 +262,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({ | |||||||
| 			function(){ | 			function(){ | ||||||
| 				var fadein = this.config['current-image-indicator-fadein'] | 				var fadein = this.config['current-image-indicator-fadein'] | ||||||
| 				this.updateCurrentImageIndicator() | 				this.updateCurrentImageIndicator() | ||||||
| 				this.ribbons.viewer.find('.current-marker') | 				this.dom.find('.current-marker') | ||||||
| 					.css({ | 					.css({ | ||||||
| 						display: 'block', | 						display: 'block', | ||||||
| 						opacity: 0, | 						opacity: 0, | ||||||
| @ -302,7 +302,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({ | |||||||
| 					&& clearTimeout(this.__current_image_indicator_restore_timeout) | 					&& clearTimeout(this.__current_image_indicator_restore_timeout) | ||||||
| 				delete this.__current_image_indicator_restore_timeout | 				delete this.__current_image_indicator_restore_timeout | ||||||
| 
 | 
 | ||||||
| 				this.ribbons.viewer | 				this.dom | ||||||
| 					.find('.current-marker') | 					.find('.current-marker') | ||||||
| 						.velocity({opacity: 0}, { duration: 100 }) | 						.velocity({opacity: 0}, { duration: 100 }) | ||||||
| 			}], | 			}], | ||||||
| @ -312,7 +312,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({ | |||||||
| 				this.__current_image_indicator_restore_timeout = setTimeout(function(){ | 				this.__current_image_indicator_restore_timeout = setTimeout(function(){ | ||||||
| 					that.updateCurrentImageIndicator() | 					that.updateCurrentImageIndicator() | ||||||
| 
 | 
 | ||||||
| 					that.ribbons.viewer | 					that.dom | ||||||
| 						.find('.current-marker') | 						.find('.current-marker') | ||||||
| 							.velocity({opacity: 1}, { duration: 100 }) | 							.velocity({opacity: 1}, { duration: 100 }) | ||||||
| 				}, this.config['current-image-indicator-restore-delay'] || 500) | 				}, this.config['current-image-indicator-restore-delay'] || 500) | ||||||
| @ -322,12 +322,12 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({ | |||||||
| 		['toggleSingleImage', | 		['toggleSingleImage', | ||||||
| 			function(){ | 			function(){ | ||||||
| 				if(this.toggleSingleImage('?') == 'off'){ | 				if(this.toggleSingleImage('?') == 'off'){ | ||||||
| 					this.ribbons.viewer.find('.current-marker') | 					this.dom.find('.current-marker') | ||||||
| 						.delay(150) | 						.delay(150) | ||||||
| 						.animate({opacity: 1}, 100) | 						.animate({opacity: 1}, 100) | ||||||
| 
 | 
 | ||||||
| 				} else { | 				} else { | ||||||
| 					this.ribbons.viewer.find('.current-marker') | 					this.dom.find('.current-marker') | ||||||
| 						.css({ opacity: 0 }) | 						.css({ opacity: 0 }) | ||||||
| 				} | 				} | ||||||
| 			}], | 			}], | ||||||
| @ -343,7 +343,7 @@ var makeIndicatorHiderOnFastAction = function(hide_timeout){ | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		var that = this | 		var that = this | ||||||
| 		var m = this.ribbons.viewer.find('.current-marker') | 		var m = this.dom.find('.current-marker') | ||||||
| 		var t = this.config[hide_timeout] | 		var t = this.config[hide_timeout] | ||||||
| 
 | 
 | ||||||
| 		var cur = this.current | 		var cur = this.current | ||||||
| @ -431,13 +431,13 @@ module.CurrentImageIndicatorHideOnScreenNav = core.ImageGridFeatures.Feature({ | |||||||
| 		// NOTE: we use .pre events here to see if we have moved...
 | 		// NOTE: we use .pre events here to see if we have moved...
 | ||||||
| 		['prevScreen.post nextScreen.post', | 		['prevScreen.post nextScreen.post', | ||||||
| 			function(){  | 			function(){  | ||||||
| 				var m = this.ribbons.viewer.find('.current-marker') | 				var m = this.dom.find('.current-marker') | ||||||
| 
 | 
 | ||||||
| 				m.css({ opacity: 0 }) | 				m.css({ opacity: 0 }) | ||||||
| 			}], | 			}], | ||||||
| 		['focusImage.post', | 		['focusImage.post', | ||||||
| 			function(){  | 			function(){  | ||||||
| 				var m = this.ribbons.viewer.find('.current-marker') | 				var m = this.dom.find('.current-marker') | ||||||
| 
 | 
 | ||||||
| 				m.css({ opacity: '' }) | 				m.css({ opacity: '' }) | ||||||
| 			}], | 			}], | ||||||
| @ -464,7 +464,7 @@ var updateBaseRibbonIndicator = function(img){ | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if(m.length == 0){ | 	if(m.length == 0){ | ||||||
| 		m = this.ribbons.viewer.find('.base-ribbon-marker') | 		m = this.dom.find('.base-ribbon-marker') | ||||||
| 
 | 
 | ||||||
| 		// make the indicator...
 | 		// make the indicator...
 | ||||||
| 		if(m.length == 0){ | 		if(m.length == 0){ | ||||||
| @ -478,7 +478,7 @@ var updateBaseRibbonIndicator = function(img){ | |||||||
| 
 | 
 | ||||||
| 	// XXX this is wrong -- need to calculate the offset after the move and not now...
 | 	// XXX this is wrong -- need to calculate the offset after the move and not now...
 | ||||||
| 	if(base.offset().left < 0){ | 	if(base.offset().left < 0){ | ||||||
| 		m.css('left', (img.position().left + img.width()/2 - this.ribbons.viewer.width()/2) / scale) | 		m.css('left', (img.position().left + img.width()/2 - this.dom.width()/2) / scale) | ||||||
| 
 | 
 | ||||||
| 	} else { | 	} else { | ||||||
| 		m.css('left', '') | 		m.css('left', '') | ||||||
| @ -530,7 +530,7 @@ module.PassiveBaseRibbonIndicator = core.ImageGridFeatures.Feature({ | |||||||
| 	actions: actions.Actions({ | 	actions: actions.Actions({ | ||||||
| 		togglePassiveBaseRibbonIndicator: ['Interface/Passive base ribbon indicator', | 		togglePassiveBaseRibbonIndicator: ['Interface/Passive base ribbon indicator', | ||||||
| 			toggler.CSSClassToggler( | 			toggler.CSSClassToggler( | ||||||
| 				function(){ return this.ribbons.viewer },  | 				function(){ return this.dom },  | ||||||
| 				'show-passive-base-ribbon-indicator', | 				'show-passive-base-ribbon-indicator', | ||||||
| 				function(state){  | 				function(state){  | ||||||
| 					this.config['ui-show-passive-base-ribbon-indicator'] = state == 'on' }) ], | 					this.config['ui-show-passive-base-ribbon-indicator'] = state == 'on' }) ], | ||||||
|  | |||||||
| @ -153,7 +153,7 @@ module.DirectControlHammer = core.ImageGridFeatures.Feature({ | |||||||
| 								// hide and remove current image indicator...
 | 								// hide and remove current image indicator...
 | ||||||
| 								// NOTE: it will be reconstructed on 
 | 								// NOTE: it will be reconstructed on 
 | ||||||
| 								// 		next .focusImage(..)
 | 								// 		next .focusImage(..)
 | ||||||
| 								var m = that.ribbons.viewer | 								var m = that.dom | ||||||
| 									.find('.current-marker') | 									.find('.current-marker') | ||||||
| 										.velocity({opacity: 0}, { | 										.velocity({opacity: 0}, { | ||||||
| 											duration: 100, | 											duration: 100, | ||||||
| @ -245,14 +245,14 @@ module.IndirectControl = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 					if(state == null){ | 					if(state == null){ | ||||||
| 						return (this.ribbons  | 						return (this.ribbons  | ||||||
| 								&& this.ribbons.viewer  | 								&& this.dom  | ||||||
| 								&& this.ribbons.viewer.data('hammer'))  | 								&& this.dom.data('hammer'))  | ||||||
| 							|| 'none' | 							|| 'none' | ||||||
| 
 | 
 | ||||||
| 					// on...
 | 					// on...
 | ||||||
| 					} else if(state == 'handling-swipes'){ | 					} else if(state == 'handling-swipes'){ | ||||||
| 						var that = this | 						var that = this | ||||||
| 						var viewer = this.ribbons.viewer | 						var viewer = this.dom | ||||||
| 
 | 
 | ||||||
| 						// prevent multiple handlers...
 | 						// prevent multiple handlers...
 | ||||||
| 						if(viewer.data('hammer') != null){ | 						if(viewer.data('hammer') != null){ | ||||||
| @ -272,7 +272,7 @@ module.IndirectControl = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 					// off...
 | 					// off...
 | ||||||
| 					} else { | 					} else { | ||||||
| 						this.ribbons.viewer | 						this.dom | ||||||
| 							.off('swipeleft') | 							.off('swipeleft') | ||||||
| 							.off('swiperight') | 							.off('swiperight') | ||||||
| 							.off('swipeup') | 							.off('swipeup') | ||||||
|  | |||||||
| @ -435,9 +435,7 @@ var VirtualDOMRibbonsPrototype = { | |||||||
| 	// 		concept, so we build the state on demand...
 | 	// 		concept, so we build the state on demand...
 | ||||||
| 	// XXX get scale from config on initial load...
 | 	// XXX get scale from config on initial load...
 | ||||||
| 	sync: function(target, size){ | 	sync: function(target, size){ | ||||||
| 		var dom = this.dom = this.dom  | 		var dom = this.dom | ||||||
| 			// get/create the ribbon-set...
 |  | ||||||
| 			|| this.imagegrid.ribbons.getRibbonSet(true) |  | ||||||
| 
 | 
 | ||||||
| 		var state = this.state ? Object.create(this.state) : {} | 		var state = this.state ? Object.create(this.state) : {} | ||||||
| 		target && (state.target = target) | 		target && (state.target = target) | ||||||
| @ -447,7 +445,7 @@ var VirtualDOMRibbonsPrototype = { | |||||||
| 		if(this.vdom == null){ | 		if(this.vdom == null){ | ||||||
| 			var n = this.vdom = this.makeView(state, true) | 			var n = this.vdom = this.makeView(state, true) | ||||||
| 			var v = vdom.create(n) | 			var v = vdom.create(n) | ||||||
| 			dom.replaceWith(v) | 			this.imagegrid.dom.append(v) | ||||||
| 			this.dom = v | 			this.dom = v | ||||||
| 
 | 
 | ||||||
| 		// patch state...
 | 		// patch state...
 | ||||||
|  | |||||||
| @ -48,7 +48,7 @@ var ProgressActions = actions.Actions({ | |||||||
| 	// XXX revise styles...
 | 	// XXX revise styles...
 | ||||||
| 	showProgress: ['- Interface/Show progress bar...', | 	showProgress: ['- Interface/Show progress bar...', | ||||||
| 		function(text, value, max){ | 		function(text, value, max){ | ||||||
| 			var viewer = this.ribbons.viewer | 			var viewer = this.dom | ||||||
| 			var that = this | 			var that = this | ||||||
| 
 | 
 | ||||||
| 			var msg = text instanceof Array ? text.slice(1).join(': ') : null | 			var msg = text instanceof Array ? text.slice(1).join(': ') : null | ||||||
|  | |||||||
| @ -27,7 +27,7 @@ var RangeActions = actions.Actions({ | |||||||
| 	makeBrace: ['- Range/', | 	makeBrace: ['- Range/', | ||||||
| 		function(type, gid){ | 		function(type, gid){ | ||||||
| 			var cls = type == 'open' ? 'brace-open' : 'brace-close' | 			var cls = type == 'open' ? 'brace-open' : 'brace-close' | ||||||
| 			var r = this.ribbons.viewer.find('.ribbon') | 			var r = this.dom.find('.ribbon') | ||||||
| 
 | 
 | ||||||
| 			var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls) | 			var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls) | ||||||
| 
 | 
 | ||||||
| @ -61,7 +61,7 @@ var RangeActions = actions.Actions({ | |||||||
| 			// 		go but it sure makes things simpler...
 | 			// 		go but it sure makes things simpler...
 | ||||||
| 			if(range == null){ | 			if(range == null){ | ||||||
| 				update = true | 				update = true | ||||||
| 				this.ribbons.viewer | 				this.dom | ||||||
| 					.find('.ribbon .mark.brace') | 					.find('.ribbon .mark.brace') | ||||||
| 						.remove() | 						.remove() | ||||||
| 
 | 
 | ||||||
| @ -90,7 +90,7 @@ var RangeActions = actions.Actions({ | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if(update){ | 			if(update){ | ||||||
| 				var r = this.ribbons.viewer.find('.ribbon') | 				var r = this.dom.find('.ribbon') | ||||||
| 
 | 
 | ||||||
| 				// XXX this does not work for non-current images ...
 | 				// XXX this does not work for non-current images ...
 | ||||||
| 				this.ribbons.preventTransitions(r) | 				this.ribbons.preventTransitions(r) | ||||||
| @ -103,7 +103,7 @@ var RangeActions = actions.Actions({ | |||||||
| 		// XXX not sure if this is the right way to go...
 | 		// XXX not sure if this is the right way to go...
 | ||||||
| 		{browseMode: function(){ return !this.data.__range && 'disabled' }}, | 		{browseMode: function(){ return !this.data.__range && 'disabled' }}, | ||||||
| 		function(image){ | 		function(image){ | ||||||
| 			var r = this.ribbons.viewer.find('.ribbon') | 			var r = this.dom.find('.ribbon') | ||||||
| 
 | 
 | ||||||
| 			delete this.data.__range | 			delete this.data.__range | ||||||
| 			this.updateRangeIndicators() | 			this.updateRangeIndicators() | ||||||
| @ -246,7 +246,7 @@ module.Range = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 		// show/hide off-screen indicators...
 | 		// show/hide off-screen indicators...
 | ||||||
| 		// XXX STUB: should we animate indicators???
 | 		// XXX STUB: should we animate indicators???
 | ||||||
| 		['setScale.pre', | 		['viewScale.pre', | ||||||
| 			function(scale){ | 			function(scale){ | ||||||
| 				var range = this.data.__range | 				var range = this.data.__range | ||||||
| 				if(!this.ribbons || !range){ | 				if(!this.ribbons || !range){ | ||||||
| @ -259,7 +259,7 @@ module.Range = core.ImageGridFeatures.Feature({ | |||||||
| 			}], | 			}], | ||||||
| 		[[ | 		[[ | ||||||
| 			'focusImage', | 			'focusImage', | ||||||
| 			'setScale', | 			'viewScale', | ||||||
| 			'updateRangeIndicators', | 			'updateRangeIndicators', | ||||||
| 		], | 		], | ||||||
| 			function(_, gid){ | 			function(_, gid){ | ||||||
| @ -273,7 +273,7 @@ module.Range = core.ImageGridFeatures.Feature({ | |||||||
| 					return | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				var Wr = this.ribbons.viewer.width() | 				var Wr = this.dom.width() | ||||||
| 				var W = (Wr / this.scale) / 2 | 				var W = (Wr / this.scale) / 2 | ||||||
| 
 | 
 | ||||||
| 				var a = this.data.getImageOrder(range[0]) | 				var a = this.data.getImageOrder(range[0]) | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
| (function(require){ var module={} // make module AMD/node compatible...
 | (function(require){ var module={} // make module AMD/node compatible...
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| 
 | 
 | ||||||
|  | var object = require('lib/object') | ||||||
| var actions = require('lib/actions') | var actions = require('lib/actions') | ||||||
| var features = require('lib/features') | var features = require('lib/features') | ||||||
| 
 | 
 | ||||||
| @ -14,9 +15,31 @@ var core = require('features/core') | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | var ViewerClassPrototype = { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var ViewerPrototype = { | ||||||
|  | 	sync: function(){ | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var Viewer = | ||||||
|  | module.Viewer = | ||||||
|  | object.makeConstructor('Viewer',  | ||||||
|  | 	ViewerClassPrototype, | ||||||
|  | 	ViewerPrototype) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| 
 | 
 | ||||||
| var ReactActions = actions.Actions({ | var ReactActions = actions.Actions({ | ||||||
|  | 	get viewer(){ | ||||||
|  | 	}, | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| var React =  | var React =  | ||||||
|  | |||||||
| @ -7,18 +7,356 @@ | |||||||
| (function(require){ var module={} // make module AMD/node compatible...
 | (function(require){ var module={} // make module AMD/node compatible...
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| 
 | 
 | ||||||
|  | var object = require('lib/object') | ||||||
| var actions = require('lib/actions') | var actions = require('lib/actions') | ||||||
| var features = require('lib/features') | var features = require('lib/features') | ||||||
| 
 | 
 | ||||||
| var core = require('features/core') | var core = require('features/core') | ||||||
| 
 | 
 | ||||||
|  | var ribbons = require('imagegrid/ribbons') | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| 
 | 
 | ||||||
| var RibbonsActions = actions.Actions({ | var RibbonsActions = actions.Actions({ | ||||||
|  | 
 | ||||||
|  | 	get dom(){ | ||||||
|  | 		return this.ribbons ? this.ribbons.viewer : undefined }, | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	// NOTE: this expects that ribbons will maintain .parent.images...
 | ||||||
|  | 	// NOTE: when getting rid of ribbons need to also remove the .parent
 | ||||||
|  | 	// 		reference...
 | ||||||
|  | 	// XXX remove...
 | ||||||
|  | 	get ribbons(){ | ||||||
|  | 		return this.__ribbons }, | ||||||
|  | 	set ribbons(ribbons){ | ||||||
|  | 		this.__ribbons = ribbons | ||||||
|  | 		ribbons.parent = this | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	load: [ | ||||||
|  | 		function(data){ | ||||||
|  | 			return function(){ | ||||||
|  | 				// recycle the viewer if one is not given specifically...
 | ||||||
|  | 				var viewer = data.viewer | ||||||
|  | 				viewer = viewer == null && this.ribbons != null  | ||||||
|  | 					? this.dom  | ||||||
|  | 					: viewer | ||||||
|  | 
 | ||||||
|  | 				if(this.ribbons == null){ | ||||||
|  | 					this.ribbons = ribbons.Ribbons(viewer, this.images) | ||||||
|  | 					// XXX is this correct???
 | ||||||
|  | 					this.ribbons.__image_updaters = [this.updateImage.bind(this)] | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 					this.ribbons.clear() | ||||||
|  | 					this.ribbons.images = this.images | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				this.reload() | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 	// NOTE: this will pass the .ribbons.updateData(..) a custom ribbon 
 | ||||||
|  | 	// 		updater if one is defined here as .updateRibbon(target) action
 | ||||||
|  | 	//
 | ||||||
|  | 	// XXX HACK: two sins:
 | ||||||
|  | 	// 		- actions.updateRibbon(..) and ribbons.updateRibbon(..)
 | ||||||
|  | 	// 		  are NOT signature compatible...
 | ||||||
|  | 	// 		- we depend on the internals of a custom add-on feature
 | ||||||
|  | 	reload: ['Interface/Reload viewer', | ||||||
|  | 		function(force){ | ||||||
|  | 			// full reload...
 | ||||||
|  | 			if(force == 'full'){ | ||||||
|  | 				//this.stop()
 | ||||||
|  | 				/* | ||||||
|  | 				killAllWorkers() | ||||||
|  | 					.done(function(){ | ||||||
|  | 						reload()  | ||||||
|  | 					}) | ||||||
|  | 				*/ | ||||||
|  | 				location.reload() | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			this.ribbons.preventTransitions() | ||||||
|  | 
 | ||||||
|  | 			// NOTE: this essentially sets the update threshold to 0...
 | ||||||
|  | 			// XXX this should be a custom arg...
 | ||||||
|  | 			force = force ? 0 : null | ||||||
|  | 
 | ||||||
|  | 			return function(){ | ||||||
|  | 				// see if we've got a custom ribbon updater...
 | ||||||
|  | 				var that = this | ||||||
|  | 				var settings = this.updateRibbon != null  | ||||||
|  | 					// XXX this should be: { updateRibbon: this.updateRibbon.bind(this) }
 | ||||||
|  | 					? { updateRibbon: function(_, ribbon){  | ||||||
|  | 							return that.updateRibbon(ribbon, null, null, force)  | ||||||
|  | 						} } | ||||||
|  | 					: null | ||||||
|  | 
 | ||||||
|  | 				this.ribbons.updateData(this.data, settings) | ||||||
|  | 
 | ||||||
|  | 				this | ||||||
|  | 					// XXX should this be here???
 | ||||||
|  | 					.refresh() | ||||||
|  | 					.focusImage() | ||||||
|  | 
 | ||||||
|  | 				// XXX HACK to make browser redraw images...
 | ||||||
|  | 				this.scale = this.scale | ||||||
|  | 
 | ||||||
|  | 				this.ribbons.restoreTransitions() | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 	// NOTE: this will trigger .updateImage hooks...
 | ||||||
|  | 	refresh: ['Interface/Refresh images without reloading', | ||||||
|  | 		function(gids, scale){ | ||||||
|  | 			gids = gids || '*' | ||||||
|  | 			var size = scale != null ?  | ||||||
|  | 				this.ribbons.getVisibleImageSize('min', scale) | ||||||
|  | 				: null | ||||||
|  | 
 | ||||||
|  | 			this.ribbons.updateImage(gids, null, size) | ||||||
|  | 		}], | ||||||
|  | 	clear: [ | ||||||
|  | 		function(){ this.ribbons && this.ribbons.clear() }], | ||||||
|  | 	// XXX do we need clone???
 | ||||||
|  | 	clone: [function(full){ | ||||||
|  | 		return function(res){ | ||||||
|  | 			if(this.ribbons){ | ||||||
|  | 				// NOTE: this is a bit wasteful as .ribbons will clone 
 | ||||||
|  | 				// 		their ref to .images that we will throw away...
 | ||||||
|  | 				res.ribbons = this.ribbons.clone() | ||||||
|  | 				res.ribbons.images = res.images | ||||||
|  | 			}  | ||||||
|  | 		} | ||||||
|  | 	}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	replaceGid: [ | ||||||
|  | 		function(from, to){ | ||||||
|  | 			return function(res){ | ||||||
|  | 				res && this.ribbons.replaceGid(from, to) | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// This is called by .ribbons, the goal is to use it to hook into 
 | ||||||
|  | 	// image updating from features and extensions...
 | ||||||
|  | 	//
 | ||||||
|  | 	// NOTE: not intended for calling manually, use .refresh(..) instead...
 | ||||||
|  | 	//
 | ||||||
|  | 	// XXX EXPERIMENTAL...
 | ||||||
|  | 	// 		...need this to get triggered by .ribbons
 | ||||||
|  | 	// 		at this point manually triggering this will not do anything...
 | ||||||
|  | 	// XXX problem: need to either redesign this or distinguish from 
 | ||||||
|  | 	// 		other actions as I keep calling it expecting results...
 | ||||||
|  | 	// XXX hide from user action list... (???)
 | ||||||
|  | 	updateImage: ['- Interface/Update image (do not use directly)', | ||||||
|  | 		'This is called by .refresh(..) and intended for use as an ' | ||||||
|  | 			+'trigger for handlers, and not as a user-callable acation.', | ||||||
|  | 		core.notUserCallable(function(gid, image){ | ||||||
|  | 			// This is the image update protocol root function
 | ||||||
|  | 			//
 | ||||||
|  | 			// Not for direct use.
 | ||||||
|  | 		})], | ||||||
|  | 
 | ||||||
|  | 	// 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) | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// NOTE: this will align only a single image...
 | ||||||
|  | 	// XXX do we need these low level primitives here???
 | ||||||
|  | 	centerImage: ['- Interface/Center an image in ribbon horizontally', | ||||||
|  | 		function(target, align, offset, scale){ | ||||||
|  | 			target = target instanceof jQuery  | ||||||
|  | 				? this.ribbons.getElemGID(target) | ||||||
|  | 				: target | ||||||
|  | 
 | ||||||
|  | 			// align current ribbon...
 | ||||||
|  | 			this.ribbons.centerImage(target, align, offset, scale) | ||||||
|  | 		}], | ||||||
|  | 	centerRibbon: ['- Interface/Center a ribbon vertically', | ||||||
|  | 		function(target){ | ||||||
|  | 			target = target instanceof jQuery  | ||||||
|  | 				? this.ribbons.getElemGID(target) | ||||||
|  | 				: target | ||||||
|  | 
 | ||||||
|  | 			// align current ribbon...
 | ||||||
|  | 			this.ribbons.centerRibbon(target) | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	focusImage: [ | ||||||
|  | 		function(target, list){ | ||||||
|  | 			return function(){ | ||||||
|  | 				this.ribbons.focusImage(this.data != null ? this.current : target) } }], | ||||||
|  | 	focusRibbon: [ | ||||||
|  | 		function(target, mode){ | ||||||
|  | 			mode = mode || this.config['ribbon-focus-mode'] | ||||||
|  | 
 | ||||||
|  | 			var c = this.data.getRibbonOrder() | ||||||
|  | 			var i = this.data.getRibbonOrder(target) | ||||||
|  | 			// NOTE: we are not changing the direction here based on 
 | ||||||
|  | 			// 		this.direction as swap will confuse the user...
 | ||||||
|  | 			var direction = c < i ? 'before' : 'after' | ||||||
|  | 
 | ||||||
|  | 			if(mode == 'visual'){ | ||||||
|  | 				var ribbons = this.ribbons | ||||||
|  | 				var r = this.data.getRibbon(target) | ||||||
|  | 				var t = ribbons.getImageByPosition('current', r) | ||||||
|  | 
 | ||||||
|  | 				if(t.length > 1){ | ||||||
|  | 					t = t.eq(direction == 'before' ? 0 : 1) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				t = ribbons.getElemGID(t) | ||||||
|  | 
 | ||||||
|  | 				this.focusImage(t, r) | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 	// Zoom/scale protocol...
 | ||||||
|  | 	resizing: [ | ||||||
|  | 		core.notUserCallable(function(unit, size, overflow){ | ||||||
|  | 			// This is a resizing protocol root function.
 | ||||||
|  | 			//
 | ||||||
|  | 			// This will never be used directly, but will wrap protocol user
 | ||||||
|  | 			// functions.
 | ||||||
|  | 			//
 | ||||||
|  | 			// As an example see: .viewScale(..)
 | ||||||
|  | 
 | ||||||
|  | 			var that = this | ||||||
|  | 			// stop currently running transition...
 | ||||||
|  | 			this.ribbons.scale(this.ribbons.scale()) | ||||||
|  | 
 | ||||||
|  | 			// transitionend handler...
 | ||||||
|  | 			if(!this.__resize_handler){ | ||||||
|  | 				this.__resize_handler = function(){ | ||||||
|  | 					that.__post_resize | ||||||
|  | 						&& that.resizingDone()  | ||||||
|  | 					delete that.__post_resize | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			this.ribbons.getRibbonSet() | ||||||
|  | 				.off('transitionend', this.__resize_handler) | ||||||
|  | 				.on('transitionend', this.__resize_handler) | ||||||
|  | 
 | ||||||
|  | 			// timeout handler...
 | ||||||
|  | 			this.__post_resize && clearTimeout(this.__post_resize) | ||||||
|  | 			return function(){ | ||||||
|  | 				this.__post_resize = setTimeout( | ||||||
|  | 					this.__resize_handler,  | ||||||
|  | 					this.config['resize-done-timeout'] || 300) | ||||||
|  | 			} | ||||||
|  | 		})], | ||||||
|  | 
 | ||||||
|  | 	viewScale: ['- Zoom/', | ||||||
|  | 		function(scale){ | ||||||
|  | 			if(scale == null || scale == '?'){ | ||||||
|  | 				return this.ribbons != null ? this.ribbons.scale() : null | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			this.resizing.chainCall(this, function(){ | ||||||
|  | 				this.ribbons  | ||||||
|  | 					&& scale  | ||||||
|  | 					&& this.ribbons.scale(scale) | ||||||
|  | 				// NOTE: we pass explicit scale here to compensate for animation...
 | ||||||
|  | 				this.refresh('*', scale) | ||||||
|  | 			}, 'scale', scale) | ||||||
|  | 		}], | ||||||
|  | 	// NOTE: if this gets a count argument it will fit count images, 
 | ||||||
|  | 	// 		default is one.
 | ||||||
|  | 	// NOTE: this will add .config['fit-overflow'] to odd counts if no 
 | ||||||
|  | 	// 		overflow if passed.
 | ||||||
|  | 	// 		...this is done to add ability to control scroll indication.
 | ||||||
|  | 	fitImage: ['Zoom/Fit image', | ||||||
|  | 		function(count, overflow){ | ||||||
|  | 			if(count == '?'){ | ||||||
|  | 				return this.ribbons != null ?  | ||||||
|  | 					this.ribbons.getScreenWidthImages()  | ||||||
|  | 					: null | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			this.resizing.chainCall(this, function(){ | ||||||
|  | 				if(count != null){ | ||||||
|  | 					overflow = overflow == false ? 0 : overflow | ||||||
|  | 					var o = overflow != null ? overflow  | ||||||
|  | 						: count % 2 != 1 ? 0 | ||||||
|  | 						: (this.config['fit-overflow'] || 0) | ||||||
|  | 					count += o | ||||||
|  | 				} | ||||||
|  | 				// XXX .ribbons...
 | ||||||
|  | 				this.ribbons.fitImage(count) | ||||||
|  | 				// NOTE: we pass explicit scale here to compensate for animation...
 | ||||||
|  | 				this.refresh('*', this.ribbons.getScreenWidthImages(1) / count) | ||||||
|  | 			}, 'screenwidth', count, overflow) | ||||||
|  | 		}], | ||||||
|  | 	// NOTE: this does not account for ribbon spacing...
 | ||||||
|  | 	fitRibbon: ['Zoom/Fit ribbon vertically', | ||||||
|  | 		function(count, whole){ | ||||||
|  | 			if(count == '?'){ | ||||||
|  | 				return this.ribbons != null ?  | ||||||
|  | 					this.ribbons.getScreenHeightRibbons()  | ||||||
|  | 					: null | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			this.resizing.chainCall(this, function(){ | ||||||
|  | 				// XXX .ribbons...
 | ||||||
|  | 				this.ribbons.fitRibbon(count, whole) | ||||||
|  | 				// NOTE: we pass explicit scale here to compensate for animation...
 | ||||||
|  | 				this.refresh('*', this.ribbons.getScreenHeightRibbons(1, whole) / count) | ||||||
|  | 			}, 'screenheight', count, whole) | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	ribbonRotation: ['- Interface|Ribbon/',  | ||||||
|  | 		function(a){  | ||||||
|  | 			if(arguments.length > 0){ | ||||||
|  | 				this.ribbons.rotate(a) | ||||||
|  | 
 | ||||||
|  | 			} else { | ||||||
|  | 				return this.ribbons.rotate() || 0 | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 	// XXX move all the stuff from UI that binds actions to ribbons...
 | ||||||
|  | 	// XXX
 | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| var Ribbons =  | var Ribbons =  | ||||||
| module.Ribbons = core.ImageGridFeatures.Feature({ | module.Ribbons = core.ImageGridFeatures.Feature({ | ||||||
| 	title: '', | 	title: '', | ||||||
| @ -29,6 +367,9 @@ module.Ribbons = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		// XXX
 | 		// XXX
 | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-ribbons-edit-render', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: RibbonsActions,  | 	actions: RibbonsActions,  | ||||||
| 
 | 
 | ||||||
| @ -37,6 +378,54 @@ module.Ribbons = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // XXX
 | ||||||
|  | 
 | ||||||
|  | var PartialRibbonsActions = actions.Actions({ | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var PartialRibbons =  | ||||||
|  | module.PartialRibbons = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-partial-ribbons-render', | ||||||
|  | 	exclusive: ['ui-render'], | ||||||
|  | 	depends: [ | ||||||
|  | 		// XXX this will need to reuse part of the actions defined in Ribbons...
 | ||||||
|  | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-ribbons-edit-render', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: PartialRibbonsActions,  | ||||||
|  | 
 | ||||||
|  | 	handlers: [], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var RibbonsEditActions = actions.Actions({ | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var RibbonsEdit =  | ||||||
|  | module.RibbonsEdit = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-ribbons-edit-render', | ||||||
|  | 	depends: [ | ||||||
|  | 		'edit', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: RibbonsEditActions,  | ||||||
|  | 
 | ||||||
|  | 	handlers: [], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /********************************************************************** | /********************************************************************** | ||||||
| * vim:set ts=4 sw=4 :                               */ return module }) | * vim:set ts=4 sw=4 :                               */ return module }) | ||||||
|  | |||||||
| @ -127,7 +127,7 @@ var SingleImageActions = actions.Actions({ | |||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			var viewer = this.ribbons.viewer | 			var viewer = this.dom | ||||||
| 
 | 
 | ||||||
| 			var ribbon = this.ribbons.getRibbon() | 			var ribbon = this.ribbons.getRibbon() | ||||||
| 			var images = viewer.find('.ribbon .image') | 			var images = viewer.find('.ribbon .image') | ||||||
| @ -239,7 +239,7 @@ var SingleImageActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 	toggleSingleImage: ['Interface/Single image view',  | 	toggleSingleImage: ['Interface/Single image view',  | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			'single-image-mode', | 			'single-image-mode', | ||||||
| 			function(state){ | 			function(state){ | ||||||
| 				if(state == 'on'){ | 				if(state == 'on'){ | ||||||
| @ -344,7 +344,7 @@ module.SingleImageView = core.ImageGridFeatures.Feature({ | |||||||
| 			function(){  | 			function(){  | ||||||
| 				// prevent this from doing anything while no viewer...
 | 				// prevent this from doing anything while no viewer...
 | ||||||
| 				if(!this.ribbons  | 				if(!this.ribbons  | ||||||
| 						|| !this.ribbons.viewer  | 						|| !this.dom  | ||||||
| 						|| this.ribbons.getRibbonSet().length == 0){ | 						|| this.ribbons.getRibbonSet().length == 0){ | ||||||
| 					return | 					return | ||||||
| 				} | 				} | ||||||
| @ -510,7 +510,7 @@ module.SingleImageViewLocalStorage = core.ImageGridFeatures.Feature({ | |||||||
| 				return function(){ | 				return function(){ | ||||||
| 					// prevent this from doing anything while no viewer...
 | 					// prevent this from doing anything while no viewer...
 | ||||||
| 					if(!this.ribbons  | 					if(!this.ribbons  | ||||||
| 							|| !this.ribbons.viewer  | 							|| !this.dom  | ||||||
| 							|| this.ribbons.getRibbonSet().length == 0){ | 							|| this.ribbons.getRibbonSet().length == 0){ | ||||||
| 						return | 						return | ||||||
| 					} | 					} | ||||||
|  | |||||||
| @ -145,7 +145,7 @@ var SlideshowActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 	toggleSlideshow: ['Slideshow/Slideshow quick toggle', | 	toggleSlideshow: ['Slideshow/Slideshow quick toggle', | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			'slideshow-running', | 			'slideshow-running', | ||||||
| 			function(state){ | 			function(state){ | ||||||
| 				// start...
 | 				// start...
 | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ var makeStateIndicatorItem = function(container, type, text){ | |||||||
| 	var item = $('<div>') | 	var item = $('<div>') | ||||||
| 			.addClass('item '+ type || '') | 			.addClass('item '+ type || '') | ||||||
| 			.attr('text', text) | 			.attr('text', text) | ||||||
| 	this.ribbons.viewer.find('.state-indicator-container.'+container) | 	this.dom.find('.state-indicator-container.'+container) | ||||||
| 		.append(item) | 		.append(item) | ||||||
| 	return item | 	return item | ||||||
| } | } | ||||||
| @ -461,11 +461,11 @@ var StatusBarActions = actions.Actions({ | |||||||
| 			// XXX change class...
 | 			// XXX change class...
 | ||||||
| 			function(){  | 			function(){  | ||||||
| 				// no viewer yet...
 | 				// no viewer yet...
 | ||||||
| 				if(!this.ribbons || !this.ribbons.viewer){ | 				if(!this.ribbons || !this.dom){ | ||||||
| 					return $() | 					return $() | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				var bar = this.ribbons.viewer.find('.state-indicator-container.global-info')  | 				var bar = this.dom.find('.state-indicator-container.global-info')  | ||||||
| 				if(bar.length == 0){ | 				if(bar.length == 0){ | ||||||
| 					bar = makeStateIndicator('global-info overlay-info statusbar')  | 					bar = makeStateIndicator('global-info overlay-info statusbar')  | ||||||
| 						.addClass(this.config['status-bar-mode']  | 						.addClass(this.config['status-bar-mode']  | ||||||
| @ -484,7 +484,7 @@ var StatusBarActions = actions.Actions({ | |||||||
| 						.on('mouseout', function(){ | 						.on('mouseout', function(){ | ||||||
| 							bar.find('.info').empty() | 							bar.find('.info').empty() | ||||||
| 						}) | 						}) | ||||||
| 						.appendTo(this.ribbons.viewer) | 						.appendTo(this.dom) | ||||||
| 				} | 				} | ||||||
| 				return bar | 				return bar | ||||||
| 			},  | 			},  | ||||||
| @ -624,7 +624,7 @@ var StatusBarActions = actions.Actions({ | |||||||
| 				this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | 				this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | ||||||
| 
 | 
 | ||||||
| 				// XXX do this better...
 | 				// XXX do this better...
 | ||||||
| 				this.ribbons.viewer.find('.global-info .index .position').focus().click() | 				this.dom.find('.global-info .index .position').focus().click() | ||||||
| 			} | 			} | ||||||
| 		}], | 		}], | ||||||
| 	editStatusBarRibbon: ['- Interface/Edit ribbon focus position in statusbar', | 	editStatusBarRibbon: ['- Interface/Edit ribbon focus position in statusbar', | ||||||
| @ -632,11 +632,11 @@ var StatusBarActions = actions.Actions({ | |||||||
| 			this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | 			this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | ||||||
| 
 | 
 | ||||||
| 			// XXX do this better...
 | 			// XXX do this better...
 | ||||||
| 			this.ribbons.viewer.find('.global-info .ribbon-number').focus().click() | 			this.dom.find('.global-info .ribbon-number').focus().click() | ||||||
| 		}], | 		}], | ||||||
| 	toggleStatusBarIndexMode: ['Interface/Status bar index mode', | 	toggleStatusBarIndexMode: ['Interface/Status bar index mode', | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer.find('.global-info .index') }, | 			function(){ return this.dom.find('.global-info .index') }, | ||||||
| 			['normal', 'global'], | 			['normal', 'global'], | ||||||
| 			function(state){ | 			function(state){ | ||||||
| 				this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | 				this.toggleStatusBar('?') == 'none' && this.toggleStatusBar() | ||||||
| @ -652,7 +652,7 @@ var StatusBarActions = actions.Actions({ | |||||||
| 	// XXX revise...
 | 	// XXX revise...
 | ||||||
| 	showStatusBarInfo: ['- Interface/', | 	showStatusBarInfo: ['- Interface/', | ||||||
| 		function(text){ | 		function(text){ | ||||||
| 			var bar = this.ribbons.viewer.find('.state-indicator-container.global-info')  | 			var bar = this.dom.find('.state-indicator-container.global-info')  | ||||||
| 
 | 
 | ||||||
| 			if(text){ | 			if(text){ | ||||||
| 				bar.find('.info').text(text) | 				bar.find('.info').text(text) | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| 
 | 
 | ||||||
| var vdom = require('ext-lib/virtual-dom') | var vdom = require('ext-lib/virtual-dom') | ||||||
| 
 | 
 | ||||||
|  | var object = require('lib/object') | ||||||
| var actions = require('lib/actions') | var actions = require('lib/actions') | ||||||
| var features = require('lib/features') | var features = require('lib/features') | ||||||
| 
 | 
 | ||||||
| @ -16,9 +17,453 @@ var core = require('features/core') | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | /*/ XXX | ||||||
|  | var ViewerClassPrototype = { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var ViewerPrototype = { | ||||||
|  | 	sync: function(){ | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var Viewer = | ||||||
|  | module.Viewer = | ||||||
|  | object.makeConstructor('Viewer',  | ||||||
|  | 	ViewerClassPrototype, | ||||||
|  | 	ViewerPrototype) | ||||||
|  | //*/
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | //
 | ||||||
|  | //	- take care of DOM construction and update...
 | ||||||
|  | //	- alignment is done via .centerRibbon(..) / .centerImage(..)
 | ||||||
|  | //	- preview updates (XXX)
 | ||||||
|  | //		- update onload (a-la .ribbons._loadImagePreviewURL(..))
 | ||||||
|  | 
 | ||||||
|  | var VirtualDOMRibbonsClassPrototype = { | ||||||
|  | 	// XXX ???
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var VirtualDOMRibbonsPrototype = { | ||||||
|  | 	// XXX this is a circular ref -- I do not like it...
 | ||||||
|  | 	imagegrid: null, | ||||||
|  | 
 | ||||||
|  | 	dom: null, | ||||||
|  | 	vdom: null, | ||||||
|  | 
 | ||||||
|  | 	// Format:
 | ||||||
|  | 	// 	{
 | ||||||
|  | 	// 		count: <count>,
 | ||||||
|  | 	//
 | ||||||
|  | 	// 		scale: <scale>,
 | ||||||
|  | 	//
 | ||||||
|  | 	// 		top: <offset>,
 | ||||||
|  | 	//
 | ||||||
|  | 	// 		ribbons: {
 | ||||||
|  | 	// 			<gid>: <offset>,
 | ||||||
|  | 	// 			...
 | ||||||
|  | 	// 		},
 | ||||||
|  | 	// 	}
 | ||||||
|  | 	state: null, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// XXX reuse these from ribbons???
 | ||||||
|  | 	preventTransitions: function(){ | ||||||
|  | 	}, | ||||||
|  | 	restoreTransitions: function(){ | ||||||
|  | 	}, | ||||||
|  | 	getElemGID: function(){ | ||||||
|  | 	}, | ||||||
|  | 	getImage: function(){ | ||||||
|  | 	}, | ||||||
|  | 	getVisibleImageSize: function(){ | ||||||
|  | 	}, | ||||||
|  | 	focusImage: function(){ | ||||||
|  | 	}, | ||||||
|  | 	px2vmin: function(){ | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// constructors...
 | ||||||
|  | 	makeView: function(state, initial){ | ||||||
|  | 		state = state || {} | ||||||
|  | 		var that = this | ||||||
|  | 		var ig = this.imagegrid | ||||||
|  | 
 | ||||||
|  | 		var target = state.target || ig.current | ||||||
|  | 
 | ||||||
|  | 		this.state = this.state || {} | ||||||
|  | 		var count = state.count = state.count | ||||||
|  | 			|| ig.screenwidth * (ig.config['ribbon-size-screens'] || 9) | ||||||
|  | 		var s = state.scale = state.scale  | ||||||
|  | 			|| ig.scale | ||||||
|  | 
 | ||||||
|  | 		var data = ig.data | ||||||
|  | 		var images = ig.images | ||||||
|  | 
 | ||||||
|  | 		var ribbons = data.ribbon_order | ||||||
|  | 			.map(function(gid){ | ||||||
|  | 				return that.makeRibbon(gid, target, count, state, initial) }) | ||||||
|  | 
 | ||||||
|  | 		return vdom.h('div.ribbon-set',  | ||||||
|  | 			{ | ||||||
|  | 				//key: 'ribbon-set',
 | ||||||
|  | 				style: { | ||||||
|  | 					transform: 'scale('+ s +', '+ s +')', | ||||||
|  | 				} | ||||||
|  | 			}, [ | ||||||
|  | 				// current image indicator...
 | ||||||
|  | 				vdom.h('div.current-marker'), | ||||||
|  | 
 | ||||||
|  | 				// ribbon locator...
 | ||||||
|  | 				vdom.h('div.ribbon-locator',  | ||||||
|  | 					{ | ||||||
|  | 						//key: 'ribbon-locator',
 | ||||||
|  | 					}, | ||||||
|  | 					ribbons), | ||||||
|  | 			]) | ||||||
|  | 	}, | ||||||
|  | 	// XXX setup handlers (???)
 | ||||||
|  | 	// XXX STUB: make aligning more extensible... (???)
 | ||||||
|  | 	makeRibbon: function(gid, target, count, state, initial){ | ||||||
|  | 		state = state || {} | ||||||
|  | 		var that = this | ||||||
|  | 		var ig = this.imagegrid | ||||||
|  | 		var current = ig.current | ||||||
|  | 		target = target || state.target || current | ||||||
|  | 		var size = this.state.tile_size = state.tile_size | ||||||
|  | 			|| this.state.tile_size  | ||||||
|  | 			|| this.getVisibleImageSize('max') | ||||||
|  | 		var scale = state.scale = state.scale  | ||||||
|  | 			|| ig.scale | ||||||
|  | 		var data = ig.data | ||||||
|  | 		var images = ig.images | ||||||
|  | 		// XXX
 | ||||||
|  | 		var ribbons = ig.ribbons | ||||||
|  | 		var base = data.base == gid ? '.base' : '' | ||||||
|  | 		var imgs = [] | ||||||
|  | 
 | ||||||
|  | 		this.state = this.state || {} | ||||||
|  | 		//this.state.ribbons = this.state.ribbons || {}
 | ||||||
|  | 		 | ||||||
|  | 		// XXX
 | ||||||
|  | 		var size = this.state.tile_size =  | ||||||
|  | 			this.state.tile_size  | ||||||
|  | 				|| this.getVisibleImageSize('max') | ||||||
|  | 
 | ||||||
|  | 		// calculate offset...
 | ||||||
|  | 		// XXX this accounts for only one offset mode...
 | ||||||
|  | 		// 		...make this extensible...
 | ||||||
|  | 		// XXX
 | ||||||
|  | 		var vsize = this.px2vmin(size / scale) | ||||||
|  | 		var ref = data.getImage(target, 'before', gid) | ||||||
|  | 		var offset = ref == target ? vsize / 2  | ||||||
|  | 			: ref != null ? vsize  | ||||||
|  | 			: 0 | ||||||
|  | 		ref = ref || data.getImage(target, 'after', gid) | ||||||
|  | 
 | ||||||
|  | 		// build the images...
 | ||||||
|  | 		//var gids = data.getImages(gid, count, 'total')
 | ||||||
|  | 		var gids = data.getImages(ref, count, 'total') | ||||||
|  | 		gids | ||||||
|  | 			.forEach(function(gid){ | ||||||
|  | 				// image...
 | ||||||
|  | 				imgs.push(that.makeImage(gid, size)) | ||||||
|  | 
 | ||||||
|  | 				// marks...
 | ||||||
|  | 				that.makeImageMarks(gid) | ||||||
|  | 					.forEach(function(mark){ imgs.push(mark) }) | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 		// XXX not sure about this...
 | ||||||
|  | 		var style = initial ? { transform: 'translate3d(120vw, 0, 0)' } : {} | ||||||
|  | 
 | ||||||
|  | 		return vdom.h('div.ribbon'+base, { | ||||||
|  | 			//key: 'ribbon-'+gid,
 | ||||||
|  | 
 | ||||||
|  | 			// XXX events, hammer, ...???
 | ||||||
|  | 
 | ||||||
|  | 			attributes: { | ||||||
|  | 				gid: JSON.stringify(gid) | ||||||
|  | 					.replace(/^"(.*)"$/g, '$1'), | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			style: style, | ||||||
|  | 		}, | ||||||
|  | 		imgs) | ||||||
|  | 	}, | ||||||
|  | 	// XXX setup image handlers...
 | ||||||
|  | 	// XXX update image previews...
 | ||||||
|  | 	// XXX update image proportions for rotated images... (???)
 | ||||||
|  | 	makeImage: function(gid, size){ | ||||||
|  | 		var ig = this.imagegrid | ||||||
|  | 		//size = this.state.tile_size = size 
 | ||||||
|  | 		size = size  | ||||||
|  | 			|| this.state.tile_size | ||||||
|  | 			|| this.getVisibleImageSize('max') | ||||||
|  | 		var data = this.imagegrid.data | ||||||
|  | 		var images = this.imagegrid.images || {} | ||||||
|  | 		var current = data.current == gid ? '.current' : '' | ||||||
|  | 
 | ||||||
|  | 		// resolve group preview cover...
 | ||||||
|  | 		var image = images[gid] || {} | ||||||
|  | 		var seen = [] | ||||||
|  | 		while(image.type == 'group'){ | ||||||
|  | 			// error, recursive group...
 | ||||||
|  | 			if(seen.indexOf(image.id) >= 0){ | ||||||
|  | 				image = images.IMAGE_DATA | ||||||
|  | 				console.error('Recursive group:', gid) | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			seen.push(image.id) | ||||||
|  | 
 | ||||||
|  | 			image = that.images[image.cover] | ||||||
|  | 		} | ||||||
|  | 		var url = ig.images.getBestPreview(gid, size, image, true).url | ||||||
|  | 
 | ||||||
|  | 		return vdom.h('div.image'+current, { | ||||||
|  | 			// XXX BUG:
 | ||||||
|  | 			// 		- setting this makes the images some times not change previews...
 | ||||||
|  | 			// 		- removing this breaks .current class setting...
 | ||||||
|  | 			key: 'image-'+gid, | ||||||
|  | 
 | ||||||
|  | 			attributes: { | ||||||
|  | 				gid: JSON.stringify(gid) | ||||||
|  | 					.replace(/^"(.*)"$/g, '$1'), | ||||||
|  | 				orientation: image.orientation, | ||||||
|  | 				flipped: image.flipped, | ||||||
|  | 
 | ||||||
|  | 				// XXX preview size -- get this onload from image...
 | ||||||
|  | 				//'preview-width': ..,
 | ||||||
|  | 				//'preview-height': ..,
 | ||||||
|  | 			}, | ||||||
|  | 			style: { | ||||||
|  | 				// XXX need to update this onload if changing preview 
 | ||||||
|  | 				// 		of same image...
 | ||||||
|  | 				backgroundImage: 'url("'+ url +'")', | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	// XXX STUB: make marks handling extensible... (???)
 | ||||||
|  | 	makeImageMarks: function(gid){ | ||||||
|  | 		var that = this | ||||||
|  | 		var marks = [] | ||||||
|  | 		var tags = this.imagegrid.data.getTags(gid) | ||||||
|  | 
 | ||||||
|  | 		// XXX STUB: make this extensible...
 | ||||||
|  | 		tags.indexOf('bookmark') >= 0  | ||||||
|  | 			&& marks.push('bookmark') | ||||||
|  | 		tags.indexOf('selected') >= 0  | ||||||
|  | 			&& marks.push('selected') | ||||||
|  | 
 | ||||||
|  | 		return marks | ||||||
|  | 			.map(function(type){ | ||||||
|  | 				return vdom.h('div.mark.'+(type || ''), { | ||||||
|  | 					key: 'mark-'+type+'-'+gid, | ||||||
|  | 					attributes: { | ||||||
|  | 						gid: JSON.stringify(gid) | ||||||
|  | 							.replace(/^"(.*)"$/g, '$1'), | ||||||
|  | 					}, | ||||||
|  | 				}) | ||||||
|  | 			}) | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	// XXX add ability to hook in things like current image marker...
 | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	// XXX these need .getImage(..) / .getRibbon(..) / .getRibbonLocator(..)
 | ||||||
|  | 	centerRibbon: function(target){ | ||||||
|  | 		var ribbon = this.getRibbon(target) | ||||||
|  | 		var locator = this.getRibbonLocator()  | ||||||
|  | 
 | ||||||
|  | 		if(locator.length != 0 && ribbon.length != 0){ | ||||||
|  | 			var t = ribbon[0].offsetTop | ||||||
|  | 			var h = ribbon[0].offsetHeight | ||||||
|  | 
 | ||||||
|  | 			locator.transform({ x: 0, y: this.px2vh(-(t + h/2)) + 'vh', z: 0 })  | ||||||
|  | 		} | ||||||
|  | 		return this | ||||||
|  | 	}, | ||||||
|  | 	centerImage: function(target, mode){ | ||||||
|  | 		target = this.getImage(target) | ||||||
|  | 		var ribbon = this.getRibbon(target) | ||||||
|  | 
 | ||||||
|  | 		if(ribbon.length != 0){ | ||||||
|  | 			var l = target[0].offsetLeft | ||||||
|  | 			var w = target[0].offsetWidth | ||||||
|  | 
 | ||||||
|  | 			var image_offset = mode == 'before' ? 0 | ||||||
|  | 				: mode == 'after' ? w | ||||||
|  | 				: w/2 | ||||||
|  | 
 | ||||||
|  | 			ribbon.transform({x: -this.px2vmin(l + image_offset) + 'vmin', y: 0, z: 0})  | ||||||
|  | 		} | ||||||
|  | 		return this | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	scale: function(scale){ | ||||||
|  | 		if(scale){ | ||||||
|  | 			this.state.scale = scale | ||||||
|  | 			this.sync() | ||||||
|  | 
 | ||||||
|  | 		} else { | ||||||
|  | 			return this.imagegrid.scale | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	// XXX not sure how to proceed with these...
 | ||||||
|  | 	setImageHandler: function(evt, handler){ | ||||||
|  | 	}, | ||||||
|  | 	setRibbonHandler: function(evt, handler){ | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	clear: function(){ | ||||||
|  | 		this.dom | ||||||
|  | 			&& this.dom.remove() | ||||||
|  | 
 | ||||||
|  | 		delete this.state | ||||||
|  | 		delete this.dom | ||||||
|  | 		delete this.vdom | ||||||
|  | 
 | ||||||
|  | 		return this | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	// NOTE: virtual-dom architecture is designed around a fast-render-on-demand
 | ||||||
|  | 	// 		concept, so we build the state on demand...
 | ||||||
|  | 	// XXX get scale from config on initial load...
 | ||||||
|  | 	sync: function(target, size){ | ||||||
|  | 		var dom = this.dom  | ||||||
|  | 
 | ||||||
|  | 		var state = this.state ? Object.create(this.state) : {} | ||||||
|  | 		target && (state.target = target) | ||||||
|  | 		size && (state.count = size) | ||||||
|  | 
 | ||||||
|  | 		// build initial state...
 | ||||||
|  | 		if(this.vdom == null){ | ||||||
|  | 			var n = this.vdom = this.makeView(state, true) | ||||||
|  | 			var v = vdom.create(n) | ||||||
|  | 			this.imagegrid.dom.append(v) | ||||||
|  | 			this.dom = v | ||||||
|  | 
 | ||||||
|  | 		// patch state...
 | ||||||
|  | 		} else { | ||||||
|  | 			var n = this.makeView(state) | ||||||
|  | 			var diff = vdom.diff(this.vdom, n) | ||||||
|  | 			vdom.patch(dom, diff) | ||||||
|  | 			this.vdom = n | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return this | ||||||
|  | 	}, | ||||||
|  | 	// XXX should this do a full or partial .clear()???
 | ||||||
|  | 	// XXX BUG: current image indicator resets but does not get shown...
 | ||||||
|  | 	reset: function(){ | ||||||
|  | 		delete this.dom | ||||||
|  | 		delete this.vdom | ||||||
|  | 		if(this.state){  | ||||||
|  | 			delete this.state.tile_size  | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return this | ||||||
|  | 			.sync() | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	__init__: function(imagegrid){ | ||||||
|  | 		this.imagegrid = imagegrid | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var VirtualDOMRibbons = | ||||||
|  | module.VirtualDOMRibbons = | ||||||
|  | object.makeConstructor('VirtualDOMRibbons',  | ||||||
|  | 	VirtualDOMRibbonsClassPrototype, | ||||||
|  | 	VirtualDOMRibbonsPrototype) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| 
 | 
 | ||||||
| var VirtualDomActions = actions.Actions({ | var VirtualDomActions = actions.Actions({ | ||||||
|  | 
 | ||||||
|  | 	get dom(){ | ||||||
|  | 		return this.__dom }, | ||||||
|  | 	set dom(value){ | ||||||
|  | 		this.__dom = value}, | ||||||
|  | 	get virtualdom(){ | ||||||
|  | 		return (this.__virtual_dom = this.__virtual_dom || VirtualDOMRibbons(this)) }, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	load: [ | ||||||
|  | 		function(data){ | ||||||
|  | 			return function(){ | ||||||
|  | 				// recycle the viewer if one is not given specifically...
 | ||||||
|  | 				var viewer = data.viewer | ||||||
|  | 				viewer = viewer == null ? this.dom : viewer | ||||||
|  | 
 | ||||||
|  | 				if(this.dom == null){ | ||||||
|  | 					this.dom = viewer | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 					this.virtualdom.clear() | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				this.reload() | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | 	reload: ['Interface/Reload viewer', | ||||||
|  | 		function(){ | ||||||
|  | 			this.virtualdom.reset() | ||||||
|  | 			this.focusImage() | ||||||
|  | 		}], | ||||||
|  | 	// XXX this ignores it's args...
 | ||||||
|  | 	refresh: ['Interface/Refresh images without reloading', | ||||||
|  | 		function(gids, scale){ | ||||||
|  | 			this.virtualdom.sync() | ||||||
|  | 			this.focusImage() | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// XXX
 | ||||||
|  | 	updateRibbon: ['- Interface/Update partial ribbon size',  | ||||||
|  | 		function(target, w, size, threshold){ | ||||||
|  | 			target = target instanceof jQuery  | ||||||
|  | 				? this.virtualdom.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')) | ||||||
|  | 			w = w || this.screenwidth | ||||||
|  | 			// get config data and normalize...
 | ||||||
|  | 			size = (size  | ||||||
|  | 				|| this.config['ribbon-size-screens']  | ||||||
|  | 				|| 9) * w | ||||||
|  | 
 | ||||||
|  | 			// XXX DEBUG
 | ||||||
|  | 			//size = 5
 | ||||||
|  | 
 | ||||||
|  | 			// XXX for some reason this does not set the .current class 
 | ||||||
|  | 			// 		on the right image...
 | ||||||
|  | 			this.virtualdom.sync(target, size) | ||||||
|  | 
 | ||||||
|  | 			// XXX HACK: this fixes a bug in virtual-dom where .current
 | ||||||
|  | 			// 		is not synced correctly...
 | ||||||
|  | 			// 		...one theory I have is that we change the class 
 | ||||||
|  | 			// 		manually, dom gets diffed and no change is detected
 | ||||||
|  | 			// 		then the object gets recycled and the .current class
 | ||||||
|  | 			// 		ends up on a different element...
 | ||||||
|  | 			this.virtualdom.focusImage(target) | ||||||
|  | 
 | ||||||
|  | 			this.centerViewer(target) | ||||||
|  | 		}], | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| var VirtualDom =  | var VirtualDom =  | ||||||
| @ -34,7 +479,55 @@ module.VirtualDom = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 	actions: VirtualDomActions,  | 	actions: VirtualDomActions,  | ||||||
| 
 | 
 | ||||||
| 	handlers: [], | 	handlers: [ | ||||||
|  | 		['clear', | ||||||
|  | 			function(){ this.virtualdom.clear() }], | ||||||
|  | 		['fitImage toggleSingleImage', | ||||||
|  | 			function(){ delete this.virtualdom.state.tile_size }], | ||||||
|  | 
 | ||||||
|  | 		// XXX account for fast navigation...
 | ||||||
|  | 		['focusImage.pre',  | ||||||
|  | 			function(target){  | ||||||
|  | 				var img = this.virtualdom.getImage(target) | ||||||
|  | 
 | ||||||
|  | 				// in-place update...
 | ||||||
|  | 				if(img.length > 0){ | ||||||
|  | 					// XXX need to account for running out of images and
 | ||||||
|  | 					// 		not only on the current ribbon...
 | ||||||
|  | 					if(!this.__partial_ribbon_update){ | ||||||
|  | 						this.__partial_ribbon_update = setTimeout((function(){ | ||||||
|  | 							delete this.__partial_ribbon_update | ||||||
|  | 							this.virtualdom.preventTransitions() | ||||||
|  | 
 | ||||||
|  | 							this | ||||||
|  | 								.updateRibbon(this.current) | ||||||
|  | 								// NOTE: we are doing this manually because we
 | ||||||
|  | 								// 		are running after the handler is done 
 | ||||||
|  | 								// 		thus missing the base call...
 | ||||||
|  | 								.alignRibbons(null, null, true) | ||||||
|  | 
 | ||||||
|  | 							this.virtualdom.restoreTransitions() | ||||||
|  | 						}).bind(this), 150) | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 				// long-jump...
 | ||||||
|  | 				} else { | ||||||
|  | 					if(this.__partial_ribbon_update){ | ||||||
|  | 						clearTimeout(this.__partial_ribbon_update) | ||||||
|  | 						delete this.__partial_ribbon_update | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					this.updateRibbon(target)  | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 
 | ||||||
|  | 		// marks...
 | ||||||
|  | 		[[ | ||||||
|  | 			'toggleMark', | ||||||
|  | 			'toggleBookmark', | ||||||
|  | 		//], function(){ this.updateRibbon() }],
 | ||||||
|  | 		], function(){ this.virtualdom.sync() }], | ||||||
|  | 	], | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ function(context, cls, data){ | |||||||
| 	cls = cls instanceof Array ? cls : cls.split(/\s+/g) | 	cls = cls instanceof Array ? cls : cls.split(/\s+/g) | ||||||
| 
 | 
 | ||||||
| 	// remove old versions...
 | 	// remove old versions...
 | ||||||
| 	context.ribbons.viewer.find('.'+ cls.join('.')).remove() | 	context.dom.find('.'+ cls.join('.')).remove() | ||||||
| 
 | 
 | ||||||
| 	// make container...
 | 	// make container...
 | ||||||
| 	var controls = $('<div>') | 	var controls = $('<div>') | ||||||
| @ -103,7 +103,7 @@ function(context, cls, data){ | |||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	controls | 	controls | ||||||
| 		.appendTo(context.ribbons.viewer) | 		.appendTo(context.dom) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // XXX write docs:
 | // XXX write docs:
 | ||||||
| @ -121,7 +121,7 @@ function(cls, cfg, parent){ | |||||||
| 
 | 
 | ||||||
| 	return toggler.Toggler(null, | 	return toggler.Toggler(null, | ||||||
| 		function(){  | 		function(){  | ||||||
| 			parent = parent == null ? this.ribbons.viewer | 			parent = parent == null ? this.dom | ||||||
| 				: parent instanceof Function ? parent.call(this)  | 				: parent instanceof Function ? parent.call(this)  | ||||||
| 				: parent | 				: parent | ||||||
| 			return parent.find('.'+ cls.join('.')).length > 0 ? 'on' : 'off'  | 			return parent.find('.'+ cls.join('.')).length > 0 ? 'on' : 'off'  | ||||||
| @ -135,7 +135,7 @@ function(cls, cfg, parent){ | |||||||
| 					&& makeButtonControls(this, cls, config) | 					&& makeButtonControls(this, cls, config) | ||||||
| 
 | 
 | ||||||
| 			} else { | 			} else { | ||||||
| 				this.ribbons.viewer.find('.'+ cls.join('.')).remove() | 				this.dom.find('.'+ cls.join('.')).remove() | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| } | } | ||||||
| @ -341,7 +341,7 @@ module.makeUIContainer = function(make){ | |||||||
| 						// 						is in a state where the window
 | 						// 						is in a state where the window
 | ||||||
| 						// 						is in focus but keys are not 
 | 						// 						is in focus but keys are not 
 | ||||||
| 						// 						tracked...
 | 						// 						tracked...
 | ||||||
| 						: that.ribbons.viewer.focus() | 						: that.dom.focus() | ||||||
| 				}) | 				}) | ||||||
| 				// Compensate for click focusing the parent dialog when
 | 				// Compensate for click focusing the parent dialog when
 | ||||||
| 				// a child is created...
 | 				// a child is created...
 | ||||||
| @ -427,7 +427,7 @@ var makeDrawer = function(direction){ | |||||||
| 		var that = this | 		var that = this | ||||||
| 		options = options || {} | 		options = options || {} | ||||||
| 		var parent = options.parentElement  | 		var parent = options.parentElement  | ||||||
| 		parent = parent ? $(parent) : this.ribbons.viewer  | 		parent = parent ? $(parent) : this.dom  | ||||||
| 
 | 
 | ||||||
| 		options.direction = direction || 'bottom' | 		options.direction = direction || 'bottom' | ||||||
| 
 | 
 | ||||||
| @ -513,7 +513,7 @@ var DialogsActions = actions.Actions({ | |||||||
| 	// 		element
 | 	// 		element
 | ||||||
| 	// 		null
 | 	// 		null
 | ||||||
| 	get modal(){ | 	get modal(){ | ||||||
| 		var modal = this.ribbons.viewer | 		var modal = this.dom | ||||||
| 			.find('.modal-widget') | 			.find('.modal-widget') | ||||||
| 				.last() | 				.last() | ||||||
| 		return modal.data('widget-controller')  | 		return modal.data('widget-controller')  | ||||||
| @ -540,7 +540,7 @@ var DialogsActions = actions.Actions({ | |||||||
| 	Overlay: ['- Interface/', | 	Overlay: ['- Interface/', | ||||||
| 		makeUIContainer(function(dialog, options){ | 		makeUIContainer(function(dialog, options){ | ||||||
| 			var that = this | 			var that = this | ||||||
| 			return overlay.Overlay(this.ribbons.viewer, dialog, options) | 			return overlay.Overlay(this.dom, dialog, options) | ||||||
| 				// focus top modal on exit...
 | 				// focus top modal on exit...
 | ||||||
| 				.on('close', function(){ | 				.on('close', function(){ | ||||||
| 					var o = that.modal | 					var o = that.modal | ||||||
| @ -575,7 +575,7 @@ var DialogsActions = actions.Actions({ | |||||||
| 				client: dialog, | 				client: dialog, | ||||||
| 				dom: $('<div>') | 				dom: $('<div>') | ||||||
| 					.append(dialog.dom || dialog) | 					.append(dialog.dom || dialog) | ||||||
| 					.appendTo(this.ribbons.viewer) | 					.appendTo(this.dom) | ||||||
| 					.draggable(), | 					.draggable(), | ||||||
| 				close: function(func){ | 				close: function(func){ | ||||||
| 					if(func){ | 					if(func){ | ||||||
| @ -762,7 +762,7 @@ var DialogsActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 	toggleOverlayBlur: ['Interface/Dialog overlay blur', | 	toggleOverlayBlur: ['Interface/Dialog overlay blur', | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			'overlay-blur-enabled', | 			'overlay-blur-enabled', | ||||||
| 			function(state){ this.config['ui-overlay-blur'] = state }) ], | 			function(state){ this.config['ui-overlay-blur'] = state }) ], | ||||||
| }) | }) | ||||||
| @ -1406,7 +1406,7 @@ module.ContextActionMenu = core.ImageGridFeatures.Feature({ | |||||||
| 		['load', | 		['load', | ||||||
| 			function(){ | 			function(){ | ||||||
| 				var that = this | 				var that = this | ||||||
| 				var viewer = this.ribbons.viewer | 				var viewer = this.dom | ||||||
| 
 | 
 | ||||||
| 				!viewer.data('context-menu')  | 				!viewer.data('context-menu')  | ||||||
| 					&& viewer | 					&& viewer | ||||||
| @ -1528,7 +1528,7 @@ module.Buttons = core.ImageGridFeatures.Feature({ | |||||||
| 				$('.main-buttons.buttons .crop.button sub') | 				$('.main-buttons.buttons .crop.button sub') | ||||||
| 					.text(this.crop_stack ? this.crop_stack.length : '') }], | 					.text(this.crop_stack ? this.crop_stack.length : '') }], | ||||||
| 		// update zoom button status...
 | 		// update zoom button status...
 | ||||||
| 		['setScale',  | 		['viewScale',  | ||||||
| 			function(){ | 			function(){ | ||||||
| 				$('.secondary-buttons.buttons .zoom.button sub') | 				$('.secondary-buttons.buttons .zoom.button sub') | ||||||
| 					.text(Math.round(this.screenwidth)) }], | 					.text(Math.round(this.screenwidth)) }], | ||||||
| @ -1897,7 +1897,7 @@ var WidgetTestActions = actions.Actions({ | |||||||
| 				make('c/') | 				make('c/') | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			var o = overlay.Overlay(this.ribbons.viewer,  | 			var o = overlay.Overlay(this.dom,  | ||||||
| 				browse.makePathList(null, { | 				browse.makePathList(null, { | ||||||
| 					'a/*': list, | 					'a/*': list, | ||||||
| 					'b/*': list, | 					'b/*': list, | ||||||
| @ -1914,8 +1914,8 @@ var WidgetTestActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// XXX migrate to the dialog framework...
 | 	// XXX migrate to the dialog framework...
 | ||||||
| 	// XXX use this.ribbons.viewer as base...
 | 	// XXX use this.dom as base...
 | ||||||
| 	// XXX BUG: when using this.ribbons.viewer as base some actions leak
 | 	// XXX BUG: when using this.dom as base some actions leak
 | ||||||
| 	// 		between the two viewers...
 | 	// 		between the two viewers...
 | ||||||
| 	showTaggedInDrawer: ['- Test/Show tagged in drawer', | 	showTaggedInDrawer: ['- Test/Show tagged in drawer', | ||||||
| 		function(tag){ | 		function(tag){ | ||||||
| @ -1928,7 +1928,7 @@ var WidgetTestActions = actions.Actions({ | |||||||
| 					height: H, | 					height: H, | ||||||
| 					background: 'black', | 					background: 'black', | ||||||
| 				}) | 				}) | ||||||
| 			// XXX use this.ribbons.viewer as base...
 | 			// XXX use this.dom as base...
 | ||||||
| 			// XXX when using viewer zoom and other stuff get leaked...
 | 			// XXX when using viewer zoom and other stuff get leaked...
 | ||||||
| 			var widget = drawer.Drawer($('body'),  | 			var widget = drawer.Drawer($('body'),  | ||||||
| 				$('<div>') | 				$('<div>') | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ | |||||||
| * Experimental Features: | * Experimental Features: | ||||||
| *	- ui-ribbons-placement | *	- ui-ribbons-placement | ||||||
| *		manage different low level ribbon placement mechanics | *		manage different low level ribbon placement mechanics | ||||||
| *		XXX experimental... | *		XXX EXPERIMENTAL... | ||||||
| *	- auto-single-image | *	- auto-single-image | ||||||
| *	- auto-ribbon | *	- auto-ribbon | ||||||
| * | * | ||||||
| @ -234,21 +234,11 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		'ribbon-align-delay': 50, | 		'ribbon-align-delay': 50, | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	// Ribbons...
 | 	// Viewer dom... 
 | ||||||
| 	//
 | 	dom: null, | ||||||
| 	// NOTE: this expects that ribbons will maintain .parent.images...
 |  | ||||||
| 	// NOTE: when getting rid of ribbons need to also remove the .parent
 |  | ||||||
| 	// 		reference...
 |  | ||||||
| 	get ribbons(){ |  | ||||||
| 		return this.__ribbons }, |  | ||||||
| 	set ribbons(ribbons){ |  | ||||||
| 		this.__ribbons = ribbons |  | ||||||
| 		ribbons.parent = this |  | ||||||
| 	}, |  | ||||||
| 
 | 
 | ||||||
| 	// Current image data...
 | 	// Current image data...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// XXX experimental...
 |  | ||||||
| 	get image(){ | 	get image(){ | ||||||
| 		return this.images && this.images[this.current] }, | 		return this.images && this.images[this.current] }, | ||||||
| 	set image(val){ | 	set image(val){ | ||||||
| @ -259,28 +249,21 @@ module.ViewerActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 	// Scaling...
 | 	// Scaling...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// Normal scale...
 | 	// NOTE: .screenwidth / .screenheight are measured in square image blocks...
 | ||||||
| 	get scale(){ | 	get scale(){ | ||||||
| 		return this.ribbons != null ? this.ribbons.scale() : null }, | 		return this.viewScale() }, | ||||||
| 	set scale(s){ | 	set scale(s){ | ||||||
| 		this.setScale(s) }, | 		this.viewScale(s) }, | ||||||
| 	 |  | ||||||
| 	// Screen width in image blocks...
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: this will change depending on image block sizing...
 |  | ||||||
| 	// NOTE: this not usable for image blocks of different sizes...
 |  | ||||||
| 	get screenwidth(){ | 	get screenwidth(){ | ||||||
| 		return this.ribbons != null ? this.ribbons.getScreenWidthImages() : null }, | 		return this.fitImage('?') }, | ||||||
| 	set screenwidth(n){ | 	set screenwidth(n){ | ||||||
| 		this.fitImage(n, false) }, | 		this.fitImage(n, false) }, | ||||||
| 
 |  | ||||||
| 	// Screen height in image blocks...
 |  | ||||||
| 	get screenheight(){ | 	get screenheight(){ | ||||||
| 		return this.ribbons != null ? this.ribbons.getScreenHeightRibbons() : null }, | 		return this.fitRibbon('?') }, | ||||||
| 	set screenheight(n){ | 	set screenheight(n){ | ||||||
| 		this.fitRibbon(n, false) }, | 		this.fitRibbon(n, false) }, | ||||||
| 
 | 
 | ||||||
| 	// Screen size in image radii on the narrow side of the screen...
 | 	// Screen size in image "radii" on the narrow side of the screen...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// E.g.
 | 	// E.g.
 | ||||||
| 	//
 | 	//
 | ||||||
| @ -289,10 +272,10 @@ module.ViewerActions = actions.Actions({ | |||||||
| 	// 						min(image.width, image.height)
 | 	// 						min(image.width, image.height)
 | ||||||
| 	//
 | 	//
 | ||||||
| 	get screenfit(){ | 	get screenfit(){ | ||||||
| 		if(!this.ribbons || !this.ribbons.viewer){ | 		if(!this.ribbons || !this.dom){ | ||||||
| 			return null | 			return null | ||||||
| 		} | 		} | ||||||
| 		var viewer = this.ribbons.viewer | 		var viewer = this.dom | ||||||
| 		var W = viewer.width() | 		var W = viewer.width() | ||||||
| 		var H = viewer.height() | 		var H = viewer.height() | ||||||
| 
 | 
 | ||||||
| @ -301,7 +284,7 @@ module.ViewerActions = actions.Actions({ | |||||||
| 			: this.screenheight | 			: this.screenheight | ||||||
| 	}, | 	}, | ||||||
| 	set screenfit(n){ | 	set screenfit(n){ | ||||||
| 		var viewer = this.ribbons.viewer | 		var viewer = this.dom | ||||||
| 		var W = viewer.width() | 		var W = viewer.width() | ||||||
| 		var H = viewer.height() | 		var H = viewer.height() | ||||||
| 
 | 
 | ||||||
| @ -313,170 +296,12 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	load: [ |  | ||||||
| 		function(data){ |  | ||||||
| 			return function(){ |  | ||||||
| 				// recycle the viewer if one is not given specifically...
 |  | ||||||
| 				var viewer = data.viewer |  | ||||||
| 				viewer = viewer == null && this.ribbons != null  |  | ||||||
| 					? this.ribbons.viewer  |  | ||||||
| 					: viewer |  | ||||||
| 
 |  | ||||||
| 				if(this.ribbons == null){ |  | ||||||
| 					this.ribbons = ribbons.Ribbons(viewer, this.images) |  | ||||||
| 					// XXX is this correct???
 |  | ||||||
| 					this.ribbons.__image_updaters = [this.updateImage.bind(this)] |  | ||||||
| 
 |  | ||||||
| 				} else { |  | ||||||
| 					this.ribbons.clear() |  | ||||||
| 					this.ribbons.images = this.images |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				this.reload() |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 	// NOTE: this will pass the .ribbons.updateData(..) a custom ribbon 
 |  | ||||||
| 	// 		updater if one is defined here as .updateRibbon(target) action
 |  | ||||||
| 	//
 |  | ||||||
| 	// XXX HACK: two sins:
 |  | ||||||
| 	// 		- actions.updateRibbon(..) and ribbons.updateRibbon(..)
 |  | ||||||
| 	// 		  are NOT signature compatible...
 |  | ||||||
| 	// 		- we depend on the internals of a custom add-on feature
 |  | ||||||
| 	reload: ['Interface/Reload viewer', |  | ||||||
| 		function(force){ |  | ||||||
| 			// full reload...
 |  | ||||||
| 			if(force == 'full'){ |  | ||||||
| 				//this.stop()
 |  | ||||||
| 				/* |  | ||||||
| 				killAllWorkers() |  | ||||||
| 					.done(function(){ |  | ||||||
| 						reload()  |  | ||||||
| 					}) |  | ||||||
| 				*/ |  | ||||||
| 				location.reload() |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			this.ribbons.preventTransitions() |  | ||||||
| 
 |  | ||||||
| 			// NOTE: this essentially sets the update threshold to 0...
 |  | ||||||
| 			// XXX this should be a custom arg...
 |  | ||||||
| 			force = force ? 0 : null |  | ||||||
| 
 |  | ||||||
| 			return function(){ |  | ||||||
| 				// see if we've got a custom ribbon updater...
 |  | ||||||
| 				var that = this |  | ||||||
| 				var settings = this.updateRibbon != null  |  | ||||||
| 					// XXX this should be: { updateRibbon: this.updateRibbon.bind(this) }
 |  | ||||||
| 					? { updateRibbon: function(_, ribbon){  |  | ||||||
| 							return that.updateRibbon(ribbon, null, null, force)  |  | ||||||
| 						} } |  | ||||||
| 					: null |  | ||||||
| 
 |  | ||||||
| 				this.ribbons.updateData(this.data, settings) |  | ||||||
| 
 |  | ||||||
| 				this |  | ||||||
| 					// XXX should this be here???
 |  | ||||||
| 					.refresh() |  | ||||||
| 					.focusImage() |  | ||||||
| 
 |  | ||||||
| 				// XXX HACK to make browser redraw images...
 |  | ||||||
| 				this.scale = this.scale |  | ||||||
| 
 |  | ||||||
| 				this.ribbons.restoreTransitions() |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 	// NOTE: this will trigger .updateImage hooks...
 |  | ||||||
| 	refresh: ['Interface/Refresh images without reloading', |  | ||||||
| 		function(gids, scale){ |  | ||||||
| 			gids = gids || '*' |  | ||||||
| 			var size = scale != null ?  |  | ||||||
| 				this.ribbons.getVisibleImageSize('min', scale) |  | ||||||
| 				: null |  | ||||||
| 
 |  | ||||||
| 			this.ribbons.updateImage(gids, null, size) |  | ||||||
| 		}], |  | ||||||
| 	clear: [ |  | ||||||
| 		function(){ this.ribbons && this.ribbons.clear() }], |  | ||||||
| 	clone: [function(full){ |  | ||||||
| 		return function(res){ |  | ||||||
| 			if(this.ribbons){ |  | ||||||
| 				// NOTE: this is a bit wasteful as .ribbons will clone 
 |  | ||||||
| 				// 		their ref to .images that we will throw away...
 |  | ||||||
| 				res.ribbons = this.ribbons.clone() |  | ||||||
| 				res.ribbons.images = res.images |  | ||||||
| 			}  |  | ||||||
| 		} |  | ||||||
| 	}], |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	replaceGid: [ |  | ||||||
| 		function(from, to){ |  | ||||||
| 			return function(res){ |  | ||||||
| 				res && this.ribbons.replaceGid(from, to) |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	// This is called by .ribbons, the goal is to use it to hook into 
 |  | ||||||
| 	// image updating from features and extensions...
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: not intended for calling manually, use .refresh(..) instead...
 |  | ||||||
| 	//
 |  | ||||||
| 	// XXX experimental...
 |  | ||||||
| 	// 		...need this to get triggered by .ribbons
 |  | ||||||
| 	// 		at this point manually triggering this will not do anything...
 |  | ||||||
| 	// XXX problem: need to either redesign this or distinguish from 
 |  | ||||||
| 	// 		other actions as I keep calling it expecting results...
 |  | ||||||
| 	// XXX hide from user action list... (???)
 |  | ||||||
| 	updateImage: ['- Interface/Update image (do not use directly)', |  | ||||||
| 		'This is called by .refresh(..) and intended for use as an ' |  | ||||||
| 			+'trigger for handlers, and not as a user-callable acation.', |  | ||||||
| 		core.notUserCallable(function(gid, image){ |  | ||||||
| 			// This is the image update protocol root function
 |  | ||||||
| 			//
 |  | ||||||
| 			// Not for direct use.
 |  | ||||||
| 		})], |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// 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',  | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			function(){ return this.config.themes }, | 			function(){ return this.config.themes }, | ||||||
| 			function(state){ this.config.theme = state }) ], | 			function(state){ this.config.theme = state }) ], | ||||||
| 	lighterTheme: ['Interface/Theme/Lighter theme', | 	lighterTheme: ['Interface/Theme/Lighter theme', | ||||||
| @ -493,17 +318,65 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		}], | 		}], | ||||||
| 	toggleRibbonTheme: ['Interface/Theme/Ribbon theme',  | 	toggleRibbonTheme: ['Interface/Theme/Ribbon theme',  | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			function(){ return this.config['ribbon-themes'] }, | 			function(){ return this.config['ribbon-themes'] }, | ||||||
| 			function(state){ this.config['ribbon-theme'] = state }) ], | 			function(state){ this.config['ribbon-theme'] = state }) ], | ||||||
| 	toggleRibbonImageSepators: ['Interface/Theme/Ribbon image separators',  | 	toggleRibbonImageSepators: ['Interface/Theme/Ribbon image separators',  | ||||||
| 		toggler.CSSClassToggler( | 		toggler.CSSClassToggler( | ||||||
| 			function(){ return this.ribbons.viewer },  | 			function(){ return this.dom },  | ||||||
| 			'ribbon-image-separators', | 			'ribbon-image-separators', | ||||||
| 			function(state){ this.config['ribbon-image-separators'] = state }) ], | 			function(state){ this.config['ribbon-image-separators'] = state }) ], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// ribbon aligning...
 | 	// Navigation...
 | ||||||
|  | 	//
 | ||||||
|  | 	// NOTE: these prioritize whole images, i.e. each image will at least
 | ||||||
|  | 	// 		once be fully shown.
 | ||||||
|  | 	prevScreen: ['Navigate/Screen width back', | ||||||
|  | 		function(){ | ||||||
|  | 			// NOTE: the 0.2 is added to compensate for alignment/scaling
 | ||||||
|  | 			// 		errors -- 2.99 images wide counts as 3 while 2.5 as 2.
 | ||||||
|  | 			var w = Math.floor(this.screenwidth + 0.2) | ||||||
|  | 			w += (w % 2) - 1 | ||||||
|  | 			this.prevImage(w) | ||||||
|  | 		}], | ||||||
|  | 	nextScreen: ['Navigate/Screen width forward', | ||||||
|  | 		function(){ | ||||||
|  | 			var w = Math.floor(this.screenwidth + 0.2) | ||||||
|  | 			w += (w % 2) - 1 | ||||||
|  | 			this.nextImage(w) | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// Renderer API...
 | ||||||
|  | 	/*/ XXX do we need these here??? | ||||||
|  | 	centerImage: ['- Interface/Center an image in ribbon horizontally', | ||||||
|  | 		function(target, align, offset, scale){ | ||||||
|  | 		}], | ||||||
|  | 	centerRibbon: ['- Interface/Center a ribbon vertically', | ||||||
|  | 		function(target){ | ||||||
|  | 		}], | ||||||
|  | 	ribbonRotation: ['- Interface|Ribbon/',  | ||||||
|  | 		function(a){  | ||||||
|  | 		}], | ||||||
|  | 	viewScale: ['- Zoom/', | ||||||
|  | 		function(scale){ | ||||||
|  | 		}], | ||||||
|  | 	fitImage: ['Zoom/Fit image', | ||||||
|  | 		function(count, overflow){ | ||||||
|  | 		}], | ||||||
|  | 	fitRibbon: ['Zoom/Fit ribbon vertically', | ||||||
|  | 		function(count, whole){ | ||||||
|  | 		}], | ||||||
|  | 	//*/
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// ribbon aligning and centering...
 | ||||||
|  | 	centerViewer: ['- Interface/Center the viewer', | ||||||
|  | 		function(target){ | ||||||
|  | 			this | ||||||
|  | 				.centerImage(target) | ||||||
|  | 				.centerRibbon(target) }], | ||||||
| 	alignRibbons: ['Interface/Align ribbons', | 	alignRibbons: ['Interface/Align ribbons', | ||||||
| 		function(target, scale, now){ | 		function(target, scale, now){ | ||||||
| 			if(target == 'now'){ | 			if(target == 'now'){ | ||||||
| @ -535,6 +408,7 @@ module.ViewerActions = actions.Actions({ | |||||||
| 	// 		order...
 | 	// 		order...
 | ||||||
| 	// XXX skip off-screen ribbons (???)
 | 	// XXX skip off-screen ribbons (???)
 | ||||||
| 	// XXX should the timeout be configurable???
 | 	// XXX should the timeout be configurable???
 | ||||||
|  | 	// XXX remove dependency on .ribbons
 | ||||||
| 	alignByOrder: ['Interface/Align ribbons by image order', | 	alignByOrder: ['Interface/Align ribbons by image order', | ||||||
| 		function(target, scale, now){ | 		function(target, scale, now){ | ||||||
| 			if(target == 'now'){ | 			if(target == 'now'){ | ||||||
| @ -649,34 +523,8 @@ module.ViewerActions = actions.Actions({ | |||||||
| 			//}, 0)
 | 			//}, 0)
 | ||||||
| 		}], | 		}], | ||||||
| 
 | 
 | ||||||
| 	// NOTE: this will align only a single image...
 |  | ||||||
| 	// XXX do we need these low level primitives here???
 |  | ||||||
| 	centerImage: ['- Interface/Center an image in ribbon horizontally', |  | ||||||
| 		function(target, align, offset, scale){ |  | ||||||
| 			target = target instanceof jQuery  |  | ||||||
| 				? this.ribbons.getElemGID(target) |  | ||||||
| 				: target |  | ||||||
| 
 |  | ||||||
| 			// align current ribbon...
 |  | ||||||
| 			this.ribbons.centerImage(target, align, offset, scale) |  | ||||||
| 		}], |  | ||||||
| 	centerRibbon: ['- Interface/Center a ribbon vertically', |  | ||||||
| 		function(target){ |  | ||||||
| 			target = target instanceof jQuery  |  | ||||||
| 				? this.ribbons.getElemGID(target) |  | ||||||
| 				: target |  | ||||||
| 
 |  | ||||||
| 			// align current ribbon...
 |  | ||||||
| 			this.ribbons.centerRibbon(target) |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	centerViewer: ['- Interface/Center the viewer', |  | ||||||
| 		function(target){ |  | ||||||
| 			this |  | ||||||
| 				.centerImage(target) |  | ||||||
| 				.centerRibbon(target) |  | ||||||
| 		}], |  | ||||||
| 
 | 
 | ||||||
|  | 	// Viewer/window resize event...
 | ||||||
| 	resizingWindow: ['- Interface/', | 	resizingWindow: ['- Interface/', | ||||||
| 		core.doc`This is called by the window resize event handler...
 | 		core.doc`This is called by the window resize event handler...
 | ||||||
| 		 | 		 | ||||||
| @ -694,55 +542,11 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		})], | 		})], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	focusImage: [ | 	// Zoom/scale protocol...
 | ||||||
| 		function(target, list){ | 	//
 | ||||||
| 			return function(){ | 	// Events...
 | ||||||
| 				this.ribbons.focusImage(this.data != null ? this.current : target) } }], | 	// NOTE: the implementation needs to call .resizingDone(..) when all 
 | ||||||
| 	focusRibbon: [ | 	// 		animations are done...
 | ||||||
| 		function(target, mode){ |  | ||||||
| 			mode = mode || this.config['ribbon-focus-mode'] |  | ||||||
| 
 |  | ||||||
| 			var c = this.data.getRibbonOrder() |  | ||||||
| 			var i = this.data.getRibbonOrder(target) |  | ||||||
| 			// NOTE: we are not changing the direction here based on 
 |  | ||||||
| 			// 		this.direction as swap will confuse the user...
 |  | ||||||
| 			var direction = c < i ? 'before' : 'after' |  | ||||||
| 
 |  | ||||||
| 			if(mode == 'visual'){ |  | ||||||
| 				var ribbons = this.ribbons |  | ||||||
| 				var r = this.data.getRibbon(target) |  | ||||||
| 				var t = ribbons.getImageByPosition('current', r) |  | ||||||
| 
 |  | ||||||
| 				if(t.length > 1){ |  | ||||||
| 					t = t.eq(direction == 'before' ? 0 : 1) |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				t = ribbons.getElemGID(t) |  | ||||||
| 
 |  | ||||||
| 				this.focusImage(t, r) |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	// NOTE: these prioritize whole images, i.e. each image will at least
 |  | ||||||
| 	// 		once be fully shown.
 |  | ||||||
| 	prevScreen: ['Navigate/Screen width back', |  | ||||||
| 		function(){ |  | ||||||
| 			// NOTE: the 0.2 is added to compensate for alignment/scaling
 |  | ||||||
| 			// 		errors -- 2.99 images wide counts as 3 while 2.5 as 2.
 |  | ||||||
| 			var w = Math.floor(this.screenwidth + 0.2) |  | ||||||
| 			w += (w % 2) - 1 |  | ||||||
| 			this.prevImage(w) |  | ||||||
| 		}], |  | ||||||
| 	nextScreen: ['Navigate/Screen width forward', |  | ||||||
| 		function(){ |  | ||||||
| 			var w = Math.floor(this.screenwidth + 0.2) |  | ||||||
| 			w += (w % 2) - 1 |  | ||||||
| 			this.nextImage(w) |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// XXX hide from user action list... (???)
 |  | ||||||
| 	// XXX need to check if a transition is running and delay timeout...
 |  | ||||||
| 	resizing: ['- Zoom/Scale root protocol action (not for direct use)',  | 	resizing: ['- Zoom/Scale root protocol action (not for direct use)',  | ||||||
| 		core.doc`Zooming/scaling root action...
 | 		core.doc`Zooming/scaling root action...
 | ||||||
| 
 | 
 | ||||||
| @ -785,34 +589,7 @@ module.ViewerActions = actions.Actions({ | |||||||
| 			//
 | 			//
 | ||||||
| 			// This will never be used directly, but will wrap protocol user
 | 			// This will never be used directly, but will wrap protocol user
 | ||||||
| 			// functions.
 | 			// functions.
 | ||||||
| 			//
 |  | ||||||
| 			// As an example see: .setScale(..)
 |  | ||||||
| 
 |  | ||||||
| 			var that = this |  | ||||||
| 			// stop currently running transition...
 |  | ||||||
| 			this.ribbons.scale(this.ribbons.scale()) |  | ||||||
| 
 |  | ||||||
| 			// transitionend handler...
 |  | ||||||
| 			if(!this.__resize_handler){ |  | ||||||
| 				this.__resize_handler = function(){ |  | ||||||
| 					that.__post_resize |  | ||||||
| 						&& that.resizingDone()  |  | ||||||
| 					delete that.__post_resize |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			this.ribbons.getRibbonSet() |  | ||||||
| 				.off('transitionend', this.__resize_handler) |  | ||||||
| 				.on('transitionend', this.__resize_handler) |  | ||||||
| 
 |  | ||||||
| 			// timeout handler...
 |  | ||||||
| 			this.__post_resize && clearTimeout(this.__post_resize) |  | ||||||
| 			return function(){ |  | ||||||
| 				this.__post_resize = setTimeout( |  | ||||||
| 					this.__resize_handler,  |  | ||||||
| 					this.config['resize-done-timeout'] || 300) |  | ||||||
| 			} |  | ||||||
| 		})], | 		})], | ||||||
| 
 |  | ||||||
| 	resizingDone: ['- Zoom/scale post-transition protocol action (not for direct use)', | 	resizingDone: ['- Zoom/scale post-transition protocol action (not for direct use)', | ||||||
| 		core.doc`Zooming/scaling post-transition action...
 | 		core.doc`Zooming/scaling post-transition action...
 | ||||||
| 	 | 	 | ||||||
| @ -835,56 +612,6 @@ module.ViewerActions = actions.Actions({ | |||||||
| 			// 		be called before the transition is done.
 | 			// 		be called before the transition is done.
 | ||||||
| 		})], | 		})], | ||||||
| 
 | 
 | ||||||
| 	// Zoom/scale protocol actions...
 |  | ||||||
| 	setScale: ['- Zoom/', |  | ||||||
| 		function(scale){ |  | ||||||
| 			this.resizing.chainCall(this, function(){ |  | ||||||
| 				this.ribbons && scale && this.ribbons.scale(scale) |  | ||||||
| 				// NOTE: we pass explicit scale here to compensate for animation...
 |  | ||||||
| 				this.refresh('*', scale) |  | ||||||
| 			}, 'scale', scale) |  | ||||||
| 		}], |  | ||||||
| 	fitOrig: ['Zoom/Fit to original scale', |  | ||||||
| 		function(){  |  | ||||||
| 			this.resizing.chainCall(this, function(){ |  | ||||||
| 				this.ribbons.scale(1)  |  | ||||||
| 				// NOTE: we pass explicit scale here to compensate for animation...
 |  | ||||||
| 				this.refresh('*', 1) |  | ||||||
| 			}, 'scale', 1) |  | ||||||
| 		}], |  | ||||||
| 	// NOTE: if this gets a count argument it will fit count images, 
 |  | ||||||
| 	// 		default is one.
 |  | ||||||
| 	// NOTE: this will add .config['fit-overflow'] to odd counts if no 
 |  | ||||||
| 	// 		overflow if passed.
 |  | ||||||
| 	// 		...this is done to add ability to control scroll indication.
 |  | ||||||
| 	fitImage: ['Zoom/Fit image', |  | ||||||
| 		function(count, overflow){ |  | ||||||
| 			this.resizing.chainCall(this, function(){ |  | ||||||
| 				if(count != null){ |  | ||||||
| 					overflow = overflow == false ? 0 : overflow |  | ||||||
| 					var o = overflow != null ? overflow  |  | ||||||
| 						: count % 2 != 1 ? 0 |  | ||||||
| 						: (this.config['fit-overflow'] || 0) |  | ||||||
| 					count += o |  | ||||||
| 				} |  | ||||||
| 				this.ribbons.fitImage(count) |  | ||||||
| 				// NOTE: we pass explicit scale here to compensate for animation...
 |  | ||||||
| 				this.refresh('*', this.ribbons.getScreenWidthImages(1) / count) |  | ||||||
| 			}, 'screenwidth', count, overflow) |  | ||||||
| 		}], |  | ||||||
| 	// NOTE: this does not account for ribbon spacing...
 |  | ||||||
| 	fitRibbon: ['Zoom/Fit ribbon vertically', |  | ||||||
| 		function(count, whole){ |  | ||||||
| 			this.resizing.chainCall(this, function(){ |  | ||||||
| 				this.ribbons.fitRibbon(count, whole) |  | ||||||
| 				// NOTE: we pass explicit scale here to compensate for animation...
 |  | ||||||
| 				this.refresh('*', this.ribbons.getScreenHeightRibbons(1, whole) / count) |  | ||||||
| 			}, 'screenheight', count, whole) |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// Zooming...
 |  | ||||||
| 	//
 |  | ||||||
| 	// Zooming is done by multiplying the current scale by .config['zoom-step']
 | 	// Zooming is done by multiplying the current scale by .config['zoom-step']
 | ||||||
| 	// and rounding to nearest discrete number of images to fit on screen.
 | 	// and rounding to nearest discrete number of images to fit on screen.
 | ||||||
| 	zoomIn: ['Zoom/Zoom in', | 	zoomIn: ['Zoom/Zoom in', | ||||||
| @ -917,24 +644,16 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		}], | 		}], | ||||||
| 
 | 
 | ||||||
| 	// Scale presets...
 | 	// Scale presets...
 | ||||||
| 	//
 | 	fitOrig: ['Zoom/Fit to original scale', | ||||||
|  | 		function(){ this.viewScale(1) }], | ||||||
| 	fitMax: ['Zoom/Fit the maximum number of images', | 	fitMax: ['Zoom/Fit the maximum number of images', | ||||||
| 		function(){ this.fitImage(this.config['max-screen-images']) }], | 		function(){ this.screenwidth = this.config['max-screen-images'] }], | ||||||
| 	fitScreen: ['Zoom/Fit image to screen', | 	fitScreen: ['Zoom/Fit image to screen', | ||||||
| 		function(){ this.screenfit = 1 }], | 		function(){ this.screenfit = 1 }], | ||||||
| 
 | 
 | ||||||
| 	// ribbon rotation...
 | 
 | ||||||
|  | 	// Ribbon rotation...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	ribbonRotation: ['- Interface|Ribbon/',  |  | ||||||
| 		function(a){  |  | ||||||
| 			if(arguments.length > 0){ |  | ||||||
| 				this.ribbons.rotate(a) |  | ||||||
| 
 |  | ||||||
| 			} else { |  | ||||||
| 				return this.ribbons.rotate() || 0 |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	// Rotate ribbon CW/CCW...
 | 	// Rotate ribbon CW/CCW...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// 	Rotate ribbon (default step)
 | 	// 	Rotate ribbon (default step)
 | ||||||
| @ -957,7 +676,7 @@ module.ViewerActions = actions.Actions({ | |||||||
| 		function(){ this.ribbonRotation(0) }], | 		function(){ this.ribbonRotation(0) }], | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// XXX experimental: not sure if this is the right way to go...
 | 	// XXX EXPERIMENTAL: not sure if this is the right way to go...
 | ||||||
| 	// XXX make this play nice with crops...
 | 	// XXX make this play nice with crops...
 | ||||||
| 	// 		...should this be a crop???
 | 	// 		...should this be a crop???
 | ||||||
| 	toggleRibbonList: ['Interface|Ribbon/Ribbons as images view', | 	toggleRibbonList: ['Interface|Ribbon/Ribbons as images view', | ||||||
| @ -992,6 +711,7 @@ module.Viewer = core.ImageGridFeatures.Feature({ | |||||||
| 		'base', | 		'base', | ||||||
| 		'workspace', | 		'workspace', | ||||||
| 		'introspection', | 		'introspection', | ||||||
|  | 		'ui-render', | ||||||
| 	], | 	], | ||||||
| 	suggested: [ | 	suggested: [ | ||||||
| 		// XXX is this the right way???
 | 		// XXX is this the right way???
 | ||||||
| @ -1196,7 +916,7 @@ core.ImageGridFeatures.Feature({ | |||||||
| 		// manage the .crop-mode css class...
 | 		// manage the .crop-mode css class...
 | ||||||
| 		['crop uncrop', | 		['crop uncrop', | ||||||
| 			function(){ | 			function(){ | ||||||
| 				this.ribbons.viewer[this.cropped ?  | 				this.dom[this.cropped ?  | ||||||
| 					'addClass'  | 					'addClass'  | ||||||
| 					: 'removeClass']('crop-mode') | 					: 'removeClass']('crop-mode') | ||||||
| 			}], | 			}], | ||||||
| @ -1546,11 +1266,11 @@ module.Cursor = core.ImageGridFeatures.Feature({ | |||||||
| 	actions: actions.Actions({ | 	actions: actions.Actions({ | ||||||
| 		toggleHiddenCursor: ['Interface/Cursor hidden', | 		toggleHiddenCursor: ['Interface/Cursor hidden', | ||||||
| 			toggler.CSSClassToggler( | 			toggler.CSSClassToggler( | ||||||
| 				function(){ return this.ribbons.viewer },  | 				function(){ return this.dom },  | ||||||
| 				'cursor-hidden', | 				'cursor-hidden', | ||||||
| 				function(state){ | 				function(state){ | ||||||
| 					var that = this | 					var that = this | ||||||
| 					var viewer = this.ribbons.viewer | 					var viewer = this.dom | ||||||
| 
 | 
 | ||||||
| 					if(state == 'on'){ | 					if(state == 'on'){ | ||||||
| 						var x, y | 						var x, y | ||||||
| @ -1619,12 +1339,12 @@ module.Cursor = core.ImageGridFeatures.Feature({ | |||||||
| 		//
 | 		//
 | ||||||
| 		toggleAutoHideCursor: ['Interface/Cursor auto-hide', | 		toggleAutoHideCursor: ['Interface/Cursor auto-hide', | ||||||
| 			toggler.CSSClassToggler( | 			toggler.CSSClassToggler( | ||||||
| 				function(){ return this.ribbons.viewer },  | 				function(){ return this.dom },  | ||||||
| 				'cursor-autohide', | 				'cursor-autohide', | ||||||
| 				function(state){ | 				function(state){ | ||||||
| 					var that = this | 					var that = this | ||||||
| 
 | 
 | ||||||
| 					var viewer = this.ribbons.viewer | 					var viewer = this.dom | ||||||
| 					// NOTE: this is handled by the keyboard feature...
 | 					// NOTE: this is handled by the keyboard feature...
 | ||||||
| 					var kb_target = this.__keyboard_event_source || $(window) | 					var kb_target = this.__keyboard_event_source || $(window) | ||||||
| 
 | 
 | ||||||
| @ -1654,7 +1374,7 @@ module.Cursor = core.ImageGridFeatures.Feature({ | |||||||
| 											: -1 | 											: -1 | ||||||
| 									if(timeout && timeout > 0){ | 									if(timeout && timeout > 0){ | ||||||
| 										m_timer = setTimeout(function(){ | 										m_timer = setTimeout(function(){ | ||||||
| 											var viewer = that.ribbons.viewer | 											var viewer = that.dom | ||||||
| 
 | 
 | ||||||
| 											// auto-hide is off -- restore...
 | 											// auto-hide is off -- restore...
 | ||||||
| 											if(!viewer.hasClass('cursor-autohide')){ | 											if(!viewer.hasClass('cursor-autohide')){ | ||||||
| @ -1680,7 +1400,7 @@ module.Cursor = core.ImageGridFeatures.Feature({ | |||||||
| 									// avoid this from delaying the keyboard handler...
 | 									// avoid this from delaying the keyboard handler...
 | ||||||
| 									kb_timer = setTimeout(function(){ | 									kb_timer = setTimeout(function(){ | ||||||
| 										kb_timer = null | 										kb_timer = null | ||||||
| 										var viewer = that.ribbons.viewer | 										var viewer = that.dom | ||||||
| 
 | 
 | ||||||
| 										// get key...
 | 										// get key...
 | ||||||
| 										var key = keyboard.normalizeKey( | 										var key = keyboard.normalizeKey( | ||||||
| @ -1842,7 +1562,7 @@ var ControlActions = actions.Actions({ | |||||||
| 						// 		nothing to do...
 | 						// 		nothing to do...
 | ||||||
| 						null | 						null | ||||||
| 					: (this.ribbons  | 					: (this.ribbons  | ||||||
| 							&& this.ribbons.viewer  | 							&& this.dom  | ||||||
| 							//&& this.ribbons.getRibbon().data('hammer') ? 'handling-click' : 'none' },
 | 							//&& this.ribbons.getRibbon().data('hammer') ? 'handling-click' : 'none' },
 | ||||||
| 							&& this.ribbons.getRibbon().hasClass('clickable')) ?  | 							&& this.ribbons.getRibbon().hasClass('clickable')) ?  | ||||||
| 						'handling-click'  | 						'handling-click'  | ||||||
| @ -1978,7 +1698,7 @@ var ControlActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 			var cl = central && central.offset().left | 			var cl = central && central.offset().left | ||||||
| 			var w = central && central.outerWidth(true) | 			var w = central && central.outerWidth(true) | ||||||
| 			var W = this.ribbons.viewer.width() | 			var W = this.dom.width() | ||||||
| 			var vmin = Math.min( | 			var vmin = Math.min( | ||||||
| 				document.body.offsetWidth,  | 				document.body.offsetWidth,  | ||||||
| 				document.body.offsetHeight) | 				document.body.offsetHeight) | ||||||
| @ -2044,7 +1764,7 @@ var ControlActions = actions.Actions({ | |||||||
| 						// 		nothing to do...
 | 						// 		nothing to do...
 | ||||||
| 						null | 						null | ||||||
| 					: (this.ribbons  | 					: (this.ribbons  | ||||||
| 							&& this.ribbons.viewer  | 							&& this.dom  | ||||||
| 							&& this.ribbons.getRibbon().hasClass('draggable')) ?   | 							&& this.ribbons.getRibbon().hasClass('draggable')) ?   | ||||||
| 						'handling-pan'  | 						'handling-pan'  | ||||||
| 					: 'none' }, | 					: 'none' }, | ||||||
| @ -2281,8 +2001,8 @@ var ControlActions = actions.Actions({ | |||||||
| 						// 		nothing to do...
 | 						// 		nothing to do...
 | ||||||
| 						null | 						null | ||||||
| 					: (this.ribbons  | 					: (this.ribbons  | ||||||
| 						&& this.ribbons.viewer  | 						&& this.dom  | ||||||
| 						&& this.ribbons.viewer.hasClass('mouse-wheel-scroll')) ? | 						&& this.dom.hasClass('mouse-wheel-scroll')) ? | ||||||
| 						'handling-mouse-wheel'  | 						'handling-mouse-wheel'  | ||||||
| 					: 'none' }, | 					: 'none' }, | ||||||
| 			'handling-mouse-wheel', | 			'handling-mouse-wheel', | ||||||
| @ -2318,7 +2038,7 @@ var ControlActions = actions.Actions({ | |||||||
| 						var rgid = this.ribbons.getElemGID(r) | 						var rgid = this.ribbons.getElemGID(r) | ||||||
| 
 | 
 | ||||||
| 						// XXX vertical scroll...
 | 						// XXX vertical scroll...
 | ||||||
| 						this.ribbons.viewer | 						this.dom | ||||||
| 							.on('wheel', function(){ | 							.on('wheel', function(){ | ||||||
| 							}) | 							}) | ||||||
| 
 | 
 | ||||||
| @ -2357,7 +2077,7 @@ var ControlActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 				// on...
 | 				// on...
 | ||||||
| 				if(state == 'on'){ | 				if(state == 'on'){ | ||||||
| 					this.ribbons.viewer.addClass('mouse-wheel-scroll') | 					this.dom.addClass('mouse-wheel-scroll') | ||||||
| 					// NOTE: we are resetting this to avoid multiple setting
 | 					// NOTE: we are resetting this to avoid multiple setting
 | ||||||
| 					// 		handlers...
 | 					// 		handlers...
 | ||||||
| 					this.off('updateRibbon', setup) | 					this.off('updateRibbon', setup) | ||||||
| @ -2368,7 +2088,7 @@ var ControlActions = actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 				// off...
 | 				// off...
 | ||||||
| 				} else { | 				} else { | ||||||
| 					this.ribbons.viewer.removeClass('mouse-wheel-scroll') | 					this.dom.removeClass('mouse-wheel-scroll') | ||||||
| 					this.off('updateRibbon', setup) | 					this.off('updateRibbon', setup) | ||||||
| 
 | 
 | ||||||
| 					this.data.ribbon_order.forEach(function(gid){ | 					this.data.ribbon_order.forEach(function(gid){ | ||||||
| @ -2390,13 +2110,13 @@ var ControlActions = actions.Actions({ | |||||||
| 				return state ? | 				return state ? | ||||||
| 						null | 						null | ||||||
| 					: (this.ribbons  | 					: (this.ribbons  | ||||||
| 							&& this.ribbons.viewer  | 							&& this.dom  | ||||||
| 							&& this.ribbons.viewer.data('hammer')) ?  | 							&& this.dom.data('hammer')) ?  | ||||||
| 						'handling-swipes'  | 						'handling-swipes'  | ||||||
| 					: 'none' }, | 					: 'none' }, | ||||||
| 			'handling-swipes', | 			'handling-swipes', | ||||||
| 			function(state){ | 			function(state){ | ||||||
| 				var viewer = this.ribbons.viewer | 				var viewer = this.dom | ||||||
| 
 | 
 | ||||||
| 				// on...
 | 				// on...
 | ||||||
| 				if(state == 'on'){ | 				if(state == 'on'){ | ||||||
| @ -2520,7 +2240,7 @@ module.Control = core.ImageGridFeatures.Feature({ | |||||||
| 			}], | 			}], | ||||||
| 			 | 			 | ||||||
| 		// if panned image is off screen, center it...
 | 		// if panned image is off screen, center it...
 | ||||||
| 		['setScale', | 		['viewScale', | ||||||
| 			function(){ | 			function(){ | ||||||
| 				var that = this | 				var that = this | ||||||
| 				Object.keys(this.data.ribbons).forEach(function(r){ | 				Object.keys(this.data.ribbons).forEach(function(r){ | ||||||
| @ -2617,7 +2337,7 @@ module.PreviewFilters = core.ImageGridFeatures.Feature({ | |||||||
| 					var cls = filters[state] | 					var cls = filters[state] | ||||||
| 					var classes = Object.values(filters) | 					var classes = Object.values(filters) | ||||||
| 						.filter(function(c){ return c != cls }) | 						.filter(function(c){ return c != cls }) | ||||||
| 					this.ribbons.viewer | 					this.dom | ||||||
| 						.find('.'+ classes.join(', .')) | 						.find('.'+ classes.join(', .')) | ||||||
| 							.removeClass(classes.join(' ')) | 							.removeClass(classes.join(' ')) | ||||||
| 
 | 
 | ||||||
| @ -2641,7 +2361,7 @@ module.PreviewFilters = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
| // XXX experimental...
 | // XXX EXPERIMENTAL...
 | ||||||
| 
 | 
 | ||||||
| // 		...not sure if this is the right way to go...
 | // 		...not sure if this is the right way to go...
 | ||||||
| // XXX need to get the minimal size and not the width as results will 
 | // XXX need to get the minimal size and not the width as results will 
 | ||||||
|  | |||||||
| @ -102,7 +102,7 @@ $(function(){ | |||||||
| 	m = Object.keys(m).filter(function(e){ return m[e] != null }) | 	m = Object.keys(m).filter(function(e){ return m[e] != null }) | ||||||
| 	console.log('Modules (%d):', m.length, m) | 	console.log('Modules (%d):', m.length, m) | ||||||
| 
 | 
 | ||||||
| 
 | 	try { | ||||||
| 		// setup actions...
 | 		// setup actions...
 | ||||||
| 		window.ig =  | 		window.ig =  | ||||||
| 		window.ImageGrid =  | 		window.ImageGrid =  | ||||||
| @ -119,6 +119,11 @@ $(function(){ | |||||||
| 					//'-ui-partial-ribbons',
 | 					//'-ui-partial-ribbons',
 | ||||||
| 				]) | 				]) | ||||||
| 
 | 
 | ||||||
|  | 	} catch(err){ | ||||||
|  | 		console.error(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 	// used to switch experimental actions on (set to true) or off (unset or false)...
 | 	// used to switch experimental actions on (set to true) or off (unset or false)...
 | ||||||
| 	//ig.experimental = true
 | 	//ig.experimental = true
 | ||||||
| @ -130,6 +135,9 @@ $(function(){ | |||||||
| 		&& console.warn('Features excluded (%d):', | 		&& console.warn('Features excluded (%d):', | ||||||
| 			ig.features.excluded.length,  | 			ig.features.excluded.length,  | ||||||
| 			ig.features.excluded) | 			ig.features.excluded) | ||||||
|  | 	Object.keys(ig.features.missing).length > 0 | ||||||
|  | 		&& console.warn('Features disabled (%d):', | ||||||
|  | 			ig.features.missing) | ||||||
| 	ig.features.disabled.length > 0  | 	ig.features.disabled.length > 0  | ||||||
| 		&& console.log('Features disabled (%d):', | 		&& console.log('Features disabled (%d):', | ||||||
| 			ig.features.disabled.length,  | 			ig.features.disabled.length,  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user