(function($, undefined ) { // add new event shortcuts $.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) { $.fn[ name ] = function( fn ) { return fn ? this.bind( name, fn ) : this.trigger( name ); }; $.attrFn[ name ] = true; }); var supportTouch = $.support.touch, scrollEvent = "touchmove scroll", touchStartEvent = supportTouch ? "touchstart" : "mousedown", touchStopEvent = supportTouch ? "touchend" : "mouseup", touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; // also handles scrollstop $.event.special.scrollstart = { enabled: true, setup: function() { var thisObject = this, $this = $( thisObject ), scrolling, timer; function trigger( event, state ) { scrolling = state; var originalType = event.type; event.type = scrolling ? "scrollstart" : "scrollstop"; $.event.handle.call( thisObject, event ); event.type = originalType; } // iPhone triggers scroll after a small delay; use touchmove instead $this.bind( scrollEvent, function( event ) { if ( !$.event.special.scrollstart.enabled ) { return; } if ( !scrolling ) { trigger( event, true ); } clearTimeout( timer ); timer = setTimeout(function() { trigger( event, false ); }, 50 ); }); } }; // also handles taphold $.event.special.tap = { setup: function() { var thisObject = this, $this = $( thisObject ); $this .bind( touchStartEvent, function( event ) { if ( event.which && event.which !== 1 ) { return; } var moved = false, touching = true, origPos = [ event.pageX, event.pageY ], originalType, timer; function moveHandler() { if ((Math.abs(origPos[0] - event.pageX) > 10) || (Math.abs(origPos[1] - event.pageY) > 10)) { moved = true; } } timer = setTimeout(function() { if ( touching && !moved ) { originalType = event.type; event.type = "taphold"; $.event.handle.call( thisObject, event ); event.type = originalType; } }, 750 ); $this .one( touchMoveEvent, moveHandler) .one( touchStopEvent, function( event ) { $this.unbind( touchMoveEvent, moveHandler ); clearTimeout( timer ); touching = false; if ( !moved ) { originalType = event.type; event.type = "tap"; $.event.handle.call( thisObject, event ); event.type = originalType; } }); }); } }; // also handles swipeleft, swiperight $.event.special.swipe = { setup: function() { var thisObject = this, $this = $( thisObject ); $this .bind( touchStartEvent, function( event ) { var data = event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event, start = { time: (new Date).getTime(), coords: [ data.pageX, data.pageY ], origin: $( event.target ) }, stop; function moveHandler( event ) { if ( !start ) { return; } var data = event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event; stop = { time: (new Date).getTime(), coords: [ data.pageX, data.pageY ] }; // prevent scrolling if ( Math.abs( start.coords[0] - stop.coords[0] ) > 10 ) { event.preventDefault(); } } $this .bind( touchMoveEvent, moveHandler ) .one( touchStopEvent, function( event ) { $this.unbind( touchMoveEvent, moveHandler ); if ( start && stop ) { if ( stop.time - start.time < 1000 && Math.abs( start.coords[0] - stop.coords[0]) > 30 && Math.abs( start.coords[1] - stop.coords[1]) < 75 ) { start.origin .trigger( "swipe" ) .trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" ); } } start = stop = undefined; }); }); } }; (function($){ // "Cowboy" Ben Alman var win = $(window), special_event, get_orientation, last_orientation; $.event.special.orientationchange = special_event = { setup: function(){ // If the event is supported natively, return false so that jQuery // will bind to the event using DOM methods. if ( $.support.orientation ) { return false; } // Get the current orientation to avoid initial double-triggering. last_orientation = get_orientation(); // Because the orientationchange event doesn't exist, simulate the // event by testing window dimensions on resize. win.bind( "resize", handler ); }, teardown: function(){ // If the event is not supported natively, return false so that // jQuery will unbind the event using DOM methods. if ( $.support.orientation ) { return false; } // Because the orientationchange event doesn't exist, unbind the // resize event handler. win.unbind( "resize", handler ); }, add: function( handleObj ) { // Save a reference to the bound event handler. var old_handler = handleObj.handler; handleObj.handler = function( event ) { // Modify event object, adding the .orientation property. event.orientation = get_orientation(); // Call the originally-bound event handler and return its result. return old_handler.apply( this, arguments ); }; } }; // If the event is not supported natively, this handler will be bound to // the window resize event to simulate the orientationchange event. function handler() { // Get the current orientation. var orientation = get_orientation(); if ( orientation !== last_orientation ) { // The orientation has changed, so trigger the orientationchange event. last_orientation = orientation; win.trigger( "orientationchange" ); } }; // Get the current page orientation. This method is exposed publicly, should it // be needed, as jQuery.event.special.orientationchange.orientation() special_event.orientation = get_orientation = function() { var elem = document.documentElement; return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape"; }; })(jQuery); $.each({ scrollstop: "scrollstart", taphold: "tap", swipeleft: "swipe", swiperight: "swipe" }, function( event, sourceEvent ) { $.event.special[ event ] = { setup: function() { $( this ).bind( sourceEvent, $.noop ); } }; }); })( jQuery );