jQuery 如何绑定“touchstart”和“click”事件但不响应两者?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7018919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to bind 'touchstart' and 'click' events but not respond to both?
提问by DA.
I'm working on a mobile web site that has to work on a variety of devices. The one's giving me a headache at the moment are BlackBerry.
我正在开发一个必须在各种设备上运行的移动网站。目前让我头疼的是黑莓。
We need to support both keyboard clicks as well as touch events.
我们需要同时支持键盘点击和触摸事件。
Ideally I'd just use:
理想情况下,我只使用:
$thing.click(function(){...})
but the issue we're running into is that some of these blackberry devices have an very annoying delay from the time of the touch to it triggering a click.
但我们遇到的问题是,其中一些黑莓设备从触摸到触发点击之间有一个非常烦人的延迟。
The remedy is to instead use touchstart:
补救方法是改用 touchstart:
$thing.bind('touchstart', function(event){...})
But how do I go about binding both events, but only firing one? I still need the click event for keyboard devices, but of course, don't want the click event firing if I'm using a touch device.
但是我如何绑定两个事件,但只触发一个?我仍然需要键盘设备的点击事件,但当然,如果我使用的是触摸设备,不希望点击事件触发。
A bonus question: Is there anyway to do this and additionally accommodate browsers that don't even have a touchstart event? In researching this, it looks like BlackBerry OS5 doesn't support touchstart so will also need to rely on click events for that browser.
一个额外的问题:有没有办法做到这一点,并且还可以容纳甚至没有 touchstart 事件的浏览器?在研究这一点时,看起来 BlackBerry OS5 不支持 touchstart,因此还需要依赖该浏览器的点击事件。
ADDENDUM:
附录:
Perhaps a more comprehensive question is:
也许更全面的问题是:
With jQuery, is it possible/recommended to handle both touch interactions and mouse interactions with the same bindings?
使用 jQuery,是否可以/建议使用相同的绑定处理触摸交互和鼠标交互?
Ideally, the answer is yes. If not, I do have some options:
理想情况下,答案是肯定的。如果没有,我确实有一些选择:
1) We use WURFL to get device info so could create our own matrix of devices. Depending on the device, we'll use touchstart OR click.
1) 我们使用 WURFL 来获取设备信息,因此可以创建我们自己的设备矩阵。根据设备,我们将使用 touchstart 或 click。
2) Detect for touch support in the browser via JS (I need to do some more research on that, but it seems like that is doable).
2) 通过 JS 检测浏览器中的触摸支持(我需要对此做更多研究,但似乎这是可行的)。
However, that still leaves one issue: what about devices that support BOTH. Some of the phones we support (namely the Nokias and BlackBerries) have both touch screens andkeyboards. So that kind of takes me full circle back to the original question...is there a way to allow for both at once somehow?
然而,这仍然留下一个问题:支持两者的设备怎么样。我们支持的一些手机(即诺基亚和黑莓)同时具有触摸屏和键盘。所以这让我回到了最初的问题......有没有办法以某种方式同时允许两者?
采纳答案by Mottie
Update: Check out the jQuery Pointer Events Polyfillproject which allows you to bind to "pointer" events instead of choosing between mouse & touch.
更新:查看 jQuery Pointer Events Polyfill项目,它允许您绑定到“指针”事件,而不是在鼠标和触摸之间进行选择。
Bind to both, but make a flag so the function only fires once per 100ms or so.
绑定到两者,但制作一个标志,以便该函数每 100 毫秒左右只触发一次。
var flag = false;
$thing.bind('touchstart click', function(){
if (!flag) {
flag = true;
setTimeout(function(){ flag = false; }, 100);
// do something
}
return false
});
回答by Rafael Fragoso
This is the fix that I "create" and it take out the GhostClick and implements the FastClick. Try on your own and let us know if it worked for you.
这是我“创建”的修复程序,它去掉了 GhostClick 并实现了 FastClick。自己尝试一下,让我们知道它是否适合您。
$(document).on('touchstart click', '.myBtn', function(event){
if(event.handled === false) return
event.stopPropagation();
event.preventDefault();
event.handled = true;
// Do your magic here
});
回答by swooter
You could try something like this:
你可以尝试这样的事情:
var clickEventType=((document.ontouchstart!==null)?'click':'touchstart');
$("#mylink").bind(clickEventType, myClickHandler);
回答by Jonathan
Usually this works as well:
通常这也有效:
$('#buttonId').on('touchstart click', function(e){
e.stopPropagation(); e.preventDefault();
//your code here
});
回答by Roy
Just adding return false;
at the end of the on("click touchstart")
event function can solve this problem.
只需return false;
在on("click touchstart")
事件函数末尾添加即可解决此问题。
$(this).on("click touchstart", function() {
// Do things
return false;
});
From the jQuery documentation on .on()
来自.on()上的 jQuery 文档
Returning
false
from an event handler will automatically callevent.stopPropagation()
andevent.preventDefault()
. Afalse
value can also be passed for the handler as a shorthand forfunction(){ return false; }
.
false
从事件处理程序返回将自动调用event.stopPropagation()
和event.preventDefault()
。false
也可以为处理程序传递一个值作为 的简写function(){ return false; }
。
回答by Tim
I had to do something similar. Here is a simplified version of what worked for me. If a touch event is detected, remove the click binding.
我不得不做类似的事情。这是对我有用的简化版本。如果检测到触摸事件,则移除点击绑定。
$thing.on('touchstart click', function(event){
if (event.type == "touchstart")
$(this).off('click');
//your code here
});
In my case the click event was bound to an <a>
element so I had to remove the click binding and rebind a click event which prevented the default action for the <a>
element.
在我的例子中,click 事件绑定到一个<a>
元素,所以我必须删除 click 绑定并重新绑定一个 click 事件,这阻止了<a>
元素的默认操作。
$thing.on('touchstart click', function(event){
if (event.type == "touchstart")
$(this).off('click').on('click', function(e){ e.preventDefault(); });
//your code here
});
回答by Hasanavi
I succeeded by the following way.
我通过以下方式成功了。
Easy Peasy...
十分简单...
$(this).on('touchstart click', function(e){
e.preventDefault();
//do your stuff here
});
回答by DreamTeK
I believe the best practice is now to use:
我相信最好的做法是现在使用:
$('#object').on('touchend mouseup', function () { });
touchend
The touchend event is fired when a touch point is removed from the touch surface.
The touchend event will nottrigger any mouse events.
mouseup
The mouseup event is sent to an element when the mouse pointer is over the element, and the mouse button is released. Any HTML element can receive this event.
The mouseup event will nottrigger any touch events.
触摸端
当触摸点从触摸表面上移除时会触发 touchend 事件。
touchend 事件不会触发任何鼠标事件。
鼠标向上
当鼠标指针悬停在元素上并释放鼠标按钮时,mouseup 事件被发送到元素。任何 HTML 元素都可以接收此事件。
mouseup 事件不会触发任何触摸事件。
EXAMPLE
例子
$('#click').on('mouseup', function () { alert('Event detected'); });
$('#touch').on('touchend', function () { alert('Event detected'); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="click">Click me</h1>
<h1 id="touch">Touch me</h1>
EDIT (2017)
编辑 (2017)
As of 2017, browsers starting with Chrome and making steps towards making the click event .on("click")
more compatible for both mouse and touch by eliminating the delay generated by tap events on click requests.
截至 2017 年,浏览器从 Chrome 开始,并.on("click")
通过消除点击请求上的点击事件产生的延迟,使点击事件对鼠标和触摸更兼容。
This leads to the conclusion that reverting back to using just the click event would be the simplest solution moving forward.
这得出的结论是,恢复到仅使用点击事件将是最简单的解决方案。
I have not yet done any cross browser testing to see if this is practical.
我还没有做过任何跨浏览器测试,看看这是否可行。
回答by Justin808
Generally you don't want to mix the default touch and non-touch (click) api. Once you move into the world of touch it easier to deal only with the touch related functions. Below is some pseudo code that would do what you want it to.
通常你不想混合默认的触摸和非触摸(点击)api。一旦您进入触摸世界,只需处理与触摸相关的功能就更容易了。下面是一些可以做你想做的伪代码。
If you connect in the touchmove event and track the locations you can add more items in the doTouchLogic function to detect gestures and whatnot.
如果您在 touchmove 事件中连接并跟踪位置,您可以在 doTouchLogic 函数中添加更多项目以检测手势等。
var touchStartTime;
var touchStartLocation;
var touchEndTime;
var touchEndLocation;
$thing.bind('touchstart'), function() {
var d = new Date();
touchStartTime = d.getTime();
touchStartLocation = mouse.location(x,y);
});
$thing.bind('touchend'), function() {
var d = new Date();
touchEndTime= d.getTime();
touchEndLocation= mouse.location(x,y);
doTouchLogic();
});
function doTouchLogic() {
var distance = touchEndLocation - touchStartLocation;
var duration = touchEndTime - touchStartTime;
if (duration <= 100ms && distance <= 10px) {
// Person tapped their finger (do click/tap stuff here)
}
if (duration > 100ms && distance <= 10px) {
// Person pressed their finger (not a quick tap)
}
if (duration <= 100ms && distance > 10px) {
// Person flicked their finger
}
if (duration > 100ms && distance > 10px) {
// Person dragged their finger
}
}
回答by torbjon
check fast buttons and chost clicks from google https://developers.google.com/mobile/articles/fast_buttons
检查快速按钮和谷歌点击https://developers.google.com/mobile/articles/fast_buttons