I\'m using hammer.js and it appears that I event.stopPropagation()
doesn\'t work with tap event.
If I click on the child, the associated event is triggered
As mentioned in another comment, one would expect, as you did, that calling event.stopPropagation()
would be all that is require to stop the event from bubbling up to the parent.
Details: However, in Hammer.js this is not so. Hammer creates a new gesture state machine for each element on which you call $(el).hammer()
. So when a touch event is fired on the child by the browser it is processed first by the logic for child and then again by the logic on the parent. As such to stop the parent from getting the tap event you must prevent the parent's hammer state machine from getting the original touch event. Generally, calling event.stopPropagation()
will also stop the propagation of the original event. However, hammer.js's tap
event is fired on touchend
but the originalEvent
is the cached touchstart
event. As such, stopping propagation on the original event has no effect because the touchstart
event has long ago bubbled up through the DOM.
Solution? I believe this is a bug in hammer - submit a pull request that corrects the originalEvent
in the tap event. As others have suggested you could check the event's target, but that's always the parent element - another bug in my opinion. So instead check the event.originalEvent.target
. Here's a JS fiddle with this mediocre solution implemented: http://jsfiddle.net/HHRHR/
If you can't get this to work.. just call another method on the tap after verifying the needful (arguments.callee
is where I would start in such a case) , this would have the added benefits of letting other users hook the button also...
function myFn(a) { if(a) $(this).css('background', 'red'); else $(this).css('background', 'blue');}
$('#parent').hammer().bind('tap', function(e) {
//Check arguments.callee or other data in event and call myFn
});
$('#children').hammer().bind('tap', function(e) {
//Same here
});
You could try checking e.currentTarget
(or is it e.target
?) inside the parent handler to find out which element was tapped; if it's the child element then just return immediately, else continue with the function.
I had a similar problems with the touch events.
I solved it by using
return false;
which is the same as calling e.preventDefault(); e.stopPropagation();
As I couldn't get this work, I used a variable to know if the child event has already been triggered. It works quite well with jGestures (I have not tried with hammer.js)
var childTriggered = false;
$('#child').bind('tapone', function(e) {
$(this).css('background', 'red');
childTriggered = true;
});
$('#parent').bind('tapone', function(e) {
if(childTriggered) {
childTriggered = false;
return;
}
$(this).css('background', 'blue');
});