我有一些我以前建立的网站,使用jquery鼠标事件...我刚刚得到一个ipad,我注意到所有鼠标悬停事件都是通过点击转换...所以例如我必须做两次点击而不是一个..(第一个悬停,而不是实际点击)
是否有解决此问题的解决方法?也许是一个jquery命令我shoudl使用而不是mouseover / out等。 谢谢!
答案 0 :(得分:196)
没有完全测试过,但是因为iOS触发了触摸事件,所以假设你处于jQuery设置中,这可能会有效。
$('a').on('click touchend', function(e) {
var el = $(this);
var link = el.attr('href');
window.location = link;
});
想法是Mobile WebKit在点击结束时触发touchend
事件,因此我们会监听该事件,然后在链接上触发touchend
事件后立即重定向浏览器。
答案 1 :(得分:36)
目前还不完全清楚你的问题是什么,但如果你只想消除双击,同时保留鼠标的悬停效果,我的建议是:
touchstart
和mouseenter
上添加悬停效果。 mouseleave
,touchmove
和click
上的悬停效果。 为了模拟鼠标,如果用户在触摸屏上触摸并释放手指(如iPad),Webkit移动等浏览器会触发以下事件(来源:html5rocks.com上的Touch And Mouse):
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
,mouseenter
或mousemove
事件更改了网页内容,则永远不会触发以下事件。mousemove
mousedown
mouseup
click
似乎无法简单地告诉webbrowser跳过鼠标事件。
更糟糕的是,如果mouseover事件更改了页面内容,则不会触发click事件,如Safari Web Content Guide - Handling Events所述,特别是 One-Finger Events 中的图6.4。究竟什么是“内容更改”,取决于浏览器和版本。我发现对于iOS 7.0,背景颜色的变化不是(或不再是?)内容变化。
回顾一下:
touchstart
和mouseenter
添加悬停效果。mouseleave
,touchmove
和click
上的悬停效果。请注意,touchend
上没有任何操作!
这显然适用于鼠标事件:mouseenter
和mouseleave
(mouseover
和mouseout
稍微改进的版本)会被触发,并添加和删除悬停。
如果用户实际click
是一个链接,则还会删除悬停效果。这可以确保在用户按下Web浏览器中的后退按钮时将其删除。
这也适用于触摸事件:在touchstart
上添加悬停效果。它在touchend
上没有被删除。它会再次添加到mouseenter
,因为这不会导致内容更改(已添加),所以click
事件也会被触发,并且会跟踪链接,而无需用户再次单击!
浏览器在touchstart
事件和click
之间的300毫秒延迟实际上得到了充分利用,因为悬停效果将在这么短的时间内显示。
如果用户决定取消点击,则手指的移动将正常进行。通常,这是一个问题,因为没有触发mouseleave
事件,并且悬停效果仍然存在。值得庆幸的是,通过删除touchmove
上的悬停效果,可以轻松解决此问题。
就是这样!
请注意,可以删除300毫秒延迟,例如使用FastClick library,但这超出了此问题的范围。
我发现以下替代方案存在以下问题:
touchend
中的点击事件:这将错误地跟踪链接,即使用户只想滚动或缩放,而无意实际点击链接。touchend
中设置一个变量,该变量在后续鼠标事件中用作if条件,以防止在该时间点发生状态更改。该变量在click事件中重置。如果您真的不希望在触摸界面上悬停效果,这是一个不错的解决方案。不幸的是,如果touchend
由于其他原因被触发并且没有触发点击事件(例如用户滚动或缩放),并且随后尝试使用鼠标跟踪链接(即在设备上鼠标和触摸界面)。mouseover
或mousemove
事件期间更改内容后不会触发其他事件。另请参阅iPad/iPhone double click problem和Disable hover effects on mobile browsers。
答案 2 :(得分:20)
毕竟似乎有一个CSS解决方案。 Safari等待第二次触摸的原因是您通常在:hover事件上分配的背景图像(或元素)。如果没有显示 - 你将不会有任何问题。解决方案是使用辅助CSS文件(或JS方法中的样式)来覆盖iOS平台,该文件覆盖:例如,将鼠标悬停在背景上并保持隐藏在鼠标上显示的元素:
以下是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;
}
答案 3 :(得分:5)
对我来说有用的是其他人已经说过的话:
不要在悬停或鼠标移动时显示/隐藏元素(在我的情况下这是事件)。
可点击元素是链接,表单元素,图像映射区域或具有mousemove,mousedown,mouseup或onclick处理程序的任何其他元素
如果用户点击可点击元素,则事件按此顺序到达:mouseover,mousemove,mousedown,mouseup和click。此外,如果页面内容在mousemove事件中发生更改,则不会发送序列中的后续事件。此行为允许用户点击新内容。
所以,你可以使用@ woop的解决方案:检测userAgent,检查它是否和iOS设备然后绑定事件。我最终使用这种技术,因为它适合我的需要,更有意义的是当你不想要它时不要绑定悬停事件。
但是......如果你不想弄乱userAgents并且仍然在hover / mousemove上隐藏/显示元素,我发现你可以通过使用本机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();
}
});
答案 4 :(得分:3)
无需过度复杂。
$('a').on('touchend', function() {
$(this).click();
});
答案 5 :(得分:3)
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");
}
);
}
*代码为了说明目的而减少
答案 6 :(得分:2)
我认为用mouseenter
代替mouseover
是明智之举。它是绑定到.hover(fn,fn)
时内部使用的,通常是你想要的。
答案 7 :(得分:1)
我在现有解决方案中遇到了以下问题,并找到了似乎可以解决所有这些问题的问题。这假设您的目标是跨浏览器,跨设备,并且不希望设备嗅探。
仅使用touchstart
或touchend
:
触发mouseover
上的touchstart
和mouseout
touchmove
上的touchstart
事件的后果不太严重,但会干扰通常的浏览器行为,例如:
mouseover
上的手指位置视为mouseout
,touchstart
会在下一个touchmove
上进行mouseout
。因此,在Android中查看鼠标悬停内容的一种方法是触摸感兴趣的区域并摆动手指,稍微滚动页面。将touchmove
视为touchstart
可以打破这一点。理论上,您可以添加touchend
的标记,但即使没有移动,iPhone也会触发触摸。从理论上讲,您只需比较pageX
和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);
和{{1}} but on iPhones, there's no touchend
pageX
or pageY
。
所以很遗憾,为了覆盖所有基础,它最终会变得更加复杂。
{{1}}
答案 8 :(得分:1)
我刚刚发现,如果你添加一个空的听众,它不会问我原因,但是我在iPhone和iPad上用iOS 9.3.2进行了测试,它运行良好。
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(){});
}
}
答案 9 :(得分:1)
MacFreak的回答对我非常有帮助。这里有一些实用的代码,以防它帮助你。
问题 - 应用 touchend 表示每次在元素上滚动手指时,即使您只是尝试滚动,它也会像按下它一样响应过去。
我正在使用jQuery创建一个效果,它会在某些按钮下淡化一行以“突出显示”悬停的按钮。我不希望这意味着您必须在触摸设备上按两次按钮才能跟踪链接。
以下是按钮:
<a class="menu_button" href="#">
<div class="menu_underline"></div>
</a>
我希望“menu_underline”div在鼠标悬停时淡出并在mouseout上逐渐淡出。但我希望触摸设备只需点击一下即可关注链接。
解决方案 - 这是让它运行的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的帮助。
答案 10 :(得分:1)
我“认为”您的链接没有onmouseover事件,其中1点击激活onmouseover并且双击激活链接。但是idk。我没有iPad。 我想你必须使用手势/触摸事件。
答案 11 :(得分: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">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;
});
干杯,
的Jeroen
答案 12 :(得分:0)
我遇到类似的情况,我将事件绑定到一个元素的mouseenter / mouseleave / click状态,但是在iPhone上,用户必须双击该元素才能首先触发mouseenter事件,然后再次触发点击事件。
我使用与上面类似的方法解决了这个问题,但是我使用了jQuery $ .browser插件(对于jQuery 1.9&gt;)并将一个.trigger事件添加到了mouseenter绑定事件中,如下所示:
// 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上查看元素的鼠标中心(或初始点击)时,.trigger可以通过触发.click事件处理程序来防止双击该元素。可能不是最优雅的解决方案,但它在我的情况下工作得很好并且使用了我已经拥有的插件,并且要求我添加一行代码以使我现有的事件在这些设备下工作。
您可以在此处获取jQuery $ .browser插件:https://github.com/gabceb/jquery-browser-plugin
答案 13 :(得分: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 );
});
答案 14 :(得分:0)
从MacFreak获得灵感,我把一些适合我的东西放在一起。
此js方法可防止悬停粘在ipad上,并在某些情况下防止点击注册为两次点击。在CSS中,如果您有任何:在您的CSS中悬停psudo类,请将它们更改为.hover例如.some-class:hover to .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
答案 15 :(得分:0)
为了在不破坏触摸滚动的情况下使链接正常工作,我使用jQuery Mobile的“tap”事件解决了这个问题:
$('a').not('nav.navbar a').on("tap", function () {
var link = $(this).attr('href');
if (typeof link !== 'undefined') {
window.location = link;
}
});
答案 16 :(得分: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移动设备。
答案 17 :(得分:0)
这个简短的片段似乎有用。 点击链接时触发点击事件:
$('a').on('touchstart', function() {
$(this).trigger('click');
});
答案 18 :(得分:0)
我有同样的问题,但没有在触控设备上。每次单击时都会触发该事件。有关事件排队等等的事情。
但是,我的解决方案是这样的: 在点击事件(或触摸?)上设置一个计时器。如果在X ms内再次单击该链接,则只返回false。
要设置每个元素计时器,您可以使用$.data()
。
这也可以解决上述的@Ferdy问题。
答案 19 :(得分:0)
其他答案都没有对我有用。我的应用程序有很多事件监听器,自己的复选框和具有监听器的链接以及没有监听器的链接。
我用这个:
<a class="linkToModal" onclick="showModal('http://www.example.com/seal/1e047f70-948c-4d40-a47f-0a15c59fc243')">MY SITE SEAL</a>
<div id="modal"><iframe src=""></iframe></div>
答案 20 :(得分:0)
当您有jQuery UI下拉菜单时,这对我有用
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('.ui-autocomplete').off('menufocus hover mouseover');
}
答案 21 :(得分:0)
避免在css悬停事件内更改“显示”样式。我的“显示:阻止”处于悬停状态。删除ios后,只需轻按一下即可进入lins。顺便说一下,似乎最新的IOS更新修复了此“功能”
答案 22 :(得分:0)
解决双击IPad的最简单方法是在媒体查询
import ...
class ItemCardsAdapter(private val myDataset: ArrayList<Item>, private val f: Fragment) : RecyclerView.Adapter<ItemCardsAdapter.MyViewHolder>() {
class MyViewHolder(viewItem: View) : RecyclerView.ViewHolder(viewItem){
val itemphoto = viewItem.itemphoto
val itemtitle = viewItem.title
val itemprice = viewItem.itemprice
val itemlocation = viewItem.itemlocation
val editpencil = viewItem.editCard
}
// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// create a new view
val viewItem = LayoutInflater.from(parent.context).inflate(R.layout.item_card, parent, false)
// set the view's size, margins, paddings and layout parameters
return MyViewHolder(viewItem)
}
// Replace the contents of a view (invoked by the layout manager)
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.itemtitle.text = myDataset[position].title
holder.itemprice.text = myDataset[position].price
holder.itemlocation.text = myDataset[position].location
if(myDataset[position].photoPath != "") /*Here it stucks on load !?*/
holder.itemphoto.setImageBitmap(decodeSampledBitmapFromResource(myDataset[position].photoPath,256,256))
//holder.View.startAnimation(AnimationUtils.loadLayoutAnimation(this,R.anim.layout_animation))
val bundle = bundleOf("itemAdKey" to myDataset[position].adId)
holder.editpencil.setOnClickListener {
bundle.putString("nav", "editCard")
f.findNavController().navigate(R.id.action_nav_itemlist_to_itemEditFragment, bundle)
}
holder.itemView.setOnClickListener {
f.findNavController().navigate(R.id.action_nav_itemlist_to_nav_itemdetails, bundle)
}
}
// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = myDataset.size
}
中将css包装起来以实现悬停效果:
@media (pointer: fine)
此媒体查询中包装的CSS仅适用于台式机。
此解决方案的说明在https://css-tricks.com/annoying-mobile-double-tap-link-issue/
答案 23 :(得分:-1)
你可以这样检查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屏幕,你可能会得到大部分掌上电脑,但不是全部。
答案 24 :(得分:-1)
只需制作一个不包含平板电脑和移动设备的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" />