mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-11-03 04:40:10 +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...
 | 
						|
		{browseMode: 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...
 | 
						|
		{browseMode: 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...
 | 
						|
		{browseMode: 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 })
 |