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

132
我以前建的一些网站使用了jquery鼠标事件......我刚刚买了一个iPad,发现所有的鼠标悬停事件都被转换为点击事件...所以例如我需要做两个点击而不是一个...(先是悬停,然后才是实际点击)
是否有一种解决方法可以解决这个问题?也许有一个我应该使用而不是mouseover/out等的jquery命令.. 谢谢!

1
你的事件绑定在什么上面?例如,onclick事件应该能正常工作... onmouseover、onmouseout和CSS的:hover是有点难处理的,因为触摸屏没有"hover"可用。你有代码示例吗? - scunliffe
我建议您重新思考界面设计(如果可能的话)。iPad / iPhone上的交互方式与PC上不完全相同,因此最好让您的网站感觉像是针对iPad / iPhone / 其他具有类似多点触控机制的触摸设备编写的。这只是一个想法。 - jer
我同意“jer”的观点。这是一个奇怪的问题,我个人认为解决方案不是“变通”。我认为将桌面浏览器上的“鼠标悬停”翻译成触摸屏浏览器上的“手指轻触”是有道理的。如果您同意这种翻译,但想要一次轻触而不是两次,则可能需要对iPad事件(例如“touchstart”)进行功能检测并更改事件处理程序。也许将代码提取到一个jquery插件中,“触摸或点击”类似的功能根据特性以不同的方式触发,但在我看来似乎是针对您的网站/应用程序的。 - Andy Atkinson
1
我认为这种翻译实际上是一种功能。如果您设置了悬停事件,那么肯定有一些实用性可见。单击会显示悬停元素,第二次点击会跟随链接“后面”的悬停。 - Aaron
27个回答

1

我认为你的链接没有onmouseover事件,其中一个轻触会激活onmouseover,而双击则会激活链接。但我不确定。我没有iPad。

我认为你需要使用手势/触摸事件。

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


0

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

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

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


0
为了使链接在不破坏触摸滚动的情况下正常工作,我使用了jQuery Mobile的“tap”事件来解决这个问题:
    $('a').not('nav.navbar a').on("tap", function () {
        var link = $(this).attr('href');
        if (typeof link !== 'undefined') {
            window.location = link;
        }
    });

0

其他答案对我都不起作用。我的应用程序有很多事件监听器,自己的复选框和带有监听器和没有监听器的链接。

我使用这个:

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: https://dev59.com/Z3I-5IYBdhLWcg3wwLS3#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

这个简短的代码片段似乎是可以工作的。 当链接被轻击时触发点击事件:

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

0

如果您使用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移动设备范围。


0

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

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

0

我遇到了一个类似的情况,我将事件绑定到元素的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
});

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

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


0
你可以使用click touchend,例如:
$('a').on('click touchend', function() {
    var linkToAffect = $(this);
    var linkToAffectHref = linkToAffect.attr('href');
    window.location = linkToAffectHref;
});

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

如果您只想针对特定链接进行操作,您可以在其上设置一个类,例如:

HTML:

<a href="example.html" class="prevent-extra-click">防止在触摸设备上额外点击</a>

Jquery:

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

祝愉快!

Jeroen


0

我遇到了同样的问题,但不是在触摸设备上。每次点击时都会触发事件。这可能与事件排队有关。

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

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

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


你能否发布这段代码是什么样子的?我遇到了点击事件触发两次的问题。 - fancy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接