Preventing ghost click when binding 'touchstart' and 'click'
If you want to do specific stuff for different event types use e.type
$('.button').on('touchstart click', function(e) {
e.preventDefault(); //prevent default behavior
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
This code from @Krishna doesn't work for me:
$('.button').on('touchstart click', function(e) {
e.stopPropagation(); //stops propagation
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
But this one should work, as @Slashback originally suggested.
$('.button').on('touchstart click', function(e) {
e.preventDefault();
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
.preventDefault() alone worked for me instead of .stopPropagation(). I din't have to do the overkill as well.
Touchstart should happen before click, so I remove the click handler if the event is of type touchstart. This seems to be working nicely for my purposes:
$('.do-popdown').on('click touchstart', handlePopdown);
function handlePopdown(e){
if(e.type == 'touchstart') {
$('.do-popdown').off('click', handlePopdown).click(function(e){
// do nothing
e.stopPropagation();
e.preventDefault();
return false;
});
}
// do my handling...
// and nothing else:
e.stopPropagation();
e.preventDefault();
return false;
}
The e.stopPropagation(); e.preventDefault(); return false;
may be overkill, but I use this on a variety of different elements (<a>
, <div>
, <span>
, <button>
, &c.) and this meets my usual needs.
EDIT: A more general (better?) approach is to create something similar to the familiar .click()
event binder:
jQuery.fn.extend({
clickOrTouch: function(handler) {
return this.each(function() {
var event = ('ontouchstart' in document) ? 'touchstart' : 'click';
$(this).on(event, handler);
});
}
});
This way, only the appropriate event is attached to the selected element(s).
I suppose a more "proper" name would be .touchstartOrClick()
but since it is more or less a replacement for .click()
I decided to start the name with click
.
This can be used just like .click()
. For example, put a button
inside of a div
and run:
$('button').clickOrTouch(doSomething);
$('div').clickOrTouch(doSomething);
function doSomething(e) {
$('body').append(this.tagName + ' ' + e.type + '<br>');
e.stopPropagation();
}
This will show "DIV click" or "BUTTON touchstart" depending on how it is triggered. If this is used on a link, add e.preventDefault()
if needed in your handler.