我正在开发一个需要在多种设备上运行的移动网站。目前让我头疼的是黑莓手机。

我们需要同时支持键盘点击和触摸事件。

理想情况下,我会使用:

$thing.click(function(){...})

但我们遇到的问题是,一些黑莓设备从触摸到触发点击有一个非常恼人的延迟。

补救方法是使用touchstart:

$thing.bind('touchstart', function(event){...})

但是如何绑定两个事件,但只触发一个事件呢?对于键盘设备,我仍然需要click事件,但当然,如果我使用的是触摸设备,我不想让click事件触发。

一个额外的问题:有没有办法做到这一点,并额外适应那些甚至没有touchstart事件的浏览器?在研究中,看起来黑莓OS5不支持touchstart,因此也需要依赖于该浏览器的点击事件。

附录:

也许一个更全面的问题是:

使用jQuery,是否可能/建议使用相同的绑定同时处理触摸交互和鼠标交互?

理想情况下,答案是肯定的。如果不是,我确实有一些选择:

我们使用WURFL来获取设备信息,这样就可以创建我们自己的设备矩阵。根据设备的不同,我们将使用touchstart或click。 通过JS检测浏览器中的触摸支持(我需要做更多的研究,但这似乎是可行的)。

然而,还有一个问题:支持这两种功能的设备怎么办?我们支持的一些手机(即诺基亚和黑莓)既有触摸屏又有键盘。这让我又回到了最初的问题……有没有一种方法可以同时兼顾两者?


当前回答

检查快速按钮和chost点击从谷歌https://developers.google.com/mobile/articles/fast_buttons

其他回答

为什么不使用jQuery事件API?

http://learn.jquery.com/events/event-extensions/

我成功地使用了这个简单的事件。它干净、可命名且足够灵活,可以继续改进。

var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var eventType = isMobile ? "touchstart" : "click";

jQuery.event.special.touchclick = {
  bindType: eventType,
  delegateType: eventType
};

对于简单的功能,只需识别触摸或点击我使用以下代码:

var element = $("#element");

element.click(function(e)
{
  if(e.target.ontouchstart !== undefined)
  {
    console.log( "touch" );
    return;
  }
  console.log( "no touch" );
});

如果定义了touchstart事件,它将返回“touch”,如果没有定义则返回“no touch”。就像我说的,这是一个简单的点击/点击事件的方法。

如果你正在使用jQuery,下面的工作对我来说很好:

var callback; // Initialize this to the function which needs to be called

$(target).on("click touchstart", selector, (function (func){
    var timer = 0;
    return function(e){
        if ($.now() - timer < 500) return false;
        timer = $.now();
        func(e);
    }
})(callback));

其他解决方案也很好,但我在一个循环中绑定多个事件,需要自调用函数来创建适当的闭包。此外,我不想禁用绑定,因为我希望它可以在下次单击/触摸启动时调用。

可能会帮助到有类似情况的人!

这里没有提到,但你可能想看看这个链接:https://joshtronic.com/2015/04/19/handling-click-and-touch-events-on-the-same-element/

为了便于后人回顾,您可以简单地检查设备是否是触摸屏并仅分配给相关事件,而不是尝试分配给两个处理程序然后对结果进行排序。观察:

var clickEvent = (function() {
  if ('ontouchstart' in document.documentElement === true)
    return 'touchstart';
  else
    return 'click';
})();

// and assign thusly:

el.addEventListener( clickEvent, function( e ){ 
    // things and stuff
});

我使用它来绑定我的事件,这样我就可以在触摸屏上测试,处理touchstart和click事件,会触发两次,在我的开发PC上只听到点击

不过,该链接的作者提到了一个问题,即设计用于处理这两种事件的触摸屏笔记本电脑:

I learned about a third device I was not considering, the touchscreen laptop. It’s a hybrid device that supports both touch and click events. Binding one event means only that event be supported. Does that mean someone with a touchscreen and mouse would have to explicitly touch because that’s the only event I am handling? Binding touchstart and click seemed ideal to handle these hybrid devices. To keep the event from firing twice, I added e.stopPropagation() and e.preventDefault() to the callback functions. e.stopPropagation() stops events from “bubbling up” to their parents but also keeps a second event from firing. I included e.preventDefault() as a “just in case” but seems like it could be omitted.

如果您已经在使用jQuery,有两种方法来处理这个问题,它们都非常简短。我认为它不需要像大多数答案那么复杂……

返回错误;

只需监听任何/所有事件,并在最后添加“return false;”以停止额外的重复事件处理。

thing$.on('click touchend',function(){
    // do Stuff
    return false; // stop
});

可重复使用的例子:

function bindClickAndTouchEvent(__targets$, __eventHandler){
    
    __targets$.on('click touchend',function(){
        __eventHandler.apply(this,arguments);// send original event
        return false;// but stop additional events
    });
}

// In-Line Usage:

bindClickAndTouchEvents( $('#some-element-id'), function(){ 
    console.log('Hey look only one click even when using touch on a touchscreen laptop') 
});

鼠标向上和触摸结束

根据您的用例,您可能只使用mouseup和touchend,因为这两个事件完全不重叠,只创建一个事件开始…然后你甚至不需要“return false;”。

thing$.on('mouseup touchend',function(){
    // do Stuff
});