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

3 голосов
/ 20 июля 2012

проверка быстрых кнопок и простых кликов от Google https://developers.google.com/mobile/articles/fast_buttons

2 голосов
/ 25 апреля 2013

Только для целей документирования, вот что я сделал для самого быстрого / наиболее быстрого реагирования на рабочем столе / касании мобильного решения, о котором я только мог подумать:

Я заменил функцию on в jQuery на измененнуютот, который всякий раз, когда браузер поддерживает сенсорные события, заменял все мои события нажатия на сенсорный запуск.

$.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);
        };
    }()),
});

Использование, которое будет точно таким же, как и раньше, например:

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

Но этобудет использовать сенсорный запуск, когда доступно, нажмите, когда нет.Никаких задержек не требуется: D

2 голосов
/ 15 декабря 2014

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

<script> touchAvailable = false; </script>
<button ontouchstart="touchAvailable=true; myFunction();" onclick="if(!touchAvailable) myFunction();">Button</button>
2 голосов
/ 20 августа 2015

Вы можете попробовать вот так:

var clickEvent = (('ontouchstart' in document.documentElement)?'touchstart':'click');
$("#mylink").on(clickEvent, myClickHandler);
2 голосов
/ 28 апреля 2012

Еще одна реализация для лучшего обслуживания.Тем не менее, этот метод также будет делать event.stopPropagation ().Клик не фиксируется ни на одном другом элементе, который щелкал в течение 100 мс.

var clickObject = {
    flag: false,
    isAlreadyClicked: function () {
        var wasClicked = clickObject.flag;
        clickObject.flag = true;
        setTimeout(function () { clickObject.flag = false; }, 100);
        return wasClicked;
    }
};

$("#myButton").bind("click touchstart", function (event) {
   if (!clickObject.isAlreadyClicked()) {
      ...
   }
}
1 голос
/ 02 октября 2017

В моем случае это работало отлично:

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

Основная проблема заключалась в том, что вместо того, чтобы пытаться щелкнуть мышью, на сенсорных устройствах одновременно срабатывал щелчок и касание, если я использовал выключение, некоторые функции на мобильных устройствах вообще не работали. Проблема с щелчком состоит в том, что это глобальное событие, которое запускает остальную часть события, включая touchend.

1 голос
/ 05 августа 2014

Будучи для меня лучшим ответом, данным Мотти, я просто пытаюсь сделать его код более пригодным для повторного использования, так что это мой вклад:

bindBtn ("#loginbutton",loginAction);

function bindBtn(element,action){

var flag = false;
$(element).bind('touchstart click', function(e) {
    e.preventDefault();
    if (!flag) {
        flag = true;
        setTimeout(function() {
            flag = false;
        }, 100);
        // do something
        action();
    }
    return false;
});
1 голос
/ 04 декабря 2015

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

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

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

     var val = _step( _options.arrowStep );
               _evt('Button', [val, true]);
  });
0 голосов
/ 25 января 2017

найти разницу перемещений прокрутки документа (как горизонтальную, так и вертикальную), сенсорный запуск и касание, если один из них больше, чем 1 пиксель, то это перемещение, а не нажатие

var touchstartverscrollpos , touchstarthorscrollpos;


    $('body').on('touchstart','.thumbnail',function(e){

        touchstartverscrollpos = $(document).scrollTop();
        touchstarthorscrollpos = $(document).scrollLeft();


    });



    $('body').on('touchend','.thumbnail',function(e){


        var touchendverscrollpos = $(document).scrollTop();
        var touchendhorscrollpos = $(document).scrollLeft();

        var verdiff = touchendverscrollpos - touchstartverscrollpos;
        var hordiff = touchendhorscrollpos - touchstarthorscrollpos;


        if (Math.abs(verdiff) <1 && Math.abs(hordiff)<1){

// do you own function () here 



            e.stopImmediatePropagation();

            return false;
        }

    });
0 голосов
/ 06 декабря 2016

Лучший метод, который я нашел, - написать событие касания и заставить это событие вызывать событие обычного щелчка программно. Таким образом, у вас есть все ваши обычные события нажатия, а затем вам нужно добавить только один обработчик событий для всех событий касания. Для каждого узла, который вы хотите сделать сенсорным, просто добавьте в него класс «сенсорный», чтобы вызвать сенсорный обработчик. С Jquery это работает так с некоторой логикой, чтобы удостовериться, что это настоящее событие касания, а не ложное срабатывание.

$("body").on("touchstart", ".touchable", function() { //make touchable  items fire like a click event
var d1 = new Date();
var n1 = d1.getTime();
setTimeout(function() {
    $(".touchable").on("touchend", function(event) {
        var d2 = new Date();
        var n2 = d2.getTime();
        if (n2 - n1 <= 300) {
            $(event.target).trigger("click"); //dont do the action here just call real click handler
        }
    });
}, 50)}).on("click", "#myelement", function() {
//all the behavior i originally wanted
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...