| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580 | 
							- // jquery.event.move
 
- //
 
- // 1.3.1
 
- //
 
- // Stephen Band
 
- //
 
- // Triggers 'movestart', 'move' and 'moveend' events after
 
- // mousemoves following a mousedown cross a distance threshold,
 
- // similar to the native 'dragstart', 'drag' and 'dragend' events.
 
- // Move events are throttled to animation frames. Move event objects
 
- // have the properties:
 
- //
 
- // pageX:
 
- // pageY:   Page coordinates of pointer.
 
- // startX:
 
- // startY:  Page coordinates of pointer at movestart.
 
- // distX:
 
- // distY:  Distance the pointer has moved since movestart.
 
- // deltaX:
 
- // deltaY:  Distance the finger has moved since last event.
 
- // velocityX:
 
- // velocityY:  Average velocity over last few events.
 
- (function (module) {
 
- 	if (typeof define === 'function' && define.amd) {
 
- 		// AMD. Register as an anonymous module.
 
- 		define(['jquery'], module);
 
- 	} else {
 
- 		// Browser globals
 
- 		module(jQuery);
 
- 	}
 
- })(function(jQuery, undefined){
 
- 	var // Number of pixels a pressed pointer travels before movestart
 
- 	    // event is fired.
 
- 	    threshold = 6,
 
- 	
 
- 	    add = jQuery.event.add,
 
- 	
 
- 	    remove = jQuery.event.remove,
 
- 	    // Just sugar, so we can have arguments in the same order as
 
- 	    // add and remove.
 
- 	    trigger = function(node, type, data) {
 
- 	    	jQuery.event.trigger(type, data, node);
 
- 	    },
 
- 	    // Shim for requestAnimationFrame, falling back to timer. See:
 
- 	    // see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 
- 	    requestFrame = (function(){
 
- 	    	return (
 
- 	    		window.requestAnimationFrame ||
 
- 	    		window.webkitRequestAnimationFrame ||
 
- 	    		window.mozRequestAnimationFrame ||
 
- 	    		window.oRequestAnimationFrame ||
 
- 	    		window.msRequestAnimationFrame ||
 
- 	    		function(fn, element){
 
- 	    			return window.setTimeout(function(){
 
- 	    				fn();
 
- 	    			}, 25);
 
- 	    		}
 
- 	    	);
 
- 	    })(),
 
- 	    
 
- 	    ignoreTags = {
 
- 	    	textarea: true,
 
- 	    	input: true,
 
- 	    	select: true,
 
- 	    	button: true
 
- 	    },
 
- 	    
 
- 	    mouseevents = {
 
- 	    	move: 'mousemove',
 
- 	    	cancel: 'mouseup dragstart',
 
- 	    	end: 'mouseup'
 
- 	    },
 
- 	    
 
- 	    touchevents = {
 
- 	    	move: 'touchmove',
 
- 	    	cancel: 'touchend',
 
- 	    	end: 'touchend'
 
- 	    };
 
- 	// Constructors
 
- 	
 
- 	function Timer(fn){
 
- 		var callback = fn,
 
- 				active = false,
 
- 				running = false;
 
- 		
 
- 		function trigger(time) {
 
- 			if (active){
 
- 				callback();
 
- 				requestFrame(trigger);
 
- 				running = true;
 
- 				active = false;
 
- 			}
 
- 			else {
 
- 				running = false;
 
- 			}
 
- 		}
 
- 		
 
- 		this.kick = function(fn) {
 
- 			active = true;
 
- 			if (!running) { trigger(); }
 
- 		};
 
- 		
 
- 		this.end = function(fn) {
 
- 			var cb = callback;
 
- 			
 
- 			if (!fn) { return; }
 
- 			
 
- 			// If the timer is not running, simply call the end callback.
 
- 			if (!running) {
 
- 				fn();
 
- 			}
 
- 			// If the timer is running, and has been kicked lately, then
 
- 			// queue up the current callback and the end callback, otherwise
 
- 			// just the end callback.
 
- 			else {
 
- 				callback = active ?
 
- 					function(){ cb(); fn(); } : 
 
- 					fn ;
 
- 				
 
- 				active = true;
 
- 			}
 
- 		};
 
- 	}
 
- 	// Functions
 
- 	
 
- 	function returnTrue() {
 
- 		return true;
 
- 	}
 
- 	
 
- 	function returnFalse() {
 
- 		return false;
 
- 	}
 
- 	
 
- 	function preventDefault(e) {
 
- 		e.preventDefault();
 
- 	}
 
- 	
 
- 	function preventIgnoreTags(e) {
 
- 		// Don't prevent interaction with form elements.
 
- 		if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
 
- 		
 
- 		e.preventDefault();
 
- 	}
 
- 	function isLeftButton(e) {
 
- 		// Ignore mousedowns on any button other than the left (or primary)
 
- 		// mouse button, or when a modifier key is pressed.
 
- 		return (e.which === 1 && !e.ctrlKey && !e.altKey);
 
- 	}
 
- 	function identifiedTouch(touchList, id) {
 
- 		var i, l;
 
- 		if (touchList.identifiedTouch) {
 
- 			return touchList.identifiedTouch(id);
 
- 		}
 
- 		
 
- 		// touchList.identifiedTouch() does not exist in
 
- 		// webkit yet… we must do the search ourselves...
 
- 		
 
- 		i = -1;
 
- 		l = touchList.length;
 
- 		
 
- 		while (++i < l) {
 
- 			if (touchList[i].identifier === id) {
 
- 				return touchList[i];
 
- 			}
 
- 		}
 
- 	}
 
- 	function changedTouch(e, event) {
 
- 		var touch = identifiedTouch(e.changedTouches, event.identifier);
 
- 		// This isn't the touch you're looking for.
 
- 		if (!touch) { return; }
 
- 		// Chrome Android (at least) includes touches that have not
 
- 		// changed in e.changedTouches. That's a bit annoying. Check
 
- 		// that this touch has changed.
 
- 		if (touch.pageX === event.pageX && touch.pageY === event.pageY) { return; }
 
- 		return touch;
 
- 	}
 
- 	// Handlers that decide when the first movestart is triggered
 
- 	
 
- 	function mousedown(e){
 
- 		var data;
 
- 		if (!isLeftButton(e)) { return; }
 
- 		data = {
 
- 			target: e.target,
 
- 			startX: e.pageX,
 
- 			startY: e.pageY,
 
- 			timeStamp: e.timeStamp
 
- 		};
 
- 		add(document, mouseevents.move, mousemove, data);
 
- 		add(document, mouseevents.cancel, mouseend, data);
 
- 	}
 
- 	function mousemove(e){
 
- 		var data = e.data;
 
- 		checkThreshold(e, data, e, removeMouse);
 
- 	}
 
- 	function mouseend(e) {
 
- 		removeMouse();
 
- 	}
 
- 	function removeMouse() {
 
- 		remove(document, mouseevents.move, mousemove);
 
- 		remove(document, mouseevents.cancel, mouseend);
 
- 	}
 
- 	function touchstart(e) {
 
- 		var touch, template;
 
- 		// Don't get in the way of interaction with form elements.
 
- 		if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
 
- 		touch = e.changedTouches[0];
 
- 		
 
- 		// iOS live updates the touch objects whereas Android gives us copies.
 
- 		// That means we can't trust the touchstart object to stay the same,
 
- 		// so we must copy the data. This object acts as a template for
 
- 		// movestart, move and moveend event objects.
 
- 		template = {
 
- 			target: touch.target,
 
- 			startX: touch.pageX,
 
- 			startY: touch.pageY,
 
- 			timeStamp: e.timeStamp,
 
- 			identifier: touch.identifier
 
- 		};
 
- 		// Use the touch identifier as a namespace, so that we can later
 
- 		// remove handlers pertaining only to this touch.
 
- 		add(document, touchevents.move + '.' + touch.identifier, touchmove, template);
 
- 		add(document, touchevents.cancel + '.' + touch.identifier, touchend, template);
 
- 	}
 
- 	function touchmove(e){
 
- 		var data = e.data,
 
- 		    touch = changedTouch(e, data);
 
- 		if (!touch) { return; }
 
- 		checkThreshold(e, data, touch, removeTouch);
 
- 	}
 
- 	function touchend(e) {
 
- 		var template = e.data,
 
- 		    touch = identifiedTouch(e.changedTouches, template.identifier);
 
- 		if (!touch) { return; }
 
- 		removeTouch(template.identifier);
 
- 	}
 
- 	function removeTouch(identifier) {
 
- 		remove(document, '.' + identifier, touchmove);
 
- 		remove(document, '.' + identifier, touchend);
 
- 	}
 
- 	// Logic for deciding when to trigger a movestart.
 
- 	function checkThreshold(e, template, touch, fn) {
 
- 		var distX = touch.pageX - template.startX,
 
- 		    distY = touch.pageY - template.startY;
 
- 		// Do nothing if the threshold has not been crossed.
 
- 		if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; }
 
- 		triggerStart(e, template, touch, distX, distY, fn);
 
- 	}
 
- 	function handled() {
 
- 		// this._handled should return false once, and after return true.
 
- 		this._handled = returnTrue;
 
- 		return false;
 
- 	}
 
- 	function flagAsHandled(e) {
 
- 		e._handled();
 
- 	}
 
- 	function triggerStart(e, template, touch, distX, distY, fn) {
 
- 		var node = template.target,
 
- 		    touches, time;
 
- 		touches = e.targetTouches;
 
- 		time = e.timeStamp - template.timeStamp;
 
- 		// Create a movestart object with some special properties that
 
- 		// are passed only to the movestart handlers.
 
- 		template.type = 'movestart';
 
- 		template.distX = distX;
 
- 		template.distY = distY;
 
- 		template.deltaX = distX;
 
- 		template.deltaY = distY;
 
- 		template.pageX = touch.pageX;
 
- 		template.pageY = touch.pageY;
 
- 		template.velocityX = distX / time;
 
- 		template.velocityY = distY / time;
 
- 		template.targetTouches = touches;
 
- 		template.finger = touches ?
 
- 			touches.length :
 
- 			1 ;
 
- 		// The _handled method is fired to tell the default movestart
 
- 		// handler that one of the move events is bound.
 
- 		template._handled = handled;
 
- 			
 
- 		// Pass the touchmove event so it can be prevented if or when
 
- 		// movestart is handled.
 
- 		template._preventTouchmoveDefault = function() {
 
- 			e.preventDefault();
 
- 		};
 
- 		// Trigger the movestart event.
 
- 		trigger(template.target, template);
 
- 		// Unbind handlers that tracked the touch or mouse up till now.
 
- 		fn(template.identifier);
 
- 	}
 
- 	// Handlers that control what happens following a movestart
 
- 	function activeMousemove(e) {
 
- 		var event = e.data.event,
 
- 		    timer = e.data.timer;
 
- 		updateEvent(event, e, e.timeStamp, timer);
 
- 	}
 
- 	function activeMouseend(e) {
 
- 		var event = e.data.event,
 
- 		    timer = e.data.timer;
 
- 		
 
- 		removeActiveMouse();
 
- 		endEvent(event, timer, function() {
 
- 			// Unbind the click suppressor, waiting until after mouseup
 
- 			// has been handled.
 
- 			setTimeout(function(){
 
- 				remove(event.target, 'click', returnFalse);
 
- 			}, 0);
 
- 		});
 
- 	}
 
- 	function removeActiveMouse(event) {
 
- 		remove(document, mouseevents.move, activeMousemove);
 
- 		remove(document, mouseevents.end, activeMouseend);
 
- 	}
 
- 	function activeTouchmove(e) {
 
- 		var event = e.data.event,
 
- 		    timer = e.data.timer,
 
- 		    touch = changedTouch(e, event);
 
- 		if (!touch) { return; }
 
- 		// Stop the interface from gesturing
 
- 		e.preventDefault();
 
- 		event.targetTouches = e.targetTouches;
 
- 		updateEvent(event, touch, e.timeStamp, timer);
 
- 	}
 
- 	function activeTouchend(e) {
 
- 		var event = e.data.event,
 
- 		    timer = e.data.timer,
 
- 		    touch = identifiedTouch(e.changedTouches, event.identifier);
 
- 		// This isn't the touch you're looking for.
 
- 		if (!touch) { return; }
 
- 		removeActiveTouch(event);
 
- 		endEvent(event, timer);
 
- 	}
 
- 	function removeActiveTouch(event) {
 
- 		remove(document, '.' + event.identifier, activeTouchmove);
 
- 		remove(document, '.' + event.identifier, activeTouchend);
 
- 	}
 
- 	// Logic for triggering move and moveend events
 
- 	function updateEvent(event, touch, timeStamp, timer) {
 
- 		var time = timeStamp - event.timeStamp;
 
- 		event.type = 'move';
 
- 		event.distX =  touch.pageX - event.startX;
 
- 		event.distY =  touch.pageY - event.startY;
 
- 		event.deltaX = touch.pageX - event.pageX;
 
- 		event.deltaY = touch.pageY - event.pageY;
 
- 		
 
- 		// Average the velocity of the last few events using a decay
 
- 		// curve to even out spurious jumps in values.
 
- 		event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time;
 
- 		event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time;
 
- 		event.pageX =  touch.pageX;
 
- 		event.pageY =  touch.pageY;
 
- 		timer.kick();
 
- 	}
 
- 	function endEvent(event, timer, fn) {
 
- 		timer.end(function(){
 
- 			event.type = 'moveend';
 
- 			trigger(event.target, event);
 
- 			
 
- 			return fn && fn();
 
- 		});
 
- 	}
 
- 	// jQuery special event definition
 
- 	function setup(data, namespaces, eventHandle) {
 
- 		// Stop the node from being dragged
 
- 		//add(this, 'dragstart.move drag.move', preventDefault);
 
- 		
 
- 		// Prevent text selection and touch interface scrolling
 
- 		//add(this, 'mousedown.move', preventIgnoreTags);
 
- 		
 
- 		// Tell movestart default handler that we've handled this
 
- 		add(this, 'movestart.move', flagAsHandled);
 
- 		// Don't bind to the DOM. For speed.
 
- 		return true;
 
- 	}
 
- 	
 
- 	function teardown(namespaces) {
 
- 		remove(this, 'dragstart drag', preventDefault);
 
- 		remove(this, 'mousedown touchstart', preventIgnoreTags);
 
- 		remove(this, 'movestart', flagAsHandled);
 
- 		
 
- 		// Don't bind to the DOM. For speed.
 
- 		return true;
 
- 	}
 
- 	
 
- 	function addMethod(handleObj) {
 
- 		// We're not interested in preventing defaults for handlers that
 
- 		// come from internal move or moveend bindings
 
- 		if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
 
- 			return;
 
- 		}
 
- 		
 
- 		// Stop the node from being dragged
 
- 		add(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid, preventDefault, undefined, handleObj.selector);
 
- 		
 
- 		// Prevent text selection and touch interface scrolling
 
- 		add(this, 'mousedown.' + handleObj.guid, preventIgnoreTags, undefined, handleObj.selector);
 
- 	}
 
- 	
 
- 	function removeMethod(handleObj) {
 
- 		if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
 
- 			return;
 
- 		}
 
- 		
 
- 		remove(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid);
 
- 		remove(this, 'mousedown.' + handleObj.guid);
 
- 	}
 
- 	
 
- 	jQuery.event.special.movestart = {
 
- 		setup: setup,
 
- 		teardown: teardown,
 
- 		add: addMethod,
 
- 		remove: removeMethod,
 
- 		_default: function(e) {
 
- 			var template, data;
 
- 			
 
- 			// If no move events were bound to any ancestors of this
 
- 			// target, high tail it out of here.
 
- 			if (!e._handled()) { return; }
 
- 			template = {
 
- 				target: e.target,
 
- 				startX: e.startX,
 
- 				startY: e.startY,
 
- 				pageX: e.pageX,
 
- 				pageY: e.pageY,
 
- 				distX: e.distX,
 
- 				distY: e.distY,
 
- 				deltaX: e.deltaX,
 
- 				deltaY: e.deltaY,
 
- 				velocityX: e.velocityX,
 
- 				velocityY: e.velocityY,
 
- 				timeStamp: e.timeStamp,
 
- 				identifier: e.identifier,
 
- 				targetTouches: e.targetTouches,
 
- 				finger: e.finger
 
- 			};
 
- 			data = {
 
- 				event: template,
 
- 				timer: new Timer(function(time){
 
- 					trigger(e.target, template);
 
- 				})
 
- 			};
 
- 			
 
- 			if (e.identifier === undefined) {
 
- 				// We're dealing with a mouse
 
- 				// Stop clicks from propagating during a move
 
- 				add(e.target, 'click', returnFalse);
 
- 				add(document, mouseevents.move, activeMousemove, data);
 
- 				add(document, mouseevents.end, activeMouseend, data);
 
- 			}
 
- 			else {
 
- 				// We're dealing with a touch. Stop touchmove doing
 
- 				// anything defaulty.
 
- 				e._preventTouchmoveDefault();
 
- 				add(document, touchevents.move + '.' + e.identifier, activeTouchmove, data);
 
- 				add(document, touchevents.end + '.' + e.identifier, activeTouchend, data);
 
- 			}
 
- 		}
 
- 	};
 
- 	jQuery.event.special.move = {
 
- 		setup: function() {
 
- 			// Bind a noop to movestart. Why? It's the movestart
 
- 			// setup that decides whether other move events are fired.
 
- 			add(this, 'movestart.move', jQuery.noop);
 
- 		},
 
- 		
 
- 		teardown: function() {
 
- 			remove(this, 'movestart.move', jQuery.noop);
 
- 		}
 
- 	};
 
- 	
 
- 	jQuery.event.special.moveend = {
 
- 		setup: function() {
 
- 			// Bind a noop to movestart. Why? It's the movestart
 
- 			// setup that decides whether other move events are fired.
 
- 			add(this, 'movestart.moveend', jQuery.noop);
 
- 		},
 
- 		
 
- 		teardown: function() {
 
- 			remove(this, 'movestart.moveend', jQuery.noop);
 
- 		}
 
- 	};
 
- 	add(document, 'mousedown.move', mousedown);
 
- 	add(document, 'touchstart.move', touchstart);
 
- 	// Make jQuery copy touch event properties over to the jQuery event
 
- 	// object, if they are not already listed. But only do the ones we
 
- 	// really need. IE7/8 do not have Array#indexOf(), but nor do they
 
- 	// have touch events, so let's assume we can ignore them.
 
- 	if (typeof Array.prototype.indexOf === 'function') {
 
- 		(function(jQuery, undefined){
 
- 			var props = ["changedTouches", "targetTouches"],
 
- 			    l = props.length;
 
- 			
 
- 			while (l--) {
 
- 				if (jQuery.event.props.indexOf(props[l]) === -1) {
 
- 					jQuery.event.props.push(props[l]);
 
- 				}
 
- 			}
 
- 		})(jQuery);
 
- 	};
 
- });
 
 
  |