I\'m working on a mobile web site that has to work on a variety of devices. The one\'s giving me a headache at the moment are BlackBerry.
We need to support both key
For simple features, just recognize touch or click I use the following code:
var element = $("#element");
element.click(function(e)
{
if(e.target.ontouchstart !== undefined)
{
console.log( "touch" );
return;
}
console.log( "no touch" );
});
This will return "touch" if the touchstart event is defined and "no touch" if not. Like I said this is a simple approach for click/tap events just that.
EDIT: My former answer (based on answers in this thread) was not the way to go for me. I wanted a sub-menu to expand on mouse enter or touch click and to collapse on mouse leave or another touch click. Since mouse events normally are being fired after touch events, it was kind of tricky to write event listeners that support both touchscreen and mouse input at the same time.
I ended up writing a jQuery plugin called "Touch Or Mouse" (897 bytes minified) that can detect whether an event was invoked by a touchscreen or mouse (without testing for touch support!). This enables the support of both touchscreen and mouse at the same time and completely separate their events.
This way the OP can use touchstart
or touchend
for quickly responding to touch clicks and click
for clicks invoked only by a mouse.
First one has to make ie. the body element track touch events:
$(document.body).touchOrMouse('init');
Mouse events our bound to elements in the default way and by calling $body.touchOrMouse('get', e)
we can find out whether the event was invoked by a touchscreen or mouse.
$('.link').click(function(e) {
var touchOrMouse = $(document.body).touchOrMouse('get', e);
if (touchOrMouse === 'touch') {
// Handle touch click.
}
else if (touchOrMouse === 'mouse') {
// Handle mouse click.
}
}
See the plugin at work at http://jsfiddle.net/lmeurs/uo4069nh.
touchstart
and touchend
events, this way the touchend
event does not have to be fired on the trigger element (ie. a link or button). Between these two touch events this plugin considers any mouse event to be invoked by touch.touchend
, when a mouse event is being fired within the ghostEventDelay
(option, 1000ms by default) after touchend
, this plugin considers the mouse event to be invoked by touch.:active
state. The mouseleave
event is only fired after the element loses this state by ie. clicking on another element. Since this could be seconds (or minutes!) after the mouseenter
event has been fired, this plugin keeps track of an element's last mouseenter
event: if the last mouseenter
event was invoked by touch, the following mouseleave
event is also considered to be invoked by touch.This is the fix that I "create" and it take out the GhostClick and implements the FastClick. Try on your own and let us know if it worked for you.
$(document).on('touchstart click', '.myBtn', function(event){
if(event.handled === false) return
event.stopPropagation();
event.preventDefault();
event.handled = true;
// Do your magic here
});
Just adding return false;
at the end of the on("click touchstart")
event function can solve this problem.
$(this).on("click touchstart", function() {
// Do things
return false;
});
From the jQuery documentation on .on()
Returning
false
from an event handler will automatically callevent.stopPropagation()
andevent.preventDefault()
. Afalse
value can also be passed for the handler as a shorthand forfunction(){ return false; }
.
This worked for me, mobile listens to both, so prevent the one, which is the touch event. desktop only listen to mouse.
$btnUp.bind('touchstart mousedown',function(e){
e.preventDefault();
if (e.type === 'touchstart') {
return;
}
var val = _step( _options.arrowStep );
_evt('Button', [val, true]);
});
I am also working on an Android/iPad web app, and it seems that if only using "touchmove" is enough to "move components" ( no need touchstart ). By disabling touchstart, you can use .click(); from jQuery. It's actually working because it hasn't be overloaded by touchstart.
Finally, you can binb .live("touchstart", function(e) { e.stopPropagation(); }); to ask the touchstart event to stop propagating, living room to click() to get triggered.
It worked for me.