iPad/iPhone 悬停问题导致用户双击链接

发布于 2024-09-05 18:59:50 字数 174 浏览 4 评论 0 原文

我有一些我以前建立的网站,使用 jquery 鼠标事件...我刚买了一个 ipad,我注意到所有鼠标悬停事件都被转换为单击...所以例如我必须执行两次单击而不是一次单击..(第一次悬停,而不是实际点击)

是否有解决方法可以解决这个问题?也许我应该使用 jquery 命令而不是 mouseover/out 等。 谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(27

-柠檬树下少年和吉他 2024-09-12 19:00:42

只需进行一个排除平板电脑和移动设备的 CSS 媒体查询,然后将鼠标悬停在其中即可。为此,您实际上并不需要 jQuery 或 JavaScript。

@media screen and (min-device-width:1024px) {
    your-element:hover {
        /* Do whatever here */
    }
}

请务必将其添加到您的 html 头部,以确保它使用实际像素而不是分辨率进行计算。

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />

Simply make a CSS media query which excludes tablets and mobile devices and put the hover in there. You don't really need jQuery or JavaScript for this.

@media screen and (min-device-width:1024px) {
    your-element:hover {
        /* Do whatever here */
    }
}

And be sure to add this to your html head to make sure that it calculates with the actual pixels and not the resolution.

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
花开雨落又逢春i 2024-09-12 19:00:40

您可以像这样检查navigator.userAgent

if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
    //bind your mouseovers...
}

但是您必须检查黑莓,机器人,以及其他触摸屏设备。仅当 userAgent 包含 Mozilla、IE、Webkit 或 Opera 时,您也可以绑定鼠标悬停,但您仍然需要筛选某些设备,因为例如 Droid 将其 userAgent 字符串报告为:

Mozilla/5.0 (Linux; U; Android 2.0.1; en-us; Droid Build/ESD56) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

iPhone 的字符串类似。如果您只筛选 iPhone、iPod、iPad、Android 和 Blackberry,您可能会获得大多数手持设备,但不是全部。

You could check navigator.userAgent like this:

if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
    //bind your mouseovers...
}

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:

Mozilla/5.0 (Linux; U; Android 2.0.1; en-us; Droid Build/ESD56) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

The iPhone's string is similar. If you just screen for iPhone, iPod, iPad, Android and Blackberry you might get the majority of handhelds, but not all of them.

清晨说晚安 2024-09-12 19:00:39

解决 iPad 上双击问题的最简单方法是将您的 css 包装在媒体查询中以实现悬停效果 @media (pointer:fine)

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

包装在此媒体查询中的 CSS 仅适用于桌面。

此解决方案的说明位于此处 https://css-tricks.com /烦人的移动双击链接问题/

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/

白昼 2024-09-12 19:00:39

感谢 MacFreek 的回答 我想出了这个解决方案。当我发现有时连续有两个 mousemove 事件但未触发 click 事件时,它变得更高级了。

双鼠标移动

(function () {
    //https://stackoverflow.com/a/42162450/3717718
    function isIosSafari() {
        var ua = (window.navigator && navigator.userAgent) || '';
        var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
        var webkit = !!ua.match(/WebKit/i);
        var iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
        return iOSSafari;
    }
    (function removeHoverIosSafari() {
        if (!isIosSafari()) return;

        // Tags of interest
        function shouldPrevent(target) {
            var tagName = target.tagName.toLowerCase();
            var datasetBind = target.dataset.bind;
            var preventFilter = (datasetBind && datasetBind.indexOf('click') > -1) || (tagName == 'a' || tagName == 'button');
            return preventFilter;
        }
        var eventSelector = {
            touchend: function (_, target) {
                // Reset on touchend
                target.dataset._clicked_ = '';
                target.dataset._mousemove_ = '0';
                target.dataset._timeOutId_ = '';
            },
            mouseover: function (e) {
                e.preventDefault();
            },
            mousemove: function (e, target) {
                e.preventDefault();

                var _mousemoves = +(target.dataset._mousemove_ || '0');
                _mousemoves = _mousemoves + 1;
                console.log('mousemoves: ' + _mousemoves);
                target.dataset._mousemove_ = _mousemoves;
                if (_mousemoves > 1 && !target.dataset._timeOutId_) {
                    var id = setTimeout(function () {
                        console.log('double mousemove click fired');
                        target.click();
                    }, 80); // 80ms worked for me, could probably be lower
                    target.dataset._timeOutId_ = id;
                }
            },
            click: function (e, target) {
                if (target.dataset._clicked_) {
                    console.log('prevented doubleclick');
                    e.preventDefault();
                    return;
                }
                // prevent timeout click
                if (target.dataset._timeOutId_) {
                    console.log('cleared timeout');
                    clearTimeout(+target.dataset._timeOutId_);
                }
                // mark element as clicked
                target.dataset._clicked_ = 'true';
            }
        }
        function preventHover(e) {
            var target = e.target;
            //There is no point in continuing if the item for unknown reasons doesnt't have a clickFunction, tagName or dataset (DOMStringMap)
            if (!(target && target.click && target.tagName && target.dataset)) return;
            if (!shouldPrevent(target)) return;
            var type = e.type;
            console.log(type, target);
            eventSelector[type] && eventSelector[type](e, target);
        }

        document.addEventListener('touchend', preventHover, true);
        document.addEventListener('mouseover', preventHover, true);
        document.addEventListener('mousemove', preventHover, true);
        document.addEventListener('click', preventHover, true);
    })();
})();

Thanks to MacFreek's answer I came up with this solution. It became a bit more advanced when I discovered that sometimes there were two mousemove events in a row where the click event was not fired.

double mousemove

(function () {
    //https://stackoverflow.com/a/42162450/3717718
    function isIosSafari() {
        var ua = (window.navigator && navigator.userAgent) || '';
        var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
        var webkit = !!ua.match(/WebKit/i);
        var iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
        return iOSSafari;
    }
    (function removeHoverIosSafari() {
        if (!isIosSafari()) return;

        // Tags of interest
        function shouldPrevent(target) {
            var tagName = target.tagName.toLowerCase();
            var datasetBind = target.dataset.bind;
            var preventFilter = (datasetBind && datasetBind.indexOf('click') > -1) || (tagName == 'a' || tagName == 'button');
            return preventFilter;
        }
        var eventSelector = {
            touchend: function (_, target) {
                // Reset on touchend
                target.dataset._clicked_ = '';
                target.dataset._mousemove_ = '0';
                target.dataset._timeOutId_ = '';
            },
            mouseover: function (e) {
                e.preventDefault();
            },
            mousemove: function (e, target) {
                e.preventDefault();

                var _mousemoves = +(target.dataset._mousemove_ || '0');
                _mousemoves = _mousemoves + 1;
                console.log('mousemoves: ' + _mousemoves);
                target.dataset._mousemove_ = _mousemoves;
                if (_mousemoves > 1 && !target.dataset._timeOutId_) {
                    var id = setTimeout(function () {
                        console.log('double mousemove click fired');
                        target.click();
                    }, 80); // 80ms worked for me, could probably be lower
                    target.dataset._timeOutId_ = id;
                }
            },
            click: function (e, target) {
                if (target.dataset._clicked_) {
                    console.log('prevented doubleclick');
                    e.preventDefault();
                    return;
                }
                // prevent timeout click
                if (target.dataset._timeOutId_) {
                    console.log('cleared timeout');
                    clearTimeout(+target.dataset._timeOutId_);
                }
                // mark element as clicked
                target.dataset._clicked_ = 'true';
            }
        }
        function preventHover(e) {
            var target = e.target;
            //There is no point in continuing if the item for unknown reasons doesnt't have a clickFunction, tagName or dataset (DOMStringMap)
            if (!(target && target.click && target.tagName && target.dataset)) return;
            if (!shouldPrevent(target)) return;
            var type = e.type;
            console.log(type, target);
            eventSelector[type] && eventSelector[type](e, target);
        }

        document.addEventListener('touchend', preventHover, true);
        document.addEventListener('mouseover', preventHover, true);
        document.addEventListener('mousemove', preventHover, true);
        document.addEventListener('click', preventHover, true);
    })();
})();
两相知 2024-09-12 19:00:38

避免更改悬停 CSS 事件内的“显示”样式。我的“显示:阻止”处于悬停状态。删除 ios 后,单击即可进入 lins。顺便说一句,最新的 IOS 更新似乎修复了这个“功能”

Avoid changing of "display" style inside of hover css event. I had "display: block" in hover state. After removing ios went on lins by single tap. By the way it seems that latest IOS updates fixed this "feature"

蓝海 2024-09-12 19:00:37

当你有 jquery ui 下拉菜单时,这对我有用

if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
      $('.ui-autocomplete').off('menufocus hover mouseover');
}

This works for me when you have jquery ui dropdown

if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
      $('.ui-autocomplete').off('menufocus hover mouseover');
}
甲如呢乙后呢 2024-09-12 19:00:35

其他答案都不适合我。我的应用程序有很多事件侦听器、自己的复选框和具有侦听器的链接以及没有侦听器的链接。

我用这个:

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;
});

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;
});
单挑你×的.吻 2024-09-12 19:00:34

这个简短的片段似乎有效。
点击链接时触发点击事件:

  $('a').on('touchstart', function() {
    $(this).trigger('click');
  });

This short snippet seems to work.
Trigger the click event when link tapped :

  $('a').on('touchstart', function() {
    $(this).trigger('click');
  });
傲鸠 2024-09-12 19:00:33

我知道我太晚了,但这是我发现的最简单的解决方法之一:

    $('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);
        }
    });

这不仅适用于链接(锚标记),而且也适用于其他元素。希望这有帮助。

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.

鞋纸虽美,但不合脚ㄋ〞 2024-09-12 19:00:32

为了让链接在不中断触摸滚动的情况下工作,我使用 jQuery Mobile 的“tap”事件解决了这个问题:

    $('a').not('nav.navbar a').on("tap", function () {
        var link = $(this).attr('href');
        if (typeof link !== 'undefined') {
            window.location = link;
        }
    });

To get the links working without breaking touch scrolling, I solved this with jQuery Mobile's "tap" event:

    $('a').not('nav.navbar a').on("tap", function () {
        var link = $(this).attr('href');
        if (typeof link !== 'undefined') {
            window.location = link;
        }
    });
屋顶上的小猫咪 2024-09-12 19:00:31

受到 MacFreak 的启发,我整合了一些适合我的东西。

此 js 方法可防止悬停在 ipad 上,并防止在某些情况下将单击注册为两次单击。在 CSS 中,如果 css 中有任何 :hover psudo 类,请将它们更改为 .hover 例如 .some-class:hover 更改为 .some-class.hover

在 ipad 上测试此代码以查看 css 和 js 悬停方法的行为不同(仅在悬停效果中)。 CSS 按钮没有精美的点击警报。
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

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

尾戒 2024-09-12 19:00:30

只是一项改进,以避免当您错误地在链接上滑动手指时避免重定向。

// tablet "one touch (click)" X "hover" > link redirection
$('a').on('touchmove touchend', function(e) {

    // if touchmove>touchend, set the data() for this element to true. then leave touchmove & let touchend fail(data=true) redirection
    if (e.type == 'touchmove') {
        $.data(this, "touchmove_cancel_redirection", true );
        return;
    }

    // if it's a simple touchend, data() for this element doesn't exist.
    if (e.type == 'touchend' && !$.data(this, "touchmove_cancel_redirection")) {
        var el = $(this);
        var link = el.attr('href');
        window.location = link;
    }

    // if touchmove>touchend, to be redirected on a future simple touchend for this element
    $.data(this, "touchmove_cancel_redirection", false );
});

Just an improvement to avoid redirection when you slide your finger on a link by mistake.

// tablet "one touch (click)" X "hover" > link redirection
$('a').on('touchmove touchend', function(e) {

    // if touchmove>touchend, set the data() for this element to true. then leave touchmove & let touchend fail(data=true) redirection
    if (e.type == 'touchmove') {
        $.data(this, "touchmove_cancel_redirection", true );
        return;
    }

    // if it's a simple touchend, data() for this element doesn't exist.
    if (e.type == 'touchend' && !$.data(this, "touchmove_cancel_redirection")) {
        var el = $(this);
        var link = el.attr('href');
        window.location = link;
    }

    // if touchmove>touchend, to be redirected on a future simple touchend for this element
    $.data(this, "touchmove_cancel_redirection", false );
});
断爱 2024-09-12 19:00:28

我遇到了类似的情况,我将事件绑定到元素的 mouseenter/mouseleave/click 状态,但在 iPhone 上,用户必须双击该元素才能首先触发 mouseenter 事件,然后再次触发 click 事件。

我使用与上面类似的方法解决了这个问题,但我使用了 jQuery $.browser 插件(对于 jQuery 1.9>),并向 mouseenter 绑定事件添加了 .trigger 事件,如下所示

// 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
});

:在 iPhone 或 iPad 上查看时,通过在元素的 mouseenter(或初始单击)上触发 .click 事件处理程序来双击该元素。可能不是最优雅的解决方案,但它在我的情况下效果很好,并且利用了我已经安装的插件,并且要求我添加一行代码以使我的现有事件在这些设备下工作。

您可以在此处获取 jQuery $.browser 插件: https://github.com/gabceb/jquery-浏览器插件

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

万水千山粽是情ミ 2024-09-12 19:00:26

您可以使用 click touchend

示例:

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

上面的示例将影响触摸设备上的所有链接。

如果您只想定位特定链接,可以通过在它们上设置一个类来实现,即:

HTML:

防止触摸设备上的额外点击

Jquery:

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

干杯,

Jeroen

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

零度° 2024-09-12 19:00:23

如果您使用 Modernizr,那么使用前面提到的 Modernizr.touch 就非常容易。

然而,为了安全起见,我更喜欢结合使用 Modernizr.touch 和用户代理测试。

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

function Tipsy(element, options) {
    this.$element = $(element);
    this.options = options;
    this.enabled = !isTouchDevice;
    this.fixTitle();
};

如果您不使用 Modernizr,则只需将上面的 Modernizr.touch 函数替换为 ('ontouchstart' in document.documentElement)

另请注意,测试用户代理 iemobile将为您提供比 Windows Phone 更广泛的检测到的 Microsoft 移动设备。

If you use Modernizr, it is very easy to use Modernizr.touch as mentioned earlier.

However, I prefer using a combination of Modernizr.touch and user agent testing, just to be safe.

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

function Tipsy(element, options) {
    this.$element = $(element);
    this.options = options;
    this.enabled = !isTouchDevice;
    this.fixTitle();
};

If you don't use Modernizr, you can simply replace the Modernizr.touch function above with ('ontouchstart' in document.documentElement)

Also note that testing the user agent iemobile will give you broader range of detected Microsoft mobile devices than Windows Phone.

独行侠 2024-09-12 19:00:19

我遇到了同样的问题,但不是在触摸设备上。每次单击时都会触发该事件。有一些关于事件队列之类的事情。

然而,我的解决方案是这样的:
在单击事件(或触摸?)上设置一个计时器。如果在 X 毫秒内再次点击该链接,则返回 false。

要设置每个元素计时器,您可以使用$.data()

这也可以解决上面描述的@Ferdy 问题。

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.

鸠魁 2024-09-12 19:00:17

我“认为”您的链接没有 onmouseover 事件,其中 1 个点击激活 onmouseover ,双击激活链接。但我不知道。我没有 iPad。
我认为你必须使用手势/触摸事件。

https://developer.apple.com/documentation/webkitjs

I "think" that your links have no onmouseover event, where 1 tap activates onmouseover and the double tap activates the link. but idk. I don't have an iPad.
I think ya gotta use gesture/touch events.

https://developer.apple.com/documentation/webkitjs

画尸师 2024-09-12 19:00:12

我刚刚发现如果你添加一个空监听器它就可以工作,不要问我为什么,但我在装有 iOS 9.3.2 的 iPhone 和 iPad 上测试了它,它工作得很好。

if(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){
    var elements = document.getElementsByTagName('a');
    for(var i = 0; i < elements.length; i++){
        elements[i].addEventListener('touchend',function(){});
    }
}

I just found out that it works if you add an empty listener, don't ask me why, but I tested it on iPhone and iPad with iOS 9.3.2 and it worked fine.

if(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){
    var elements = document.getElementsByTagName('a');
    for(var i = 0; i < elements.length; i++){
        elements[i].addEventListener('touchend',function(){});
    }
}
今天小雨转甜 2024-09-12 19:00:11

MacFreak 的回答对我非常有帮助。这里有一些实践代码,希望对您有帮助。

问题 - 应用touchend意味着每次您在某个元素上滚动手指时,它都会做出响应,就像您按下了它一样,即使您只是想滚动过去。

我正在使用 jQuery 创建一个效果,它会在某些按钮下淡出一条线以“突出显示”悬停的按钮。我不希望这意味着您必须在触摸设备上按两次按钮才能点击链接。

以下是按钮:

<a class="menu_button" href="#">
    <div class="menu_underline"></div>
</a>

我希望“menu_underline”div 在鼠标悬停时淡出并在鼠标移出时淡出。但我希望触摸设备能够通过单击而不是两次单击来跟踪链接。

解决方案 - 这是使其工作的 jQuery:

//Mouse Enter
$('.menu_button').bind('touchstart mouseenter', function(){
    $(this).find(".menu_underline").fadeIn();
});

//Mouse Out   
$('.menu_button').bind('mouseleave touchmove click', function(){
    $(this).find(".menu_underline").fadeOut();
});

非常感谢您对此 MacFreak 的帮助。

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.

Here are the buttons:

<a class="menu_button" href="#">
    <div class="menu_underline"></div>
</a>

I want the "menu_underline" div to fade up on mouseover and fade out on mouseout. BUT I want touch devices to be able to follow the link on one single click, not two.

SOLUTION - Here's the jQuery to make it work:

//Mouse Enter
$('.menu_button').bind('touchstart mouseenter', function(){
    $(this).find(".menu_underline").fadeIn();
});

//Mouse Out   
$('.menu_button').bind('mouseleave touchmove click', function(){
    $(this).find(".menu_underline").fadeOut();
});

Many thanks for your help on this MacFreak.

淤浪 2024-09-12 19:00:09

我在现有的解决方案中遇到了以下问题,并找到了似乎可以解决所有问题的方法。这假设您的目标是跨浏览器、跨设备,并且不希望设备嗅探。

此解决的问题

仅使用 touchstarttouchend

  • 当人们尝试滚动内容并且碰巧滚动时,导致事件触发当他们开始滑动时,他们的手指放在这个元素上 - 意外地触发了该操作。
  • 可能会导致长按触发事件,类似于在桌面上单击鼠标右键。例如,如果您的点击事件转到 URL X,并且用户长按以在新选项卡中打开 X,则用户会很困惑地发现 X 在两个选项卡中都打开了。在某些浏览器(例如 iPhone)上,它甚至可能会阻止长按菜单的出现。

touchstart 上触发 mouseover 事件和在 touchmove 上触发 mouseout 的后果不太严重,但会干扰通常的浏览器行为,例如:

  • 长按会触发永远不会结束的鼠标悬停。
  • 许多 Android 浏览器将 touchstart 上手指的位置视为 mouseover,在下一个 touchstart 时进行mouseout >。因此,在 Android 中查看鼠标悬停内容的一种方法是触摸感兴趣的区域并摆动手指,轻轻滚动页面。将 touchmove 视为 mouseout 会打破这一点。

解决方案

理论上,您只需使用 touchmove 添加一个标志即可,但 iPhone 即使没有移动也会触发 touchmove。理论上,您可以比较 touchstarttouchend 事件 pageXpageY 但是在 iPhone 上,没有 touchend pageX< /code> 或 pageY

不幸的是,要涵盖所有基础,它最终会变得更加复杂一些。

$el.on('touchstart', function(e){
    $el.data('tstartE', e);
    if(event.originalEvent.targetTouches){
        // store values, not reference, since touch obj will change
        var touch = e.originalEvent.targetTouches[0];
        $el.data('tstartT',{ clientX: touch.clientX, clientY: touch.clientY } );
    }
});
$el.on('touchmove', function(e){
    if(event.originalEvent.targetTouches){
        $el.data('tstartM', event.originalEvent.targetTouches[0]);
    }
});

$el.on('click touchend', function(e){
    var oldE = $el.data('tstartE');
    if( oldE && oldE.timeStamp + 1000 < e.timeStamp ) {
        $el.data('tstartE',false);
        return;
    }
    if( $el.data('iosTouchM') && $el.data('tstartT') ){
        var start = $el.data('tstartT'), end = $el.data('tstartM');
        if( start.clientX != end.clientX || start.clientY != end.clientY ){
            $el.data('tstartT', false);
            $el.data('tstartM', false);
            $el.data('tstartE',false);
            return;
        }
    }
    $el.data('tstartE',false);

理论上,有方法来获取longpress 而不是仅仅使用 1000 作为近似值,但实际上并没有那么简单,最好使用合理的代理

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 pageY but on iPhones, there's no touchend pageX or pageY.

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

$el.on('touchstart', function(e){
    $el.data('tstartE', e);
    if(event.originalEvent.targetTouches){
        // store values, not reference, since touch obj will change
        var touch = e.originalEvent.targetTouches[0];
        $el.data('tstartT',{ clientX: touch.clientX, clientY: touch.clientY } );
    }
});
$el.on('touchmove', function(e){
    if(event.originalEvent.targetTouches){
        $el.data('tstartM', event.originalEvent.targetTouches[0]);
    }
});

$el.on('click touchend', function(e){
    var oldE = $el.data('tstartE');
    if( oldE && oldE.timeStamp + 1000 < e.timeStamp ) {
        $el.data('tstartE',false);
        return;
    }
    if( $el.data('iosTouchM') && $el.data('tstartT') ){
        var start = $el.data('tstartT'), end = $el.data('tstartM');
        if( start.clientX != end.clientX || start.clientY != end.clientY ){
            $el.data('tstartT', false);
            $el.data('tstartM', false);
            $el.data('tstartE',false);
            return;
        }
    }
    $el.data('tstartE',false);

In theory, there are ways to get the exact time used for a longpress instead of just using 1000 as an approximation, but in practice it's not that simple and it's best to use a reasonable proxy.

小…楫夜泊 2024-09-12 19:00:06

cduruk 的解决方案非常有效,但在我网站的某些部分造成了问题。因为我已经使用 jQuery 来添加 CSS 悬停类,所以最简单的解决方案就是不在移动设备上添加 CSS 悬停类(或者更准确地说,仅在不在移动设备上时添加它)。

总体思路如下:

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");
        }
    );
}

*出于说明目的减少了代码

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

黒涩兲箜 2024-09-12 19:00:05

对我有用的是这里其他人已经说过的:

不要在悬停或鼠标移动时显示/隐藏元素(这是我的情况下的事件)。

以下是苹果公司的说法(https://developer. apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html):

可点击元素是链接、表单元素、图像映射区域或具有 mousemove、mousedown、mouseup 或 onclick 处理程序的任何其他元素

如果用户点击可点击元素,事件将按以下顺序到达:mouseover、mousemove、mousedown、mouseup 和 click。此外,如果页面内容在 mousemove 事件上发生更改,则不会发送序列中的后续事件。此行为允许用户点击新内容。

因此,您可以使用@woop的解决方案:检测userAgent,检查它是否是iOS设备,然后绑定事件。我最终使用了这种技术,因为它适合我的需求,并且当您不需要时不绑定悬停事件更有意义。

但是...如果你不想弄乱 userAgents 并且仍然在悬停/鼠标移动时隐藏/显示元素,我发现你可以通过使用本机 JavaScript 来做到这一点,如下所示:

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

这将在桌面版本上工作,并且不会执行任何操作在移动版本上。

为了更多的兼容性......

$("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();
    }
});

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();
    }
});
你曾走过我的故事 2024-09-12 19:00:04

我认为尝试使用 mouseenter 代替 mouseover 是明智的做法。这是绑定到 .hover(fn,fn) 时在内部使用的内容,通常也是您想要的内容。

I think it'd be wise to try mouseenter in place of mouseover. It's what's used internally when binding to .hover(fn,fn) and is generally what you want.

喵星人汪星人 2024-09-12 19:00:03

没必要搞得太复杂。

$('a').on('touchend', function() {
    $(this).click();
});

No need to make overcomplicated.

$('a').on('touchend', function() {
    $(this).click();
});
风筝有风,海豚有海 2024-09-12 19:00:01

看来还是有 CSS 解决方案的。 Safari 等待第二次触摸的原因是您通常在 :hover 事件上分配的背景图像(或元素)。如果没有显示任何内容 - 您不会有任何问题。解决方案是使用辅助 CSS 文件(或 JS 方法中的样式)来定位 iOS 平台,该文件会覆盖 :hover 背景以继承,例如并隐藏要在鼠标悬停时显示的元素:

这是一个示例 CSS 和HTML - 鼠标悬停时带有星号标签的产品块:

HTML:

<a href="#" class="s"><span class="s-star"></span>Some text here</a>

CSS:

.s {
   background: url(some-image.png) no-repeat 0 0;

}
.s:hover {
   background: url(some-image-r.png) no-repeat 0 0;
}

.s-star {
   background: url(star.png) no-repeat 0 0;
   height: 56px;
   position: absolute;
   width: 72px;
   display:none;
}

.s:hover .s-star {
   display:block;
}

解决方案(辅助 CSS):

/* CSS */
/* Keep hovers the same or hidden */
.s:hover {
   background:inherit;
}
.s:hover .s-star {
   display:none;
}

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:

HTML:

<a href="#" class="s"><span class="s-star"></span>Some text here</a>

CSS:

.s {
   background: url(some-image.png) no-repeat 0 0;

}
.s:hover {
   background: url(some-image-r.png) no-repeat 0 0;
}

.s-star {
   background: url(star.png) no-repeat 0 0;
   height: 56px;
   position: absolute;
   width: 72px;
   display:none;
}

.s:hover .s-star {
   display:block;
}

Solution (secondary CSS):

/* CSS */
/* Keep hovers the same or hidden */
.s:hover {
   background:inherit;
}
.s:hover .s-star {
   display:none;
}
变身佩奇 2024-09-12 18:59:59

目前尚不完全清楚您的问题是什么,但如果您只想消除双击,同时保留鼠标悬停效果,我的建议是:

  • touchstart 上添加悬停效果mouseenter
  • 删除 mouseleavetouchmoveclick 上的悬停效果。

背景

为了模拟鼠标,如果用户在触摸屏(如 iPad)上触摸并释放手指,浏览器(例如 Webkit mobile)会触发以下事件(来源:触摸和鼠标(位于 html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. 300ms 延迟,浏览器确保这是单击,而不是双击
  5. mouseover
  6. mouseenter
    • 注意:如果 mouseovermouseentermousemove 事件更改了页面内容,则以下事件是从未被解雇过。
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

似乎不可能简单地告诉网络浏览器跳过鼠标事件。

更糟糕的是,如果鼠标悬停事件更改了页面内容,则永远不会触发单击事件,如 Safari Web 内容指南 - 处理事件,特别是单指事件。 “内容更改”到底是什么,取决于浏览器和版本。我发现对于 iOS 7.0,背景颜色的更改不是(或不再?)内容更改。

解决方案解释

回顾一下:

  • touchstartmouseenter 上添加悬停效果。
  • 删除 mouseleavetouchmoveclick 上的悬停效果。

请注意,touchend 上没有任何操作!

这显然适用于鼠标事件:mouseentermouseleavemouseovermouseout的略微改进版本)被触发,并添加和删除悬停。

如果用户实际上单击链接,悬停效果也会被删除。这可确保当用户按下 Web 浏览器中的后退按钮时将其删除。

这也适用于触摸事件:在 touchstart 上添加悬停效果。它“不会”在 touchend 上被删除。在 mouseenter 上再次添加它,并且由于这不会导致任何内容更改(它已经添加),因此也会触发 click 事件,并且无需跟踪链接即可让用户再次点击!

浏览器在 touchstart 事件和 click 之间的 300 毫秒延迟实际上得到了很好的利用,因为悬停效果将在这么短的时间内显示出来。

如果用户决定取消点击,只需移动手指即可像平常一样操作。通常,这是一个问题,因为没有触发 mouseleave 事件,并且悬停效果保持不变。值得庆幸的是,通过删除 touchmove 上的悬停效果可以轻松解决此问题。

就是这样!

请注意,可以消除 300 毫秒的延迟,例如使用 FastClick 库,但这超出了这个问题的范围。

替代解决方案

我发现以下替代方案存在以下问题:

  • 浏览器检测: 极容易出错。假设设备具有鼠标或触摸功能,而当触摸显示器激增时,两者的组合将变得越来越普遍。
  • CSS 媒体检测:我所知道的唯一纯 CSS 解决方案。仍然容易出错,并且仍然假设设备有鼠标或触摸,而两者都是可能的。
  • touchend中模拟点击事件:即使用户只想滚动或缩放,而无意实际单击链接,这也会错误地跟随链接。
  • 使用变量抑制鼠标事件:这会在 touchend 中设置一个变量,该变量用作后续鼠标事件中的 if 条件,以防止该时间点的状态发生变化。该变量在单击事件中重置。如果您确实不想在触摸界面上出现悬停效果,那么这是一个不错的解决方案。不幸的是,如果由于其他原因触发了 touchend 并且没有触发单击事件(例如用户滚动或缩放),并且随后尝试使用鼠标跟踪链接(即在同时具有鼠标和触摸界面的设备)。

进一步阅读

另请参阅 iPad/iPhone 双击问题禁用移动浏览器上的悬停效果

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

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

冷弦 2024-09-12 18:59:58

尚未对此进行全面测试,但由于 iOS 会触发触摸事件,因此假设您处于 jQuery 设置中,这可能会起作用。

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

这个想法是 Mobile WebKit 在点击结束时触发 touchend 事件,因此我们监听该事件,然后在触发 touchend 事件后立即重定向浏览器一个链接。

Haven't tested this fully but since iOS fires touch events, this could work, assuming you are in a jQuery setting.

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

The idea is that Mobile WebKit fires a touchend event at the end of a tap so we listen for that and then redirect the browser as soon as a touchend event has been fired on a link.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文