Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixes for issue 1464 - No way to stop a link from being followed with…

… some custom event (tap, taphold)

jquery.mobile.vmouse.js:

	- Modified triggerVirtualEvent() so that it returns the virtual event instead of the isDefaultPrevented() result of the virtual event.

		- Updated all references to triggerVirtualEvent() that relied on the boolean return value to instead check the isDefaultPrevented() call on the event now returned.

			- Updated mouseEventCallback() to propagate the iDefaultPrevented(), isPropagationStopped(), and stopImmediatePropagation() values from the virtual event on to the  original mouse event.

			jquery.mobile.event.js

				- Modified the "taphold" trigger code to create a new $.Event() instead of passing the stale vmousedown event.

					- Added clearTapTimer() which is called from a new vmouseup binding, to prevent the timer from firing between the tie the finger/mouse goes up and the click event is dispatched.

					- Added some propagation tests for the "tap" event. Tests for "taphold" will have to wait until we fix the problem where multiple taphold timers are fired off when an element and one of its ancestors is bound to taphold.
  • Loading branch information...
commit 7cce0c5573ad593b17302082e936b10f568551a4 1 parent 0b41fe8
@jblas jblas authored
View
16 js/jquery.mobile.event.js
@@ -78,16 +78,19 @@ $.event.special.tap = {
return false;
}
- var touching = true,
- origTarget = event.target,
+ var origTarget = event.target,
origEvent = event.originalEvent,
timer;
+ function clearTapTimer() {
+ clearTimeout( timer );
+ }
+
function clearTapHandlers() {
- touching = false;
- clearTimeout(timer);
+ clearTapTimer();
$this.unbind( "vclick", clickHandler )
+ .unbind( "vmouseup", clearTapTimer )
.unbind( "vmousecancel", clearTapHandlers );
}
@@ -102,12 +105,11 @@ $.event.special.tap = {
}
$this.bind( "vmousecancel", clearTapHandlers )
+ .bind( "vmouseup", clearTapTimer )
.bind( "vclick", clickHandler );
timer = setTimeout(function() {
- if ( touching ) {
- triggerCustomEvent( thisObject, "taphold", event );
- }
+ triggerCustomEvent( thisObject, "taphold", $.Event( "taphold" ) );
}, 750 );
});
}
View
23 js/jquery.mobile.vmouse.js
@@ -164,8 +164,7 @@ function clearResetTimer() {
}
function triggerVirtualEvent( eventType, event, flags ) {
- var defaultPrevented = false,
- ve;
+ var ve;
if ( ( flags && flags[ eventType ] ) ||
( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
@@ -173,18 +172,27 @@ function triggerVirtualEvent( eventType, event, flags ) {
ve = createVirtualEvent( event, eventType );
$( event.target).trigger( ve );
-
- defaultPrevented = ve.isDefaultPrevented();
}
- return defaultPrevented;
+ return ve;
}
function mouseEventCallback( event ) {
var touchID = $.data(event.target, touchTargetPropertyName);
if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){
- triggerVirtualEvent( "v" + event.type, event );
+ var ve = triggerVirtualEvent( "v" + event.type, event );
+ if ( ve ) {
+ if ( ve.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ if ( ve.isPropagationStopped() ) {
+ event.stopPropagation();
+ }
+ if ( ve.isImmediatePropagationStopped() ) {
+ event.stopImmediatePropagation();
+ }
+ }
}
}
@@ -264,7 +272,8 @@ function handleTouchEnd( event ) {
triggerVirtualEvent( "vmouseup", event, flags );
if ( !didScroll ) {
- if ( triggerVirtualEvent( "vclick", event, flags ) ) {
+ var ve = triggerVirtualEvent( "vclick", event, flags );
+ if ( ve && ve.isDefaultPrevented() ) {
// The target of the mouse events that follow the touchend
// event don't necessarily match the target used during the
// touch. This means we need to rely on coordinates for blocking
View
89 tests/unit/event/event_core.js
@@ -241,6 +241,95 @@
}, 40);
});
+ asyncTest( "tap event propagates up DOM tree", function(){
+ var tap = 0,
+ $qf = $( "#qunit-fixture" ),
+ $doc = $( document ),
+ docTapCB = function(){
+ same(++tap, 2, "document tap callback called once after #qunit-fixture callback");
+ };
+
+ $qf.bind( "tap", function() {
+ same(++tap, 1, "#qunit-fixture tap callback called once");
+ });
+
+ $doc.bind( "tap", docTapCB );
+
+ $qf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered twice, once for
+ // #qunit-fixture, and a second time for document.
+ same( tap, 2, "final tap callback count is 2" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
+ asyncTest( "stopPropagation() prevents tap from propagating up DOM tree", function(){
+ var tap = 0,
+ $qf = $( "#qunit-fixture" ),
+ $doc = $( document ),
+ docTapCB = function(){
+ ok(false, "tap should NOT be triggered on document");
+ };
+
+ $qf.bind( "tap", function(e) {
+ same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
+ e.stopPropagation();
+ })
+ .bind( "tap", function(e) {
+ same(++tap, 2, "tap callback 2 triggered once on #qunit-fixture");
+ });
+
+ $doc.bind( "tap", docTapCB);
+
+ $qf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered twice.
+ same( tap, 2, "final tap count is 2" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
+ asyncTest( "stopImmediatePropagation() prevents tap propagation and execution of 2nd handler", function(){
+ var tap = 0,
+ $cf = $( "#qunit-fixture" );
+ $doc = $( document ),
+ docTapCB = function(){
+ ok(false, "tap should NOT be triggered on document");
+ };
+
+ // Bind 2 tap callbacks on qunit-fixture. Only the first
+ // one should ever be called.
+ $cf.bind( "tap", function(e) {
+ same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
+ e.stopImmediatePropagation();
+ })
+ .bind( "tap", function(e) {
+ ok(false, "tap callback 2 should NOT be triggered on #qunit-fixture");
+ });
+
+ $doc.bind( "tap", docTapCB);
+
+ $cf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered once.
+ same( tap, 1, "final tap count is 1" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
var swipeTimedTest = function(opts){
var swipe = false;
Please sign in to comment.
Something went wrong with that request. Please try again.