| 
									
										
										
										
											2016-12-29 23:23:05 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var RangeActions = actions.Actions({ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 	.makeBrace('open')
 | 
					
						
							|  |  |  | 	// 	.makeBrace('open', image)
 | 
					
						
							|  |  |  | 	// 	.makeBrace('close')
 | 
					
						
							|  |  |  | 	// 	.makeBrace('close', image)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX this should not be here...
 | 
					
						
							|  |  |  | 	makeBrace: ['- Range/', | 
					
						
							|  |  |  | 		function(type, gid){ | 
					
						
							|  |  |  | 			var cls = type == 'open' ? 'brace-open' : 'brace-close' | 
					
						
							|  |  |  | 			var r = this.ribbons.viewer.find('.ribbon') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(brace.length == 0){ | 
					
						
							|  |  |  | 				brace = $('<span>') | 
					
						
							|  |  |  | 					.addClass('mark brace '+cls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else if(brace.length > 1){ | 
					
						
							|  |  |  | 				brace = brace.detach().first() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			brace | 
					
						
							|  |  |  | 				.attr('gid', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.ribbons.getImage(gid)[type == 'open' ? 'before' : 'after'](brace) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX this does not work for non-current images ...
 | 
					
						
							|  |  |  | 			this.ribbons.preventTransitions(r) | 
					
						
							|  |  |  | 			// XXX is this correct here???
 | 
					
						
							|  |  |  | 			this.focusImage() | 
					
						
							|  |  |  | 			this.ribbons.restoreTransitions(r) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX add "brace off screen" indicators....
 | 
					
						
							|  |  |  | 	updateRangeIndicators: ['- Range/', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			var update = false | 
					
						
							|  |  |  | 			var range = this.data.__range | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX not sure if this sweeping action is the right way to 
 | 
					
						
							|  |  |  | 			// 		go but it sure makes things simpler...
 | 
					
						
							|  |  |  | 			if(range == null){ | 
					
						
							|  |  |  | 				update = true | 
					
						
							|  |  |  | 				this.ribbons.viewer | 
					
						
							|  |  |  | 					.find('.ribbon .mark.brace') | 
					
						
							|  |  |  | 						.remove() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				this.data.ribbon_order.forEach(function(r){ | 
					
						
							|  |  |  | 					var a = that.data.getImage(range[0], 'after', r) | 
					
						
							|  |  |  | 					var b = that.data.getImage(range[1], 'before', r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// only draw braces if some part of the ribbon is 
 | 
					
						
							|  |  |  | 					// in range...
 | 
					
						
							|  |  |  | 					if(a != null && b != null){ | 
					
						
							|  |  |  | 						that | 
					
						
							|  |  |  | 							.makeBrace('open', a) | 
					
						
							|  |  |  | 							.makeBrace('close', b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// remove braces from ribbon...
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						update = true | 
					
						
							|  |  |  | 						that.ribbons.getRibbon(r) | 
					
						
							|  |  |  | 							.find('.mark.brace') | 
					
						
							|  |  |  | 								.remove() | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(update){ | 
					
						
							|  |  |  | 				var r = this.ribbons.viewer.find('.ribbon') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX this does not work for non-current images ...
 | 
					
						
							|  |  |  | 				this.ribbons.preventTransitions(r) | 
					
						
							|  |  |  | 				// XXX is this correct here???
 | 
					
						
							|  |  |  | 				this.focusImage() | 
					
						
							|  |  |  | 				this.ribbons.restoreTransitions(r) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	clearRange: ['Range/Clear range', | 
					
						
							| 
									
										
										
										
											2016-12-30 03:21:09 +03:00
										 |  |  | 		// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 		{browseMode: function(){ return !this.data.__range && 'disabled' }}, | 
					
						
							| 
									
										
										
										
											2016-12-29 23:23:05 +03:00
										 |  |  | 		function(image){ | 
					
						
							|  |  |  | 			var r = this.ribbons.viewer.find('.ribbon') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			delete this.data.__range | 
					
						
							|  |  |  | 			this.updateRangeIndicators() | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	// procedure:
 | 
					
						
							|  |  |  | 	// 	- set brace 
 | 
					
						
							|  |  |  | 	// 		when no braces set:
 | 
					
						
							|  |  |  | 	// 			- sets two braces around target image
 | 
					
						
							|  |  |  | 	// 		When a brace is set:
 | 
					
						
							|  |  |  | 	// 			- check brace orientation and set open/close to target
 | 
					
						
							|  |  |  | 	// 	- update braces on all ribbons
 | 
					
						
							|  |  |  | 	setRangeBorder: ['Range/Set range border', | 
					
						
							|  |  |  | 		function(image, type){ | 
					
						
							|  |  |  | 			var image = this.data.getImage(image) | 
					
						
							|  |  |  | 			var range = this.data.__range = this.data.__range || [] | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// no range...
 | 
					
						
							|  |  |  | 			if(range.length == 0){ | 
					
						
							|  |  |  | 				range.push(image) | 
					
						
							|  |  |  | 				range.push(image) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// range set...
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var a = this.data.getImageOrder(range[0]) | 
					
						
							|  |  |  | 				var b = this.data.getImageOrder(range[1]) | 
					
						
							|  |  |  | 				var t = this.data.getImageOrder(image) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var i =  | 
					
						
							|  |  |  | 					// type/range conflict...
 | 
					
						
							|  |  |  | 					type == 'close' && t < a ? null | 
					
						
							|  |  |  | 					: type == 'open' && t > b ? null | 
					
						
							|  |  |  | 					// extend left/right...
 | 
					
						
							|  |  |  | 					: t <= a ? 0  | 
					
						
							|  |  |  | 					: t >= b ? 1 | 
					
						
							|  |  |  | 					// set left/right limit...
 | 
					
						
							|  |  |  | 					: type == 'open' ? 0 | 
					
						
							|  |  |  | 					: type == 'close' ? 1 | 
					
						
							|  |  |  | 					// narrow to the closest brace...
 | 
					
						
							|  |  |  | 					: a - t < b - t ? 0 | 
					
						
							|  |  |  | 					: 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(i == null){ | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				range[i] = image | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.updateRangeIndicators() | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	openRange: ['Range/Open range', | 
					
						
							|  |  |  | 		function(image){ this.setRangeBorder(image, 'open') }], | 
					
						
							|  |  |  | 	closeRange: ['Range/Close range', | 
					
						
							|  |  |  | 		function(image){ this.setRangeBorder(image, 'close') }], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cropRange: ['Range|Crop/Crop range', | 
					
						
							| 
									
										
										
										
											2016-12-30 03:21:09 +03:00
										 |  |  | 		// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 		{browseMode: function(){ return !this.data.__range && 'disabled' }}, | 
					
						
							| 
									
										
										
										
											2016-12-29 23:23:05 +03:00
										 |  |  | 		function(){ | 
					
						
							|  |  |  | 			var range = this.data.__range | 
					
						
							|  |  |  | 			var order = this.data.order | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			range ?  | 
					
						
							|  |  |  | 				this.crop(order.slice( | 
					
						
							|  |  |  | 					order.indexOf(range[0]),  | 
					
						
							|  |  |  | 					order.indexOf(range[1])+1)) | 
					
						
							|  |  |  | 				: this.crop([]) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	cropRangeOut: ['Range|Crop/Crop out range', | 
					
						
							| 
									
										
										
										
											2016-12-30 03:21:09 +03:00
										 |  |  | 		// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 		{browseMode: function(){ return !this.data.__range && 'disabled' }}, | 
					
						
							| 
									
										
										
										
											2016-12-29 23:23:05 +03:00
										 |  |  | 		function(){ | 
					
						
							|  |  |  | 			var range = this.data.__range | 
					
						
							|  |  |  | 			var order = this.data.order | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			range ?  | 
					
						
							|  |  |  | 				this.crop(order | 
					
						
							|  |  |  | 					.slice(0, order.indexOf(range[0])) | 
					
						
							|  |  |  | 					.concat(order.slice(order.indexOf(range[1])+1))) | 
					
						
							|  |  |  | 				: this.crop() | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Range =  | 
					
						
							|  |  |  | module.Range = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'ui-range', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: RangeActions, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		[[ | 
					
						
							|  |  |  | 			'crop', | 
					
						
							|  |  |  | 			'reload', | 
					
						
							|  |  |  | 		],  | 
					
						
							|  |  |  | 			function(){ this.updateRangeIndicators() }], | 
					
						
							|  |  |  | 		['updateImage',  | 
					
						
							|  |  |  | 			function(_, gid){ | 
					
						
							|  |  |  | 				var range = this.data.__range | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(this.ribbons && range && gid){ | 
					
						
							|  |  |  | 					var r = this.data.getRibbon(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var a = gid == range[0] ?  | 
					
						
							|  |  |  | 						this.makeBrace('open', gid) | 
					
						
							|  |  |  | 						: this.data.getImage(range[0], 'after', r) | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					var b = gid == range[1] ?  | 
					
						
							|  |  |  | 						this.makeBrace('close', gid) | 
					
						
							|  |  |  | 						: this.data.getImage(range[1], 'before', r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if(a != null && b != null){ | 
					
						
							|  |  |  | 						gid == a  | 
					
						
							|  |  |  | 							&& this.makeBrace('open', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						gid == b | 
					
						
							|  |  |  | 							&& this.makeBrace('close', gid) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 		['shiftImage.pre', | 
					
						
							|  |  |  | 			function(gid){  | 
					
						
							|  |  |  | 				var range = this.data.__range | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(this.ribbons && range){ | 
					
						
							|  |  |  | 					this.ribbons.getImageMarks(gid).filter('.brace').remove() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return function(){ | 
					
						
							|  |  |  | 						this.updateRangeIndicators()  | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}],  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// show/hide off-screen indicators...
 | 
					
						
							|  |  |  | 		// XXX STUB: should we animate indicators???
 | 
					
						
							|  |  |  | 		['setScale.pre', | 
					
						
							|  |  |  | 			function(scale){ | 
					
						
							|  |  |  | 				var range = this.data.__range | 
					
						
							|  |  |  | 				if(!this.ribbons || !range){ | 
					
						
							|  |  |  | 					return  | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				this.ribbons.getRibbonLocator() | 
					
						
							|  |  |  | 					.find('.range-offscreen-indicator') | 
					
						
							|  |  |  | 						.hide() | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 		[[ | 
					
						
							|  |  |  | 			'focusImage', | 
					
						
							|  |  |  | 			'setScale', | 
					
						
							|  |  |  | 			'updateRangeIndicators', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 			function(_, gid){ | 
					
						
							|  |  |  | 				gid = gid || this.current | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				var locator = this.ribbons.getRibbonLocator() | 
					
						
							|  |  |  | 				var range = this.data.__range | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(!this.ribbons || !range){ | 
					
						
							|  |  |  | 					locator.find('.range-offscreen-indicator').remove() | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var Wr = this.ribbons.viewer.width() | 
					
						
							|  |  |  | 				var W = (Wr / this.scale) / 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var a = this.data.getImageOrder(range[0]) | 
					
						
							|  |  |  | 				var b = this.data.getImageOrder(range[1]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var _make = function(gid, ribbon, direction){ | 
					
						
							|  |  |  | 					var t = ribbon[0].offsetTop  | 
					
						
							|  |  |  | 					var h = ribbon[0].offsetHeight / 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var i = that.data.getImageOrder(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var indicator = locator | 
					
						
							|  |  |  | 						.find('.range-offscreen-indicator.'+direction+'[gid="'+gid+'"]') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX this only works if brace is loaded...
 | 
					
						
							|  |  |  | 					if(direction == 'left'){ | 
					
						
							|  |  |  | 						var brace = ribbon.find('.mark.brace-open') | 
					
						
							|  |  |  | 						if(brace.length == 0 || brace.offset().left >= 0){ | 
					
						
							|  |  |  | 							return indicator.remove() | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					} else if(direction == 'right'){ | 
					
						
							|  |  |  | 						var brace = ribbon.find('.mark.brace-close') | 
					
						
							|  |  |  | 						if(brace.length == 0 || brace.offset().left < Wr){ | 
					
						
							|  |  |  | 							return indicator.remove() | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if(indicator.length == 0){ | 
					
						
							|  |  |  | 						locator.append($('<div>') | 
					
						
							|  |  |  | 							.addClass('range-offscreen-indicator '+direction) | 
					
						
							|  |  |  | 							.attr('gid', gid)) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var css = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					css.left = (direction == 'left' ?  | 
					
						
							|  |  |  | 						-W  | 
					
						
							|  |  |  | 						: W-(indicator[0] && indicator[0].offsetWidth)) + 'px' | 
					
						
							|  |  |  | 					css.top = (t + h) + 'px' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					that.ribbons.preventTransitions(indicator) | 
					
						
							|  |  |  | 					indicator | 
					
						
							|  |  |  | 						.css(css) | 
					
						
							|  |  |  | 						.show() | 
					
						
							|  |  |  | 					that.ribbons.restoreTransitions(indicator) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return indicator | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				setTimeout(function(){ | 
					
						
							|  |  |  | 					that.data.ribbon_order.forEach(function(gid){ | 
					
						
							|  |  |  | 						var ribbon = that.ribbons.getRibbon(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						_make(gid, ribbon, 'left') | 
					
						
							|  |  |  | 						_make(gid, ribbon, 'right') | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 				}, 400) | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |