I have some websites I built times ago, that use jquery mouse events...I just got an ipad and i noticed that all the mouse over events are translated in clicks...so for instance i have to do two clicks instead of one..(the first hover, than the actual click)

is there a workaround ready to solve this? maybe a jquery command i shoudl have used instead of mouseover/out etc..
thanks!

what are your events bound to? e.g. onclick events should work fine... onmouseover, onmouseout and the CSS :hover are the ones that are a bit hard to handle since there is no "hover" available to a touch screen. Do you have a code sample?
– scunliffeJun 14 '10 at 16:25

One thing I would suggest you do is to rethink your interface if at all possible. interaction on the ipad/iphone doesn't exactly mirror that of on a pc, and it's probably a wise thing to make your website feel like it was written for the ipad/iphone/other touch devices with similar multitouch mechanisms. Just a thought.
– jerJun 14 '10 at 16:33

I agree with "jer". This is an odd question, I don't think the solution here is a "workaround" personally. I think translating a "mouse hover" on a desktop browser to a "finger tap" on a touchscreen browser makes sense. If you agree with that translation, but want one tap instead of two, then I'd probably do feature detection for the iPad events (e.g. "touchstart") and change your event handlers. Maybe extract your code into a jquery plugin "touch or click" kind of functionality that fires differently based on features, but seems specific to your website/app to me.
– Andy AtkinsonAug 6 '10 at 17:46

1

I actually consider this translation to be a feature. If you had hover events setup, there must have been some utility to seeing them. A single tap reveals a hovered element, a second tap follows the link "behind" the hover.
– AaronAug 9 '10 at 20:56

It is not entirely clear what your question is, but if you just want to eliminate the double click, while retaining the hover effect for the mouse, my advice is to:

Add hover effects on touchstart and mouseenter.

Remove hover effects on mouseleave, touchmove and click.

Background

In order to simulate a mouse, browsers such as Webkit mobile fire the following events if a user touches and releases a finger on touch screen (like iPad) (source: Touch And Mouse on html5rocks.com):

touchstart

touchmove

touchend

300ms delay, where the browser makes sure this is a single tap, not a double tap

mouseover

mouseenter

Note: If a mouseover, mouseenter or mousemove event changes the page content, the following events are never fired.

mousemove

mousedown

mouseup

click

It does not seem possible to simply tell the webbrowser to skip the mouse events.

What's worse, if a mouseover event changes the page content, the click event is never fired, as explained on Safari Web Content Guide - Handling Events, in particular figure 6.4 in One-Finger Events. What exactly a "content change" is, will depend on browser and version. I've found that for iOS 7.0, a change in background color is not (or no longer?) a content change.

Solution Explained

To recap:

Add hover effects on touchstart and mouseenter.

Remove hover effects on mouseleave, touchmove and click.

Note that there is no action on touchend!

This clearly works for mouse events: mouseenter and mouseleave (slightly improved versions of mouseover and mouseout) are fired, and add and remove the hover.

If the user actually clicks a link, the hover effect is also removed. This ensure that it is removed if the user presses the back button in the web browser.

This also works for touch events: on touchstart the hover effect is added. It is '''not''' removed on touchend. It is added again on mouseenter, and since this causes no content changes (it was already added), the click event is also fired, and the link is followed without the need for the user to click again!

The 300ms delay that a browser has between a touchstart event and click is actually put in good use because the hover effect will be shown during this short time.

If the user decides to cancel the click, a move of the finger will do so just as normal. Normally, this is a problem since no mouseleave event is fired, and the hover effect remains in place. Thankfully, this can easily be fixed by removing the hover effect on touchmove.

That's it!

Note that it is possible to remove the 300ms delay, for example using the FastClick library, but this is out of scope for this question.

Alternative Solutions

I've found the following problems with the following alternatives:

browser detection: Extremely prone to errors. Assumes that a device has either mouse or touch, while a combination of both will become more and more common when touch displays prolifirate.

CSS media detection: The only CSS-only solution I'm aware of. Still prone to errors, and still assumes that a device has either mouse or touch, while both are possible.

Emulate the click event in touchend: This will incorrectly follow the link, even if the user only wanted to scroll or zoom, without the intention of actually clicking the link.

Use a variable to suppress mouse events: This set a variable in touchend that is used as a if-condition in subsequent mouse events to prevents state changes at that point in time. The variable is reset in the click event. This is a decent solution if you really don't want a hover effect on touch interfaces. Unfortunately, this does not work if a touchend is fired for another reason and no click event is fired (e.g. the user scrolled or zoomed), and is subsequently trying to following the link with a mouse (i.e on a device with both mouse and touch interface).

Seems there is a CSS solution after all. The reason Safari waits for a second touch is because of the background image (or elements) you usually assign on the :hover event. If there is none to be shown - you won't have any problems. The solution is to target iOS platform with secondary CSS file (or style in case of a JS approach) which overrides :hover background to inherit for example and keep hidden the elements you were going to display on mouse over:

Here is an example CSS and HTML - a product block with a starred label on mouse over:

A clickable element is a link, form element, image map area, or any other element with mousemove, mousedown, mouseup, or onclick handlers

If the user taps a clickable element, events arrive in this order: mouseover, mousemove, mousedown, mouseup, and click. Also, if the contents of the page changes on the mousemove event, no subsequent events in the sequence are sent. This behavior allows the user to tap in the new content.

So, you could use @woop's solution: detect the userAgent, check if it's and iOS device and then bind the event. I ended up using this technique because it suits my needs and it makes more sense do not bind hover events when you don't want it.

But... if you don't wanna mess with userAgents and still hide/show elements on hover/mousemove, i found out you can do so by using native javascript, like this:

That bit "if the contents of the page changes on the mousemove event, no subsequent events in the sequence are sent" really did it for me. I had a page where header links would require a double tap where buttons in the content (with all out happy css3 transitions on em) would just require a single tap. Appeared that the header links had a pseudo-element that went from opacity: 0 to opacity: 1 on hover. Removing that effect immediately solved the issue and I found a CSS workaround to still get the looks I wanted.
– Fake HaakMar 27 '15 at 7:52

cduruk's solution was quite effective, but caused problems on a few parts of my site. Because I was already using jQuery to add the CSS hover class, the easiest solution was to simply not add the CSS hover class on mobile devices (or more precisely, to ONLY add it when NOT on a mobile device).

This is clearly the answer. The other "solutions" do not fix the issue. iOS safari is clearly flawed into thinking that we want hover first. Other OS's have actual hover features to when you hover over an item.
– Joshua PackAug 28 '15 at 12:27

This was the only thing that worked for me. Thank you so much!
– bjorklandOct 8 '16 at 16:26

I had the following problems with the existing solutions, and found something that seems to solve all of them. This assumes you're aiming for something cross browser, cross device, and don't want device sniffing.

The problems this solves

Using just touchstart or touchend:

Causes the event to fire when people are trying to scroll past the content and just happened to have their finger over this element when they starting swiping - triggering the action unexpectedly.

May cause the event to fire on longpress, similar to right click on desktop. For example, if your click event goes to URL X, and the user longpresses to open X in a new tab, the user will be confused to find X open in both tabs. On some browsers (e.g. iPhone) it may even prevent the long press menu from appearing.

Triggering mouseover events on touchstart and mouseout on touchmove has less serious consequences, but does interfere with the usual browser behaviour, for example:

A long press would trigger a mouseover that never ends.

Many Android browsers treat the location of the finger on touchstart like a mouseover, which is mouseouted on the next touchstart. One way to see mouseover content in Android is therefore to touch the area of interest and wiggle your finger, scrolling the page slightly. Treating touchmove as mouseout breaks this.

The solution

In theory, you could just add a flag with touchmove, but iPhones trigger touchmove even if there's no movement. In theory, you could just compare the touchstart and touchend event pageX and pageYbut on iPhones, there's no touchendpageX or pageY.

So unfortunately to cover all bases it does end up a little more complicated.

MacFreak's answer was extremely helpful to me. Here's some hands-on code in case it helps you.

PROBLEM - applying touchend means every time you scroll your finger over an element, it responds as if you've pressed it, even if you were just trying to scroll past.

I'm creating an effect with jQuery which fades up a line under some buttons to "highlight" the hovered button. I do not want this to mean you have to press the button twice on touch devices to follow the link.

I ran into a similar situation where I had events binded to the mouseenter/mouseleave/click states of an element, yet on an iPhone, the user had to double click the element to first trigger the mouseenter event, then again to fire the click event.

I resolved this using a similar method as above, but I made use of the jQuery $.browser plugin (for jQuery 1.9>) and added a .trigger event to the mouseenter binding event, as follows:

The .trigger prevents the need to double click the element by firing the .click event handler upon mouseenter (or initial click) of the element when viewed on iPhones or iPads. Might not be the most elegant solution, but it works great in my case and utilizes a plugin that I already had in place, and required me to add a single line of code to get my existing events working under these devices.

With inspiration from MacFreak, I put together something that works for me.

This js method prevents hover from sticking on an ipad, and prevents the click registering as two clicks in some cases. In CSS, if you have any :hover psudo classes in your css, change them to .hover For example .some-class:hover to .some-class.hover

<button id="unique-id" class="btn">JS Hover for Mobile devices<span id="clicked-alert"> Clicked</span>
</button>
<button class="cssonly">CSS Only Button</button>
<br>This js method prevents hover from sticking on an ipad, and prevents the click registering as two clicks. In CSS, if you have any :hover in your css, change them to .hover For example .some-class:hover to .some-class.hover

but you would have to check for blackberries, droids, umpty other touchscreen devices. You could also bind the mouseovers only if the userAgent contains Mozilla, IE, Webkit, or Opera, but you still need to screen for some devices because the Droid, for instance, reports its userAgent string as:

I think, for now, in order not to get crazy , the best thing to do could be just a script that skips the hover events..so i guess the first answer was good...and yes you are right..i should think about all the other devices...i wish Jquery or some plugin had this kind of dection feature..!
– FrancescoJun 15 '10 at 14:42

wurfl.sourceforge.net This might be your answer. Its a database of wireless devices. Won't be as straightforward as a jQuery plugin would be, but you can always write one! There's also tera-wurfl.com which uses a databse rather than an xml file. Haven't done much digging but there might be a hosted version out there so you don't have to worry about keeping your wurfl file or tera-wurfl database up to date.
– jasongetsdownJun 15 '10 at 15:56

1

Am I missing something or was the question NOT about detecting iPads, but about working around a specific behavior on iPads?
– Andrew HedgesAug 6 '10 at 17:01