Как связать события «touchstart» и «click», но не отвечать на оба? - PullRequest
187 голосов
/ 11 августа 2011

Я работаю над мобильным веб-сайтом, который должен работать на различных устройствах.В настоящий момент у меня болит голова: BlackBerry.

Мы должны поддерживать как нажатия клавиш, так и сенсорные события.

В идеале я бы просто использовал:

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

, но проблема, с которой мы сталкиваемся, заключается в том, что некоторые из этих устройств Blackberry имеют очень раздражающую задержку с момента прикосновения к нему.вызывая щелчок.

Вместо этого можно использовать сенсорный запуск:

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

Но как мне связать оба события, но только одно?Я все еще нуждаюсь в событии щелчка для клавиатурных устройств, но, разумеется, не хочу срабатывания события щелчка, если я использую сенсорное устройство.

Дополнительный вопрос: есть ли еще способ сделать это и дополнительно приспособитьсябраузеры, которые даже не имеют сенсорного запуска?При исследовании этого, похоже, что BlackBerry OS5 не поддерживает сенсорный запуск, поэтому для этого браузера также необходимо полагаться на события нажатия.

ADDENDUM:

Возможно, более всеобъемлющий вопрос:

С jQuery возможно / рекомендуется обрабатывать как сенсорные взаимодействия, так и взаимодействия мыши с одними и теми же привязками?

В идеале ответ - да.Если нет, у меня есть несколько вариантов:

1) Мы используем WURFL для получения информации об устройстве, чтобы создать собственную матрицу устройств.В зависимости от устройства мы будем использовать сенсорный запуск или щелчок.

2) Обнаружение сенсорной поддержки в браузере через JS (мне нужно провести дополнительное исследование по этому вопросу, но кажется, что это выполнимо).

Однако это все еще оставляет одну проблему: как насчет устройств, которые поддерживают ОБА.Некоторые из поддерживаемых нами телефонов (а именно Nokias и BlackBerries) оснащены сенсорными экранами и .Так что я снова возвращаюсь к первоначальному вопросу ... есть ли способ как-то учесть оба сразу?

Ответы [ 36 ]

129 голосов
/ 11 августа 2011

Обновление : ознакомьтесь с проектом jQuery Pointer Events Polyfill , который позволяет привязывать события «указателя» вместо выбора между мышью и касанием.


Привязать к обоим, но сделать флаг, чтобы функция срабатывала только один раз за 100 мс или около того.

var flag = false;
$thing.bind('touchstart click', function(){
  if (!flag) {
    flag = true;
    setTimeout(function(){ flag = false; }, 100);
    // do something
  }

  return false
});
71 голосов
/ 16 июля 2012

Это исправление, которое я «создаю», оно вынимает 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

});
48 голосов
/ 23 сентября 2011

Вы можете попробовать что-то вроде этого:

var clickEventType=((document.ontouchstart!==null)?'click':'touchstart');
$("#mylink").bind(clickEventType, myClickHandler);
42 голосов
/ 04 ноября 2012

Обычно это также работает:

$('#buttonId').on('touchstart click', function(e){
    e.stopPropagation(); e.preventDefault();
    //your code here

});
17 голосов
/ 06 апреля 2016

Простое добавление return false; в конце функции on("click touchstart") может решить эту проблему.

$(this).on("click touchstart", function() {
  // Do things
  return false;
});

Из документации по jQuery .on ()

Возвращение false из обработчика событий автоматически вызовет event.stopPropagation() и event.preventDefault(). Значение false также может быть передано для обработчика как сокращение для function(){ return false; }.

10 голосов
/ 18 декабря 2013

Я должен был сделать что-то подобное.Вот упрощенная версия того, что у меня сработало.Если событие касания обнаружено, удалите привязку щелчка.

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click');

  //your code here
});

В моем случае событие щелчка было привязано к элементу <a>, поэтому мне пришлось удалить привязку щелчка и повторно связать событие щелчка, которое предотвращалодействие по умолчанию для элемента <a>.

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click').on('click', function(e){ e.preventDefault(); });

  //your code here
});
7 голосов
/ 18 апреля 2012

Мне удалось следующим образом.

Easy Peasy ...

$(this).on('touchstart click', function(e){
  e.preventDefault();
  //do your stuff here
});
4 голосов
/ 11 августа 2011

Как правило, вы не хотите смешивать стандартные сенсорные и не сенсорные (щелчок) API.Перейдя в сенсорный мир, вам будет проще работать только с сенсорными функциями.Ниже приведен псевдокод, который будет делать то, что вы хотите.

Если вы подключитесь к событию 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
     }
}
4 голосов
/ 21 апреля 2017

Я полагаю, что сейчас рекомендуется использовать:

$('#object').on('touchend mouseup', function () { });

touchend

Событие touchend вызывается при удалении точки касания изповерхность касания.

Событие касания будет не запускать любые события мыши.


mouseup

MouseupСобытие отправляется элементу, когда указатель мыши находится над элементом и кнопка мыши отпущена.Это событие может получить любой элемент HTML.

Событие mouseup будет не вызывать любые события касания.

ПРИМЕР

$('#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>

РЕДАКТИРОВАТЬ (2017)

С 2017 года браузеры, начиная с Chrome и делающие шаги к созданиюсобытие щелчка .on("click") более совместимо как для мыши, так и для касания, устраняя задержку, генерируемую событиями касания при запросах щелчка.

Это приводит к выводу, что возврат к использованию только события щелчка будет самым простым решением.Движение вперед.

Я еще не проводил кросс-браузерное тестирование, чтобы проверить, насколько это практично.

3 голосов
/ 16 мая 2014

Ну ... Все это очень сложно.

Если у вас есть modernizr, это легко.

ev = Modernizr.touch ? 'touchstart' : 'click';

$('#menu').on(ev, '[href="#open-menu"]', function(){
  //winning
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...