iPad/iPhone hover problem causes the user to double click a link

后端 未结 26 1573
太阳男子
太阳男子 2020-11-27 09:18

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 inst

相关标签:
26条回答
  • 2020-11-27 09:32

    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.

    0 讨论(0)
  • 2020-11-27 09:32

    None from the other answer works for me. My app has a lot of event listeners, own checkboxes and links that has listener's and links without listener's.

    I use this:

    var selector = "label, a, button";
    var timer;
    var startX;
    var startY;
    $(document).on("click", selector, function (e) {
        if ($(this).data("touched") === true) {
            e.stopImmediatePropagation();
            return false;
        }
        return;
    }).on("touchend", selector, function (e) {
        if (Math.abs(startX - e.originalEvent.changedTouches[0].screenX) > 10 || Math.abs(startY - e.originalEvent.changedTouches[0].screenY) > 10)
            // user action is not a tap
            return;
        var $this = $(this);
        // Visit: http://stackoverflow.com/questions/1694595/can-i-call-jquery-click-to-follow-an-a-link-if-i-havent-bound-an-event-hand/12801548#12801548
        this.click();
        // prevents double click
        $this.data("touched", true);
        if (timer)
            clearTimeout(timer);
        setTimeout(function () {
            $this.data("touched", false);
        }, 400);
        e.stopImmediatePropagation();
        return false;
    }).on("touchstart", function (e) {
        startX = e.originalEvent.changedTouches[0].screenX;
        startY = e.originalEvent.changedTouches[0].screenY;
    });
    
    0 讨论(0)
  • 2020-11-27 09:32

    Simplest way to resolve double-click on IPad is wrapping your css for hover effect in media query @media (pointer: fine):

    @media (pointer: fine) {
      a span {
        display: none;
      }
      a:hover span {
        display: inline-block;
      }
    }
    

    CSS that wrapped in this media query will applying only on desktop.

    Explanation of this solution is here https://css-tricks.com/annoying-mobile-double-tap-link-issue/

    0 讨论(0)
  • 2020-11-27 09:33

    I am too late, I know but this is one of the easiest workaround I've found:

        $('body').on('touchstart','*',function(){   //listen to touch
            var jQueryElement=$(this);  
            var element = jQueryElement.get(0); // find tapped HTML element
            if(!element.click){
                var eventObj = document.createEvent('MouseEvents');
                eventObj.initEvent('click',true,true);
                element.dispatchEvent(eventObj);
            }
        });
    

    This does not only works for links(anchor tags) but for other elements also. Hope this helps.

    0 讨论(0)
  • 2020-11-27 09:35

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

    1. touchstart
    2. touchmove
    3. touchend
    4. 300ms delay, where the browser makes sure this is a single tap, not a double tap
    5. mouseover
    6. mouseenter
      • Note: If a mouseover, mouseenter or mousemove event changes the page content, the following events are never fired.
    7. mousemove
    8. mousedown
    9. mouseup
    10. 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).

    Further Reading

    • http://jsfiddle.net/macfreek/24Z5M/. Test the above solution for yourself in this sandbox.
    • http://www.macfreek.nl/memory/Touch_and_mouse_with_hover_effects_in_a_web_browser. This same answer, with a bit more background.
    • http://www.html5rocks.com/en/mobile/touchandmouse/. Great background article on html5rocks.com about touch and mouse in general.
    • https://developer.apple.com/library/ios/DOCUMENTATION/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html. Safari Web Content Guide - Handling Events. See in particular figure 6.4, which explains that no further events are fired after a content change during a mouseover or mousemove event.

    See also iPad/iPhone double click problem and Disable hover effects on mobile browsers.

    0 讨论(0)
  • 2020-11-27 09:35

    This works for me when you have jquery ui dropdown

    if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
          $('.ui-autocomplete').off('menufocus hover mouseover');
    }
    
    0 讨论(0)
提交回复
热议问题