jquery-mobile/js/jquery.mobile.event.js
Kin Blas 48389d1ee1 Fixed bad variable name in teardown method of jquery.mobile.vmouse.js. It was causing an error that made one() bindings fail to fire off their handlers.
Modified select and slider code to use virtual events.

Modified tap and taphold code to make use of the virtual events.
2011-02-18 17:39:04 -08:00

261 lines
6.9 KiB
JavaScript

/*
* jQuery Mobile Framework : events
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(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("vmousedown", function( event ) {
if ( event.which && event.which !== 1 ) {
return false;
}
var moved = false,
touching = true,
origTarget = event.target,
origEvent = event.originalEvent,
origPos = [ event.pageX, event.pageY ],
originalType,
timer;
function moveHandler( event ) {
if( event.type == "scroll" ){
moved = true;
return;
}
var newPageXY = event;
if ((Math.abs(origPos[0] - newPageXY.pageX) > 10) ||
(Math.abs(origPos[1] - newPageXY.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 );
//scroll now cancels tap
$(window).one("scroll", moveHandler);
$this
.bind( "vmousemove", moveHandler )
.one( "vmouseup", function( event ) {
$this.unbind( "vmousemove", moveHandler );
$(window).unbind("scroll", moveHandler);
clearTimeout( timer );
touching = false;
/* ONLY trigger a 'tap' event if the start target is
* the same as the stop target.
*/
if ( !moved && ( origTarget == event.target ) ) {
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 );