Ok, so you're setting the onclick
attribute. Now this works perfectly well on "traditional" platforms (that have a mouse-like device with buttons that can be used to click on objects). A touch device (clue is in the name) doesn't have this, instead it is operated by touching the screen. Allright, you knew that, so I take it you can understand that the touch
event is extremely overloaded (multi-touch).
Touching the screen for a second means something completely different than touching the screen for a split second. You can also touch the screen with 1, 2, 3 or 4 fingers. Each time this is to be processed differently.
To make things even more complex, you can drag or swipe accross the screen, which needs to be handled differently, too.
As luck would have it, I've recently written some code to map certain touch events to a click handler, using closures, binding listeners and setting timeouts all over the place. So this might help you on your way:
if ('ontouchstart' in window)
{//we have a touch device
document.body.addEventListener('touchstart',function(e)
{//handle all touch events on the body
e = e || window.event;
//not sure about all mobile browsers (win mobile)
//so I'm playing it safe
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() !== 'a')
{//didn't touch on a link
return e;//stop
}
//touch must end after .3 seconds, otherwise user is zooming or something
var timer = setTimeout(function()
{
target.removeEventListener('touchend',endHandler,false);//unbind after .3 seconds
clearTimeout(timer);
},300);
var endHandler = function(e)
{
e = e || window.event;
var endTarget = e.target || e.srcElement;//get element on which the touch ended
clearTimeout(timer);//stop timer
target.removeEventListener('touchend',endHandler,false);//remove listener
if (endTarget !== target)
{//user "swiped"
return e;
}
//touch ended within .3 seconds, and ended on the same element, interpret this as click
return clickHandlerFunction.apply(target,[e]);//invoke click handler with the target as context
};
target.addEventListener('touchend',endHandler,false);//bind touchend listener
},false);
}
What this does, basically, is register all touchstart events. The first thing that is being checked is did the user touch on an element of interest, one which I want to handle with my custom event handler. If not, the event is returned, nothing changes.
If the element touches is of interest, I create a listener for a touchend
event on that target. I also set a timeout, which will remove that listener after .3 seconds (to prevent leaks). If the touchend
event fires, check if the user was released on the original element, if not, interpret this as a swipe, and stop.
If the targets match, invoke the click handler, in the target's context and pass the event object! so you can invoke stopPropagation()
and/or preventDefault()
methods. The touchhandler
also kicks off by clearing the timer and removes itself, too (again: to prevent mem leaks).
As ever, this is a really, really basic snippet that can do with a lot more work
The touch events contain a lot more info (you can check how many fingers are touching the screen, for instance). I omitted a bit of my original code, too because that would have made it very complex and messy (and I don't have it here with me, and I can't really remember how I dealt with certain situations). I can tell you, however, that I tend to check the e.clientX
and e.clientY
coordinates, and if the touchend
event was within 50px of the touchstart
target I map it to the click handler anyway: to provide some soft focus for people who are cold and trembling ;) so even Inuit can browse the page.
Anyhow, see what works for you. A couple of useful links though:
Touch table
some history
some touch libs