/js/jquery.mobile.event.js
https://github.com/dannyc/jquery-mobile · JavaScript · 318 lines · 211 code · 68 blank · 39 comment · 23 complexity · 0e590728bf6f11c49d726aec9801a8d4 MD5 · raw file
- /*
- * "events" plugin - Handles events
- */
- (function( $, window, undefined ) {
- // add new event shortcuts
- $.each( ( "touchstart touchmove touchend orientationchange throttledresize " +
- "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";
- function triggerCustomEvent( obj, eventType, event ) {
- var originalType = event.type;
- event.type = eventType;
- $.event.handle.call( obj, event );
- event.type = originalType;
- }
- // also handles scrollstop
- $.event.special.scrollstart = {
- enabled: true,
- setup: function() {
- var thisObject = this,
- $this = $( thisObject ),
- scrolling,
- timer;
- function trigger( event, state ) {
- scrolling = state;
- triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
- }
- // 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( "vmousedown", function( event ) {
- if ( event.which && event.which !== 1 ) {
- return false;
- }
- var origTarget = event.target,
- origEvent = event.originalEvent,
- timer;
- function clearTapTimer() {
- clearTimeout( timer );
- }
- function clearTapHandlers() {
- clearTapTimer();
- $this.unbind( "vclick", clickHandler )
- .unbind( "vmouseup", clearTapTimer )
- .unbind( "vmousecancel", clearTapHandlers );
- }
- function clickHandler(event) {
- clearTapHandlers();
- // ONLY trigger a 'tap' event if the start target is
- // the same as the stop target.
- if ( origTarget == event.target ) {
- triggerCustomEvent( thisObject, "tap", event );
- }
- }
- $this.bind( "vmousecancel", clearTapHandlers )
- .bind( "vmouseup", clearTapTimer )
- .bind( "vclick", clickHandler );
- timer = setTimeout(function() {
- triggerCustomEvent( thisObject, "taphold", $.Event( "taphold" ) );
- }, 750 );
- });
- }
- };
- // also handles swipeleft, swiperight
- $.event.special.swipe = {
- scrollSupressionThreshold: 10, // More than this horizontal displacement, and we will suppress scrolling.
- durationThreshold: 1000, // More time than this, and it isn't a swipe.
- horizontalDistanceThreshold: 30, // Swipe horizontal displacement must be more than this.
- verticalDistanceThreshold: 75, // Swipe vertical displacement must be less than this.
- 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 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
- event.preventDefault();
- }
- }
- $this.bind( touchMoveEvent, moveHandler )
- .one( touchStopEvent, function( event ) {
- $this.unbind( touchMoveEvent, moveHandler );
- if ( start && stop ) {
- if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
- Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
- Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
- start.origin.trigger( "swipe" )
- .trigger( start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight" );
- }
- }
- start = stop = undefined;
- });
- });
- }
- };
- (function( $, window ) {
- // "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 && $.mobile.orientationChangeEnabled ) {
- 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( "throttledresize", 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 && $.mobile.orientationChangeEnabled ) {
- return false;
- }
- // Because the orientationchange event doesn't exist, unbind the
- // resize event handler.
- win.unbind( "throttledresize", 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()
- $.event.special.orientationchange.orientation = get_orientation = function() {
- var isPortrait = true, elem = document.documentElement;
- // prefer window orientation to the calculation based on screensize as
- // the actual screen resize takes place before or after the orientation change event
- // has been fired depending on implementation (eg android 2.3 is before, iphone after).
- // More testing is required to determine if a more reliable method of determining the new screensize
- // is possible when orientationchange is fired. (eg, use media queries + element + opacity)
- if ( $.support.orientation ) {
- // if the window orientation registers as 0 or 180 degrees report
- // portrait, otherwise landscape
- isPortrait = window.orientation % 180 == 0;
- } else {
- isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
- }
- return isPortrait ? "portrait" : "landscape";
- };
- })( jQuery, window );
- // throttled resize event
- (function() {
- $.event.special.throttledresize = {
- setup: function() {
- $( this ).bind( "resize", handler );
- },
- teardown: function(){
- $( this ).unbind( "resize", handler );
- }
- };
- var throttle = 250,
- handler = function() {
- curr = ( new Date() ).getTime();
- diff = curr - lastCall;
- if ( diff >= throttle ) {
- lastCall = curr;
- $( this ).trigger( "throttledresize" );
- } else {
- if ( heldCall ) {
- clearTimeout( heldCall );
- }
- // Promise a held call will still execute
- heldCall = setTimeout( handler, throttle - diff );
- }
- },
- lastCall = 0,
- heldCall,
- curr,
- diff;
- })();
- $.each({
- scrollstop: "scrollstart",
- taphold: "tap",
- swipeleft: "swipe",
- swiperight: "swipe"
- }, function( event, sourceEvent ) {
- $.event.special[ event ] = {
- setup: function() {
- $( this ).bind( sourceEvent, $.noop );
- }
- };
- });
- })( jQuery, this );