mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 10:50:08 +00:00 
			
		
		
		
	
		
			
	
	
		
			299 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			299 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /********************************************************************** | ||
|  | *  | ||
|  | * This is here for reference... | ||
|  | * | ||
|  | * | ||
|  | **********************************************************************/ | ||
|  | ((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') | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /*********************************************************************/ | ||
|  | // Mouse...
 | ||
|  | 
 | ||
|  | // XXX add setup/taredown...
 | ||
|  | var Clickable =  | ||
|  | module.Clickable = core.ImageGridFeatures.Feature({ | ||
|  | 	title: '', | ||
|  | 	doc: '', | ||
|  | 
 | ||
|  | 	tag: 'ui-clickable', | ||
|  | 	depends: ['ui'], | ||
|  | 
 | ||
|  | 	config: { | ||
|  | 		'click-threshold': { | ||
|  | 			t: 100, | ||
|  | 			d: 5, | ||
|  | 		}, | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	handlers: [ | ||
|  | 		// setup click targets...
 | ||
|  | 		// XXX click only if we did not drag...
 | ||
|  | 		['updateImage',  | ||
|  | 			function(res, gid){ | ||
|  | 				var that = this | ||
|  | 				var img = this.ribbons.getImage(gid) | ||
|  | 
 | ||
|  | 				// set the clicker only once...
 | ||
|  | 				if(!img.prop('clickable')){ | ||
|  | 					var x, y, t, last, threshold | ||
|  | 					img | ||
|  | 						.prop('clickable', true) | ||
|  | 						.on('mousedown touchstart', function(evt){  | ||
|  | 							threshold = that.config['click-threshold'] | ||
|  | 							x = evt.clientX | ||
|  | 							y = evt.clientY | ||
|  | 							t = Date.now() | ||
|  | 						}) | ||
|  | 						.on('mouseup touchend', function(evt){  | ||
|  | 							if(that.__control_in_progress){ | ||
|  | 								return | ||
|  | 							} | ||
|  | 							// prevent another handler within a timeout...
 | ||
|  | 							// XXX not too sure about this...
 | ||
|  | 							if(t - last < threshold.t){ | ||
|  | 								return | ||
|  | 							} | ||
|  | 							// constrain distance between down and up events...
 | ||
|  | 							if(x != null  | ||
|  | 								&& Math.max( | ||
|  | 									Math.abs(x - evt.clientX),  | ||
|  | 									Math.abs(y - evt.clientY)) < threshold.d){ | ||
|  | 								// this will prevent double clicks...
 | ||
|  | 								x = null | ||
|  | 								y = null | ||
|  | 								that.focusImage(that.ribbons.getElemGID($(this))) | ||
|  | 								last = Date.now() | ||
|  | 							} | ||
|  | 						}) | ||
|  | 				} | ||
|  | 			}], | ||
|  | 	], | ||
|  | }) | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /*********************************************************************/ | ||
|  | // Touch/Control...
 | ||
|  | 
 | ||
|  | // XXX add zoom...
 | ||
|  | // XXX add vertical pan to ribbon-set...
 | ||
|  | var DirectControlHammer =  | ||
|  | module.DirectControlHammer = core.ImageGridFeatures.Feature({ | ||
|  | 	title: '', | ||
|  | 	doc: '', | ||
|  | 
 | ||
|  | 	tag: 'ui-direct-control-hammer', | ||
|  | 	exclusive: ['ui-control'], | ||
|  | 	depends: [ | ||
|  | 		'ui', | ||
|  | 		// this is only used to trigger reoad...
 | ||
|  | 		//'ui-partial-ribbons',
 | ||
|  | 	], | ||
|  | 
 | ||
|  | 	config: { | ||
|  | 		// This can be:
 | ||
|  | 		// 	'silent'	- silently focus central image after pan
 | ||
|  | 		// 	true		- focus central image after pan
 | ||
|  | 		// 	null		- do nothing.
 | ||
|  | 		'focus-central-image': 'silent', | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// XXX add setup/taredown...
 | ||
|  | 	// XXX add inertia...
 | ||
|  | 	// XXX hide current image indicator on drag...
 | ||
|  | 	// XXX add swipe up/down control...
 | ||
|  | 	// XXX add mode switching....
 | ||
|  | 	// XXX BUG: after panning and silent focus, marking works correctly 
 | ||
|  | 	// 		but image is not updated -- mark not drawn...
 | ||
|  | 	handlers: [ | ||
|  | 		// setup ribbon dragging...
 | ||
|  | 		// XXX it is possible to drag over the loaded ribbon section with
 | ||
|  | 		// 		two fingers, need to force update somehow...
 | ||
|  | 		// 		...and need to try and make the update in a single frame...
 | ||
|  | 		// 		Ways to go:
 | ||
|  | 		// 			- update on touchdown
 | ||
|  | 		// 			- update on liftoff
 | ||
|  | 		// XXX drag in single image mode ONLY if image is larger than screen...
 | ||
|  | 		['updateRibbon',  | ||
|  | 			function(_, target){ | ||
|  | 				var that = this | ||
|  | 				var r = this.ribbons.getRibbon(target) | ||
|  | 
 | ||
|  | 				// setup dragging...
 | ||
|  | 				if(r.length > 0 && !r.hasClass('draggable')){ | ||
|  | 					r | ||
|  | 						.addClass('draggable') | ||
|  | 						.hammer() | ||
|  | 						.on('pan', function(evt){ | ||
|  | 							//evt.stopPropagation()
 | ||
|  | 
 | ||
|  | 							// XXX stop all previous animations...
 | ||
|  | 							//r.velocity("stop")
 | ||
|  | 
 | ||
|  | 							var d = that.ribbons.dom | ||
|  | 							var s = that.scale | ||
|  | 							var g = evt.gesture | ||
|  | 
 | ||
|  | 
 | ||
|  | 							var data = r.data('drag-data') | ||
|  | 
 | ||
|  | 							// we just started...
 | ||
|  | 							if(!data){ | ||
|  | 								that.__control_in_progress = (that.__control_in_progress || 0) + 1 | ||
|  | 
 | ||
|  | 								// hide and remove current image indicator...
 | ||
|  | 								// NOTE: it will be reconstructed on 
 | ||
|  | 								// 		next .focusImage(..)
 | ||
|  | 								var m = that.ribbons.viewer | ||
|  | 									.find('.current-marker') | ||
|  | 										.velocity({opacity: 0}, { | ||
|  | 											duration: 100, | ||
|  | 											complete: function(){ | ||
|  | 												m.remove() | ||
|  | 											}, | ||
|  | 										}) | ||
|  | 
 | ||
|  | 								// store initial position...
 | ||
|  | 								var data = { | ||
|  | 									left: d.getOffset(this).left | ||
|  | 								} | ||
|  | 								r.data('drag-data', data) | ||
|  | 							} | ||
|  | 
 | ||
|  | 							// do the actual move...
 | ||
|  | 							d.setOffset(this, data.left + (g.deltaX / s)) | ||
|  | 
 | ||
|  | 							// when done...
 | ||
|  | 							if(g.isFinal){ | ||
|  | 								r.removeData('drag-data') | ||
|  | 
 | ||
|  | 								// XXX this seems to have trouble with off-screen images...
 | ||
|  | 								var central = that.ribbons.getImageByPosition('center', r) | ||
|  | 
 | ||
|  | 								// load stuff if needed...
 | ||
|  | 								that.updateRibbon(central) | ||
|  | 								 | ||
|  | 								// XXX add inertia....
 | ||
|  | 								//console.log('!!!!', g.velocityX)
 | ||
|  | 								//r.velocity({
 | ||
|  | 								//	translateX: (data.left + g.deltaX + (g.velocityX * 10)) +'px'
 | ||
|  | 								//}, 'easeInSine')
 | ||
|  | 
 | ||
|  | 								// silently focus central image...
 | ||
|  | 								if(that.config['focus-central-image'] == 'silent'){ | ||
|  | 									that.data.current = that.ribbons.getElemGID(central) | ||
|  | 									 | ||
|  | 								// focus central image in a normal manner...
 | ||
|  | 								} else if(that.config['focus-central-image']){ | ||
|  | 									that.focusImage(that.ribbons.getElemGID(central)) | ||
|  | 								} | ||
|  | 
 | ||
|  | 								setTimeout(function(){ | ||
|  | 									that.__control_in_progress -= 1 | ||
|  | 									if(that.__control_in_progress <= 0){ | ||
|  | 										delete that.__control_in_progress | ||
|  | 									} | ||
|  | 								}, 50) | ||
|  | 							} | ||
|  | 						}) | ||
|  | 				} | ||
|  | 			}], | ||
|  | 	], | ||
|  | }) | ||
|  | 
 | ||
|  | 
 | ||
|  | // XXX try direct control with hammer.js
 | ||
|  | // XXX load state from config...
 | ||
|  | // XXX sometimes this makes the indicator hang for longer than needed...
 | ||
|  | // XXX BUG: this conflicts a bit whith ui-clickable...
 | ||
|  | // 		...use this with hammer.js taps instead...
 | ||
|  | // XXX might be a good idea to make a universal and extensible control 
 | ||
|  | // 		mode toggler...
 | ||
|  | // 		...obvious chice would seem to be a meta toggler:
 | ||
|  | // 			config['control-mode'] = {
 | ||
|  | // 				<mode-name>: <mode-toggler>
 | ||
|  | // 			}
 | ||
|  | // 			and the action will toggle the given mode on and the previous
 | ||
|  | // 			off...
 | ||
|  | // 			XXX this seems a bit too complicated...
 | ||
|  | var IndirectControl =  | ||
|  | module.IndirectControl = core.ImageGridFeatures.Feature({ | ||
|  | 	title: '', | ||
|  | 	doc: '', | ||
|  | 
 | ||
|  | 	tag: 'ui-indirect-control', | ||
|  | 	// XXX is this correct???
 | ||
|  | 	exclusive: ['ui-control'], | ||
|  | 	depends: ['ui'], | ||
|  | 
 | ||
|  | 	config: { | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	actions: actions.Actions({ | ||
|  | 		toggleSwipeHandling:['Interface/Toggle indirect control swipe handling', | ||
|  | 			toggler.Toggler(null, | ||
|  | 				function(_, state){ | ||
|  | 
 | ||
|  | 					if(state == null){ | ||
|  | 						return (this.ribbons  | ||
|  | 								&& this.ribbons.viewer  | ||
|  | 								&& this.ribbons.viewer.data('hammer'))  | ||
|  | 							|| 'none' | ||
|  | 
 | ||
|  | 					// on...
 | ||
|  | 					} else if(state == 'handling-swipes'){ | ||
|  | 						var that = this | ||
|  | 						var viewer = this.ribbons.viewer | ||
|  | 
 | ||
|  | 						// prevent multiple handlers...
 | ||
|  | 						if(viewer.data('hammer') != null){ | ||
|  | 							return | ||
|  | 						} | ||
|  | 
 | ||
|  | 						viewer.hammer() | ||
|  | 
 | ||
|  | 						var h = viewer.data('hammer') | ||
|  | 						h.get('swipe').set({direction: Hammer.DIRECTION_ALL}) | ||
|  | 
 | ||
|  | 						viewer | ||
|  | 							.on('swipeleft', function(){ that.nextImage() }) | ||
|  | 							.on('swiperight', function(){ that.prevImage() }) | ||
|  | 							.on('swipeup', function(){ that.shiftImageUp() }) | ||
|  | 							.on('swipedown', function(){ that.shiftImageDown() }) | ||
|  | 
 | ||
|  | 					// off...
 | ||
|  | 					} else { | ||
|  | 						this.ribbons.viewer | ||
|  | 							.off('swipeleft') | ||
|  | 							.off('swiperight') | ||
|  | 							.off('swipeup') | ||
|  | 							.off('swipedown') | ||
|  | 							.removeData('hammer') | ||
|  | 					} | ||
|  | 
 | ||
|  | 				}, | ||
|  | 				'handling-swipes')], | ||
|  | 	}), | ||
|  | 
 | ||
|  | 	handlers: [ | ||
|  | 		['load',  | ||
|  | 			function(){ a.toggleSwipeHandling('on') }], | ||
|  | 		['stop',  | ||
|  | 			function(){ a.toggleSwipeHandling('off') }], | ||
|  | 	], | ||
|  | }) | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /********************************************************************** | ||
|  | * vim:set ts=4 sw=4 :                               */ return module }) |