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

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

理想情况下,我会使用:

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

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

补救方法是使用touchstart:

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

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

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

附录:

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

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

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

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

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


当前回答

你可以这样尝试:

var clickEvent = (('ontouchstart' in document.documentElement)?'touchstart':'click');
$("#mylink").on(clickEvent, myClickHandler);

其他回答

出于文档的目的,以下是我所能想到的最快/响应最快的桌面点击/移动点击解决方案:

我用一个修改过的函数替换了jQuery的on函数,只要浏览器支持触摸事件,就用touchstart替换了我所有的点击事件。

$.fn.extend({ _on: (function(){ return $.fn.on; })() });
$.fn.extend({
    on: (function(){
        var isTouchSupported = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
        return function( types, selector, data, fn, one ) {
            if (typeof types == 'string' && isTouchSupported && !(types.match(/touch/gi))) types = types.replace(/click/gi, 'touchstart');
            return this._on( types, selector, data, fn);
        };
    }()),
});

than的用法和以前完全一样,比如:

$('#my-button').on('click', function(){ /* ... */ });

但它会在可用时使用touchstart,在不可用时使用click。不需要任何形式的延误:D

这对我来说很有效,手机会同时监听两个,所以要防止触摸事件。桌面只听鼠标。

 $btnUp.bind('touchstart mousedown',function(e){
     e.preventDefault();

     if (e.type === 'touchstart') {
         return;
     }

     var val = _step( _options.arrowStep );
               _evt('Button', [val, true]);
  });

我正在尝试这个,到目前为止,它是有效的(但我只在Android/Phonegap上,所以买者自负)

  function filterEvent( ob, ev ) {
      if (ev.type == "touchstart") {
          ob.off('click').on('click', function(e){ e.preventDefault(); });
      }
  }
  $('#keypad').on('touchstart click', '.number, .dot', function(event) {
      filterEvent( $('#keypad'), event );
      console.log( event.type );  // debugging only
           ... finish handling touch events...
  }

我不喜欢的事实是,我重新绑定处理器上的每一个触摸,但所有的事情都认为触摸不会经常发生(在计算机时间!)

我有一个像“#键盘”这样的处理程序,所以有一个简单的函数,让我不用太多的代码就能处理问题,这就是我为什么这样做的原因。

在我的案例中,这非常有效:

jQuery(document).on('mouseup keydown touchend', function (event) {
var eventType = event.type;
if (eventType == 'touchend') {
    jQuery(this).off('mouseup');
}
});

主要的问题是,当我尝试点击鼠标时,在触摸设备上同时触发点击和触摸结束,如果我使用点击关闭,一些功能在移动设备上根本不起作用。click的问题是,它是一个全局事件,触发了事件的其余部分,包括touchend。

如果您已经在使用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
});