mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 02:40:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			344 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
| /**********************************************************************
 | |
| * 
 | |
| *
 | |
| *
 | |
| **********************************************************************/
 | |
| ((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.dom.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.dom
 | |
| 					.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.dom.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',
 | |
| 		// XXX not sure if this is the right way to go...
 | |
| 		{mode: function(){ return !this.data.__range && 'disabled' }},
 | |
| 		function(image){
 | |
| 			var r = this.dom.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',
 | |
| 		// XXX not sure if this is the right way to go...
 | |
| 		{mode: function(){ return !this.data.__range && 'disabled' }},
 | |
| 		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',
 | |
| 		// XXX not sure if this is the right way to go...
 | |
| 		{mode: function(){ return !this.data.__range && 'disabled' }},
 | |
| 		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???
 | |
| 		['viewScale.pre',
 | |
| 			function(scale){
 | |
| 				var range = this.data.__range
 | |
| 				if(!this.ribbons || !range){
 | |
| 					return 
 | |
| 				}
 | |
| 
 | |
| 				this.ribbons.getRibbonLocator()
 | |
| 					.find('.range-offscreen-indicator')
 | |
| 						.hide()
 | |
| 			}],
 | |
| 		[[
 | |
| 			'focusImage',
 | |
| 			'viewScale',
 | |
| 			'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.dom.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 })
 |