jquery防止触摸悬停功能
Posted
技术标签:
【中文标题】jquery防止触摸悬停功能【英文标题】:jquery preventing hover function on touch 【发布时间】:2013-01-01 13:35:54 【问题描述】:我有一个悬停功能,如果它是一个触摸设备,我希望悬停事件不会发生。问题是当您使用触摸设备点击链接时,它会在执行点击事件之前执行悬停事件,因此您必须点击它两次才能使其工作。
这是悬停功能:
$("#close").hover(
function ()
$("#close_2").css(
display: "none"
);
$("#close_1").css(
display: "block"
);
,
function ()
$("#close_1").css(
display: "none"
);
$("#close_2").css(
display: "block"
);;
);
然后我将其设置为点击功能:
$('#close').click(function()
var id = $(this).attr('id');
$('#full_image').animate(
height: 0
, 300, function()
$('#full_image img').attr('src','#');
);
$("#close_1").css(
display: "none"
);
$("#close_2").css(
display: "none"
);
$("#close").css(
display: "none"
);
);
【问题讨论】:
尝试 event.preventDefault() 悬停。 api.jquery.com/event.preventDefault 嗯,你会怎么把它写进去? @Mihir 这不会阻止方法执行,也不会阻止指定的处理程序运行。它可以防止 default 操作,就像名称所暗示的那样,这不是所描述的问题。 好的,抱歉我误会了。您无法检测设备是否为触摸设备?如果是,则不要调用该函数。 【参考方案1】:使 .hover() 方法更明确,并与 .on() 结合:
var $close1 = $('#close_1'),
$close2 = $('#close_2');
$('#close').on(
mouseenter: function()
$close2.css(display:'none');
$close1.css(display:'block');
,
mouseleave: function()
$close1.css(display:'none');
$close2.css(display:'block');
);
然后将它与 .off() 结合起来。
$('#close').on('touchstart',function()
$(this).off('mouseenter,mouseleave');
);
如果您希望事件在点击触摸设备时触发,但在桌面设备上悬停时触发,则将函数作为您在这些操作中分别调用的单独函数。
编辑
自从我回答这个问题以来已经有一段时间了,这里有一个更好的方法:
$(function()
var isTouchDevice = ('ontouchstart' in window || 'onmsgesturechange' in window),
$close = $('#close'),
$close1 = $('#close_1'),
$close2 = $('#close_2');
if(!isTouchDevice)
$close.on(
mouseenter: function()
$close2.hide();
$close1.show();
,
mouseleave: function()
$close1.hide();
$close2.show();
);
$close.on('click',function()
$('#full_image').animate(height:0,300,function()
$(this).find('img').attr('src','#');
);
$close.hide();
$close1.hide();
$close2.hide();
);
);
这不需要在每次触摸时触发“防止悬停”事件,基本上是在不影响点击事件的情况下设置页面加载功能。
【讨论】:
特别指定 'mouseenter' 和 'mouseleave' 应该没有什么不同,因为hover
只是它的简写;第二种方法似乎应该可以工作。 +1
hmm,所以我在上面发布的悬停代码中添加了那个小片段,当我点击触摸屏时,它仍然首先执行悬停事件,然后再次点击并执行点击事件。
@lifeinthegrey 在这里您可以实际尝试拼写方法,速记悬停现在仅用作方法,不推荐使用伪事件,因此它在 1.8+ 中不起作用。 $('#close').off('mouseenter mouseleave');
。只是一个想法。
啊该死的,我有点怀疑,但我已经改了,不想再改了哈哈...代码已修改【参考方案2】:
我认为一个明确的方法是:
-
检测浏览器是否支持触摸事件
相应地添加悬停事件处理程序
如果您已经在使用 Modernizr 之类的东西:
if(!Modernizr.touch)
// only if the browser doesn't support touch events,
// add the hover handler here.
//add the click handler here, as you want it bound no matter what
有关检测触摸功能的其他选项,请参阅 What's the best way to detect a 'touch screen' device using javascript? 和 What's the best way to detect a 'touch screen' device using JavaScript?。
【讨论】:
这完全可行,但会增加引入库的完全不必要的开销。 ...这正是我说“如果您正在使用类似 Modernizr 已经之类的东西”的原因,并包含指向 SO 问题讨论的链接替代检测方法:)【参考方案3】:在移动端调用 touchstart 事件中的 preventDefault 可防止 mouseover、mouseenter、mousedown em> 和附属活动。详情:https://patrickhlauke.github.io/touch/tests/results/
$('#close').on('touchstart',function(e)
console.log('touchstart');
e.preventDefault();
//Do touch stuff
);
【讨论】:
这正是我所需要的。谢谢。 这个答案确实有效(这里的大多数答案不考虑具有触摸屏+鼠标的设备,如触摸屏笔记本电脑),也是最简单的答案。【参考方案4】:由于 Windows 8 和超极本,我希望看到很多设备同时支持触摸和指针事件。因此,我避免完全禁用悬停事件,因为它可能会破坏使用鼠标启用触摸的用户的网站。
为了解决这个问题,我最终使用了两个不同的类来显示菜单,.hover
和 .touch
,以及悬停和点击的单独事件。
我使用jquery.finger 来捕获点击事件,尽管任何插件都应该可以工作,这只是最小的一个。
html 应该是这样的:
<li>
<a>Some Link</a>
<div>Some Content</div>
</li>
CSS 类似于:
li div display:none;
li.hover div, li.touch div display:block;
以及使用 JQuery 的 Javascript:
// Caching whatever elements I'm using for the navigation
a = $("a");
li = $("li");
// Set hover events
li.hover(
// Both hover in and out fire whenever the user taps, aggravating!
function(e)
// Close unused menus
li.not(this).removeClass("hover").removeClass("touch");
// Show this menu
$(this).addClass( "hover" );
, function(e)
// Only closes if the menu doesn't have .touch, hell yeah!
li.removeClass("hover");
);
// Set the tap event
a.on('tap',function(e,data)
e.stopPropagation();
var thisParent = $(this.parentNode);
// Close unused menus
li.not(thisParent).removeClass("touch");
// Toggle the current menu
thisParent.toggleClass("touch");
// The menu is open, so we don't need this class anymore
li.removeClass("hover");
);
// Prevent the list items when being tapped from closing the drop down
li.on('tap',function(e)e.stopPropagation(););
// Close drop downs when tapping outside the menus
$(document).on('tap',function(e)
li.removeClass("touch");
);
这里重要的一点是我如何根据事件添加单独的 .hover
或 .touch
类,以及删除未使用的类。顺序很重要,所以菜单不会闪烁。
【讨论】:
【参考方案5】:最终使用了触摸检测:
var deviceAgent = navigator.userAgent.toLowerCase();
var agentID = deviceAgent.match(/(iphone|ipod|ipad)/);
if(agentID)
$('#close').click(function()
var id = $(this).attr('id');
$('#full_image').animate(
height: 0
, 300, function()
$('#full_image img').attr('src','#');
);
$("#close_1").css(
display: "none"
);
$("#close_2").css(
display: "none"
);
$("#close").css(
display: "none"
);
);
else
$('#close').hover(
function()
$("#close_2").css(
display: "none"
);
$("#close_1").css(
display: "block"
);
, function()
$("#close_1").css(
display: "none"
);
$("#close_2").css(
display: "block"
);
);
$('#close').click(function()
var id = $(this).attr('id');
$('#full_image').animate(
height: 0
, 300, function()
$('#full_image img').attr('src','#');
);
$("#close_1").css(
display: "none"
);
$("#close_2").css(
display: "none"
);
$("#close").css(
display: "none"
);
);
【讨论】:
不是触摸检测。是检测“如果用户是苹果的粉丝”。为什么这是公认的答案?以上是关于jquery防止触摸悬停功能的主要内容,如果未能解决你的问题,请参考以下文章