Jquery iPad/iPhone悬停问题导致用户双击链接
我有一些我很久以前建立的网站,使用jquery鼠标事件…我刚买了一台ipad,我注意到所有鼠标覆盖的事件都转换为点击次数…例如,我必须点击两次而不是一次…(第一次悬停,而不是实际点击) 是否有解决此问题的变通方法?也许我应该用jquery命令代替mouseover/out等。。Jquery iPad/iPhone悬停问题导致用户双击链接,jquery,ipad,hover,mouseover,Jquery,Ipad,Hover,Mouseover,我有一些我很久以前建立的网站,使用jquery鼠标事件…我刚买了一台ipad,我注意到所有鼠标覆盖的事件都转换为点击次数…例如,我必须点击两次而不是一次…(第一次悬停,而不是实际点击) 是否有解决此问题的变通方法?也许我应该用jquery命令代替mouseover/out等。。 谢谢 您可以像这样检查navigator.userAgent: if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i
谢谢 您可以像这样检查
navigator.userAgent
:
if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
//bind your mouseovers...
}
$("body").on("mouseover", function() {
document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
document.querySelector(".my-selector div").style.display = 'none'; // hide element
});
但你必须检查黑莓、机器人和无数其他触摸屏设备。仅当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,你可能会看到大部分的手持设备,但不是所有的。我认为尝试使用
mouseenter
代替mouseover
是明智的选择。它是绑定到时内部使用的。hover(fn,fn)
通常是您想要的。我“认为”您的链接没有onmouseover事件,点击一次激活onmouseover,双击激活链接。但是idk。我没有iPad。
我想你应该使用手势/触摸事件
尚未对此进行全面测试,但由于iOS触发触摸事件,假设您处于jQuery设置中,这可能会起作用
$('a').on('click touchend', function(e) {
var el = $(this);
var link = el.attr('href');
window.location = link;
});
其想法是,Mobile WebKit在点击结束时触发一个
touchend
事件,因此我们监听该事件,然后在链接上触发touchend
事件后立即重定向浏览器。我也有同样的问题,但不是在触摸设备上。每次单击时都会触发该事件。关于事件队列之类的东西
然而,我的解决方案是这样的:
单击事件(或触摸?)可设置计时器。如果在X毫秒内再次单击链接,则返回false
要设置每元素计时器,可以使用$.data()
这也可能解决上述@Ferdy问题。看来毕竟有一个CSS解决方案。Safari等待第二次触摸的原因是:hover事件中通常指定的背景图像(或元素)。如果没有显示-你不会有任何问题。解决方案是使用辅助CSS文件(或JS方法中的样式)以iOS平台为目标,该文件覆盖:hover background以继承,例如,并隐藏您将在鼠标上显示的元素: 下面是一个CSS和HTML示例-鼠标上方带有星号标签的产品块: HTML: 解决方案(辅助CSS):
cduruk的解决方案相当有效,但在我的站点的一些部分造成了问题。因为我已经在使用jQuery添加CSS hover类,所以最简单的解决方案就是不在移动设备上添加CSS hover类(或者更准确地说,只在不在移动设备上时添加它) 大致思路如下:
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");
}
);
}
*出于说明目的而减少的代码如果您使用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();
};
如果不使用Modernizer,只需将上面的Modernizer.touch
功能替换为(“document.documentElement”中的“ontouchstart”)
另外请注意,测试用户代理iemobile将为您提供比Windows Phone更广泛的检测到的Microsoft移动设备。对我有效的是这里的其他人已经说过的: 不要在hover或mousemove上显示/隐藏元素(在我的例子中就是这样) 以下是苹果公司的说法(): 可单击元素是一个链接、表单元素、图像映射区域或具有mousemove、mousedown、mouseup或onclick处理程序的任何其他元素 如果用户点击一个可点击的元素,事件按如下顺序到达:mouseover、mousemove、mousedown、mouseup和click。另外,如果页面内容在mousemove事件中发生更改,则不会发送序列中的后续事件。此行为允许用户点击新内容 因此,您可以使用@woop的解决方案:检测userAgent,检查它是否与iOS设备兼容,然后绑定事件。我最终使用了这种技术,因为它适合我的需要,而且在不需要的时候不绑定悬停事件更有意义 但是。。。如果您不想搞乱UserAgent,仍然在hover/mousemove上隐藏/显示元素,我发现您可以使用本机javascript来实现这一点,如下所示:
if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
//bind your mouseovers...
}
$("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();
}
});
您可以使用
单击touchend
例如:
$('a').on('click touchend', function() {
var linkToAffect = $(this);
var linkToAffectHref = linkToAffect.attr('href');
window.location = linkToAffectHref;
});
上述示例将影响触摸设备上的所有链接
如果只针对特定链接,可以通过在其上设置类来实现,即:
HTML:
$('a.prevent-extra-click').on('click touchend', function() {
var linkToAffect = $(this);
var linkToAffectHref = linkToAffect.attr('href');
window.location = linkToAffectHref;
});
Jquery:
$('a.prevent-extra-click').on('click touchend', function() {
var linkToAffect = $(this);
var linkToAffectHref = linkToAffect.attr('href');
window.location = linkToAffectHref;
});
干杯
Jeroen你的问题并不完全清楚,但如果你只是想消除双击,同时保留鼠标的悬停效果,我的建议是:
- 在
和touchstart
上添加悬停效果mouseenter
- 在
、鼠标移动
和触摸移动
上移除悬停效果单击
touchstart
touchmove
touchend
mouseov
// 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
});
$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);
// 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 );
});
$('a').not('nav.navbar a').on("tap", function () {
var link = $(this).attr('href');
if (typeof link !== 'undefined') {
window.location = link;
}
});
<a class="menu_button" href="#">
<div class="menu_underline"></div>
</a>
//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();
});
$('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);
}
});
@media screen and (min-device-width:1024px) {
your-element:hover {
/* Do whatever here */
}
}
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
$('a').on('touchstart', function() {
$(this).trigger('click');
});
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(){});
}
}
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;
});
$('a').on('touchend', function() {
$(this).click();
});
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('.ui-autocomplete').off('menufocus hover mouseover');
}
@media (pointer: fine) {
a span {
display: none;
}
a:hover span {
display: inline-block;
}
}