我有一些我以前建立的网站,使用jquery鼠标事件...我刚得到一个ipad,我注意到所有鼠标悬停事件都是通过单击转换的...因此,例如,我必须单击两次而不是单击一次..(第一个鼠标悬停,而不是实际点击)
是否有准备解决此问题的解决方法?也许我应该使用jquery命令来代替mouseover / out等。谢谢!
我有一些我以前建立的网站,使用jquery鼠标事件...我刚得到一个ipad,我注意到所有鼠标悬停事件都是通过单击转换的...因此,例如,我必须单击两次而不是单击一次..(第一个鼠标悬停,而不是实际点击)
是否有准备解决此问题的解决方法?也许我应该使用jquery命令来代替mouseover / out等。谢谢!
Answers:
尚未对此进行全面测试,但是由于iOS触发了触摸事件,因此假设您处于jQuery设置中,这可能会起作用。
$('a').on('click touchend', function(e) {
var el = $(this);
var link = el.attr('href');
window.location = link;
});
这个想法是,Mobile WebKit会touchend
在点击结束时触发一个事件,因此我们会侦听该事件,然后touchend
在链接上触发事件后立即重定向浏览器。
.on
优于.live
。阅读此答案后,我发现将代码更改为$('a').on('click touchend', function(e) {...})
超级好。
target="_blank"
它将在同一窗口和新窗口中打开。
目前尚不清楚您的问题是什么,但是如果您只想消除双击,同时保留鼠标的悬停效果,我的建议是:
touchstart
和上添加悬停效果mouseenter
。mouseleave
,touchmove
和click
。为了模拟鼠标,如果用户在触摸屏(如iPad)上触摸并释放手指,则Webkit mobile等浏览器会触发以下事件(来源:html5rocks.com上的Touch And Mouse):
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
,mouseenter
或mousemove
事件改变页面的内容,以下事件从未被触发。mousemove
mousedown
mouseup
click
似乎不可能简单地告诉Web浏览器跳过鼠标事件。
更糟糕的是,如果鼠标悬停事件更改了页面内容,就不会触发click事件,如Safari Web内容指南-处理事件所述,尤其是“ 单指事件”中的图6.4所述。。确切的“内容更改”将取决于浏览器和版本。我发现,对于iOS 7.0,背景颜色的更改不是(或不再是?)内容更改。
回顾一下:
touchstart
和上添加悬停效果mouseenter
。mouseleave
,touchmove
和click
。请注意,没有作用touchend
!
这显然适用于鼠标事件:mouseenter
和mouseleave
(略有改善的版本mouseover
和mouseout
)被解雇,并添加和删除悬停。
如果用户实际上click
是一个链接,则悬停效果也将被删除。这样可以确保在用户按下Web浏览器中的“后退”按钮时将其删除。
这也适用于触摸事件:touchstart
添加了悬停效果。已在上将其“不”删除touchend
。再次在上添加了mouseenter
该内容,由于这不会引起内容更改(已添加),因此click
也会触发该事件,并且无需用户再次单击即可跟随该链接!
在touchstart
事件和click
实际使用之间,浏览器具有300ms的延迟,因为悬停效果将在较短的时间内显示出来。
如果用户决定取消单击,则手指的移动将照常进行。通常,这是一个问题,因为不会mouseleave
触发任何事件,并且悬停效果仍然存在。幸运的是,可以通过消除上的悬停效果来轻松解决此问题touchmove
。
而已!
请注意,例如可以使用FastClick库来消除300ms的延迟,但这在此问题之外。
我发现以下替代方法存在以下问题:
touchend
:即使用户只想滚动或缩放,而实际上并没有点击链接的意图,这也会错误地跟随链接。touchend
该变量在后续鼠标事件中用作if条件,以防止该时间点的状态更改。该变量在click事件中重置。如果您确实不想在触摸界面上悬停效果,那么这是一个不错的解决方案。不幸的是,如果touchend
由于其他原因触发了a 并且未触发点击事件(例如,用户滚动或缩放),并且随后试图用鼠标跟随链接(即在同时具有鼠标和触摸界面的设备上),则此方法不起作用)。mouseover
or mousemove
事件期间更改内容后不会触发其他事件。似乎毕竟有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;
}
对我有用的是这里的其他人已经说过的话:
不要在鼠标悬停或鼠标移动时显示/隐藏元素(在我的情况下就是这种情况)。
clickable元素是链接,表单元素,图像映射区域或任何其他具有mousemove,mousedown,mouseup或onclick处理程序的元素
如果用户点击可单击元素,则事件将按以下顺序到达:鼠标悬停,鼠标移动,鼠标按下,鼠标按下和单击。同样,如果页面的内容在mousemove事件上发生更改,则序列中不会发送任何后续事件。此行为允许用户点击新内容。
因此,您可以使用@woop的解决方案:检测userAgent,检查它是否为iOS设备,然后绑定事件。我最终使用了此技术,因为它适合我的需求,并且在不需要时不要绑定悬停事件更有意义。
但是......如果您不想弄乱userAgents并仍然在悬停/ 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();
}
});
cduruk的解决方案非常有效,但是却在我的网站的某些部分引起了问题。因为我已经在使用jQuery添加CSS悬停类,所以最简单的解决方案是不在移动设备上添加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");
}
);
}
*为便于说明,减少了代码
现有的解决方案存在以下问题,并且发现了可以解决所有问题的方法。假设您的目标是跨浏览器,跨设备且不希望设备嗅探。
使用just touchstart
或touchend
:
触发mouseover
的事件touchstart
,并mouseout
在touchmove
有那么严重的后果,但与通常的浏览器行为干扰,例如:
touchstart
像a一样对待mouseover
,然后在mouseout
ed上进行编辑touchstart
。因此,在Android中查看鼠标悬停内容的一种方法是触摸感兴趣的区域并摇动手指,稍微滚动页面。将其touchmove
视为mouseout
中断。从理论上讲,您可以只添加带有的标志touchmove
,但是即使没有移动,iPhone也会触发touchmove。从理论上讲,您可以只比较touchstart
和touchend
事件pageX
,pageY
但在iPhone上则没有touchend
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);
从理论上讲,有一些方法可以获取长按所需的确切时间,而不仅仅是使用1000作为近似值,但实际上并不是那么简单,最好使用合理的代理。
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的帮助。
我只是发现,如果您添加一个空的侦听器,它会起作用,不要问我为什么,但是我在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(){});
}
}
我“认为”您的链接没有onmouseover事件,其中单击1次将激活onmouseover,而双击将激活该链接。但是idk。我没有iPad。我认为您必须使用手势/触摸事件。
如果使用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)
还要注意,与Windows Phone相比,测试用户代理iemobile将为您提供更多的检测到的Microsoft移动设备。
您可以使用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;
});
干杯,
耶罗恩
我遇到了类似的情况,事件绑定到元素的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上进行鼠标进入(或初次点击)时触发.click事件处理程序,从而避免了双击元素的需要。可能不是最优雅的解决方案,但它对我而言效果很好,并利用了我已经安装的插件,并要求我添加一行代码以使现有事件在这些设备下正常工作。
您可以在此处获取jQuery $ .browser插件:https : //github.com/gabceb/jquery-browser-plugin
只是在避免错误地在链接上滑动手指时避免重定向的一种改进。
// 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 );
});
在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
我来不及了,我知道,但这是我发现的最简单的解决方法之一:
$('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);
}
});
这不仅适用于链接(锚标记),还适用于其他元素。希望这可以帮助。
这个简短的代码片段似乎有效。点击链接时触发点击事件:
$('a').on('touchstart', function() {
$(this).trigger('click');
});
另一个答案对我来说都没有用。我的应用程序有很多事件侦听器,自己的复选框和具有侦听器的链接以及没有侦听器的链接。
我用这个:
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;
});
解决双击IPad的最简单方法是在媒体查询中包装css以获得悬浮效果@media (pointer: fine)
:
@media (pointer: fine) {
a span {
display: none;
}
a:hover span {
display: inline-block;
}
}
包装在此媒体查询中的CSS仅适用于桌面。
此解决方案的说明位于https://css-tricks.com/annoying-mobile-double-tap-link-issue/
您可以这样检查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进行屏幕显示,您可能会获得大多数手持设备,但不是全部。
只需进行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" />