Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
Fixes for issue 1464 - No way to stop a link from being followed with…
Browse files Browse the repository at this point in the history
… 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
jblas committed Sep 2, 2011
1 parent 0b41fe8 commit 7cce0c5
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 14 deletions.
16 changes: 9 additions & 7 deletions js/jquery.mobile.event.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}

Expand All @@ -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 );
});
}
Expand Down
23 changes: 16 additions & 7 deletions js/jquery.mobile.vmouse.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,27 +164,35 @@ function clearResetTimer() {
}

function triggerVirtualEvent( eventType, event, flags ) {
var defaultPrevented = false,
ve;
var ve;

if ( ( flags && flags[ eventType ] ) ||
( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {

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();
}
}
}
}

Expand Down Expand Up @@ -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
Expand Down
89 changes: 89 additions & 0 deletions tests/unit/event/event_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 7cce0c5

Please sign in to comment.