iPad/iPhone hover problem causes the user to doubl

2020-01-24 18:41发布

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!

25条回答
Evening l夕情丶
2楼-- · 2020-01-24 19:21

What worked for me is what others here have already said:

Don't show/hide elements on hover or mousemove (which is the event in my case).

Here's what Apple says (https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html):

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:

$("body").on("mouseover", function() {
       document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
       document.querySelector(".my-selector div").style.display = 'none'; // hide element
});

This will work on the Desktop version and will do nothing on the mobile version.

And for a little more compatibility...

$("body").on("mouseover", function() {
   if (document.getElementsByTagName && document.querySelector) { // check compatibility
       document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
       document.querySelector(".my-selector div").style.display = 'none'; // hide element
    } else {
        $(".my-class").show();
        $(".my-selector div").hide();
    }
});
查看更多
唯我独甜
3楼-- · 2020-01-24 19:21

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).

Here was the general idea:

var device = navigator.userAgent.toLowerCase();
var ios = device.match(/(iphone|ipod|ipad)/);

if (!(ios)) {
    $(".portfolio-style").hover(
        function(){
            $(this).stop().animate({opacity: 1}, 100);
            $(this).addClass("portfolio-red-text");
        },
        function(){
            $(this).stop().animate({opacity: 0.85}, 100);
            $(this).removeClass("portfolio-red-text");
        }
    );
}

*code reduced for illustrative purposes

查看更多
一纸荒年 Trace。
4楼-- · 2020-01-24 19:21

You can use click touchend ,

example:

$('a').on('click touchend', function() {
    var linkToAffect = $(this);
    var linkToAffectHref = linkToAffect.attr('href');
    window.location = linkToAffectHref;
});

Above example will affect all links on touch devices.

If you want to target only specific links, you can do this by setting a class on them, ie:

HTML:

<a href="example.html" class="prevent-extra-click">Prevent extra click on touch device</a>

Jquery:

$('a.prevent-extra-click').on('click touchend', function() {
    var linkToAffect = $(this);
    var linkToAffectHref = linkToAffect.attr('href');
    window.location = linkToAffectHref;
});

Cheers,

Jeroen

查看更多
贪生不怕死
5楼-- · 2020-01-24 19:22

I had the same problem but not on a touch device. The event triggers every time you click. There is something about event queuing or so.

However, my solution was like this: On click event (or touch?) you set a timer. If the link is clicked again within X ms, you just return false.

To set per element timer, you can use $.data().

This also may fix the @Ferdy problem described above.

查看更多
Juvenile、少年°
6楼-- · 2020-01-24 19:22

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

Test this code on an ipad to see how css and js hover method behave differently (in hover effect only). The CSS button doesn't have a fancy click alert. http://jsfiddle.net/bensontrent/ctgr6stm/

function clicker(id, doStuff) {
  id.on('touchstart', function(e) {
    id.addClass('hover');
  }).on('touchmove', function(e) {
    id.removeClass('hover');
  }).mouseenter(function(e) {
    id.addClass('hover');
  }).mouseleave(function(e) {
    id.removeClass('hover');
  }).click(function(e) {
    id.removeClass('hover');
    //It's clicked. Do Something
    doStuff(id);
  });
}

function doStuff(id) {
  //Do Stuff
  $('#clicked-alert').fadeIn(function() {
    $(this).fadeOut();
  });
}
clicker($('#unique-id'), doStuff);
button {
  display: block;
  margin: 20px;
  padding: 10px;
  -webkit-appearance: none;
  touch-action: manipulation;
}
.hover {
  background: yellow;
}
.btn:active {
  background: red;
}
.cssonly:hover {
  background: yellow;
}
.cssonly:active {
  background: red;
}
#clicked-alert {
  display: none;
}
<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

查看更多
在下西门庆
7楼-- · 2020-01-24 19:23

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:

// mouseenter event
$('.element').on( "mouseenter", function() {
    // insert mouseenter events below

    // double click fix for iOS and mouseenter events
    if ($.browser.iphone || $.browser.ipad) $(this).trigger('click');
});
// mouseleave event
$('.element').on( "mouseleave", function() { 
    // insert mouseout events below
});
// onclick event
$('.element').on( "click", function() {
    // insert click events below
});

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.

You can get the jQuery $.browser plugin here: https://github.com/gabceb/jquery-browser-plugin

查看更多
登录 后发表回答