Как связать события «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 ]

0 голосов
/ 27 марта 2012

Я также работаю над веб-приложением для Android / iPad, и кажется, что для «перемещения компонентов» достаточно использовать только «touchmove» (нет необходимости в touchstart). Отключив сенсорный запуск, вы можете использовать .click (); из jQuery. Это на самом деле работает, потому что он не был перегружен сенсорным стартом.

Наконец, вы можете binb .live ("touchstart", function (e) {e.stopPropagation ();}); чтобы попросить событие touchstart прекратить распространение, нажмите кнопку (), чтобы вызвать событие.

Это сработало для меня.

0 голосов
/ 27 октября 2015

Я не уверен, работает ли это на всех браузерах и устройствах. Я проверил это с помощью Google Chrome и Safari iOS.

$thing.on('click || touchend', function(e){

});

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

0 голосов
/ 22 марта 2014

Для простых функций, просто распознайте касание или нажмите. Я использую следующий код:

var element = $("#element");

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

Это вернет «касание», если событие сенсорного запуска определено, и «нет касания», если нет.Как я уже сказал, это простой подход для событий щелчка / касания.

0 голосов
/ 21 февраля 2014

Если вы используете 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));

Другие решения тоже хороши, но я связывал несколько событий в цикле и нуждался в функции самовызывания, чтобы создать соответствующее замыкание,Кроме того, я не хотел отключать привязку, поскольку хотел, чтобы ее можно было вызывать при следующем щелчке / прикосновении.

Может помочь кому-то в подобной ситуации!

0 голосов
/ 24 сентября 2018

Это не было упомянуто здесь, но вы можете проверить эту ссылку: 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, которые будут срабатывать дважды, и на моем компьютере для разработки, который слышит толькоclick

Одна из проблем, о которой упоминает автор этой ссылки, заключается в том, что ноутбуки с сенсорным экраном предназначены для обработки обоих событий:

Я узнал о третьем устройстве, которое не рассматривал:сенсорный ноутбук.Это гибридное устройство, которое поддерживает события касания и нажатия.Привязка одного события означает, что поддерживается только это событие.Означает ли это, что кому-то с сенсорным экраном и мышью придется явно касаться, потому что это единственное событие, которое я обрабатываю?

Связывание touchstart и click казалось идеальным для работы с этими гибридными устройствами.Чтобы событие не запускалось дважды, я добавил e.stopPropagation() и e.preventDefault() к функциям обратного вызова.e.stopPropagation() предотвращает всплеск событий для их родителей, но также предотвращает запуск второго события.Я включил e.preventDefault() как «на всякий случай», но кажется, что это можно было бы опустить.

0 голосов
/ 02 апреля 2014

Я пытаюсь это, и пока это работает (но я только на 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...
  }

Мне не нравится тот факт, что я перепривязываю обработчики на каждомкасание, но все рассматриваемые вещи касаются не очень часто (в компьютерное время!)

У меня есть ТОННА обработчиков, таких как «#keypad», поэтому у меня есть простая функция, которая позволяет мне иметь дело спроблема без лишнего кода - вот почему я пошел по этому пути.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...