E.preventDefault() не пуленепробиваемый?

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

$("#element")   .on( 'click', function() {
                    // do something
                } )             
                .on( 'touchstart', function(e) {
                    e.preventDefault();
                    // do the same thing but on touch device like iPad f.e.
                    // and more over PLEASE do not fire the click event also!
                } );

Я ожидаю, что событие click никогда никогда не запускается (из-за иерархии, с которой браузер должен работать через события), но на самом деле, когда я прикасаюсь к элементу, скажем 20 раз, чем один раз, когда срабатывает событие click, Почему?

И я также пробовал такие вещи, как:

$("#element")   .on( 'click', function() {
                    // do something
                } )             
                .on( 'touchstart', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    // do the same thing but on touch device like iPad f.e.
                    // and more over PLEASE do not fire the click event also!
                    return false;
                } );

Казалось, что он немного прочный, но не пуленепробиваемый. Поэтому я должен был сделать:

 $("#element")  .on( 'click', function() {
                    if ( !touchdevice ) {
                        // do something
                    };
                } )             
                .on( 'touchstart', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    // do the same thing but on touch device like iPad f.e.
                    // and more over PLEASE do not fire the click event also!
                    return false;
                } );

который, похоже, работает, но ужасно глупо, не так ли? Кто-нибудь с идеями, о чем это? Спасибо!

EDIT: Поэтому мне действительно нужно было сделать что-то вроде:

var touched;
$("#element")   .on( 'click', function() {
                    if ( !touched ) {
                        // do something
                    };
                } )             
                .on( 'touchstart', function(e) {
                    e.preventDefault();  // actual senseless here
                    e.stopPropagation(); // actual senseless here
                    touched = true;
                    // do the same thing but on touch device like iPad f.e.
                    // and more over PLEASE do not fire the click event also!
                    return false;        // actual senseless here
                } );

Давай, ребята! Должен существовать безопасный общий способ использования событий touchstart и click на одном элементе, гарантирующий, что событие click не будет запущено (дважды), чтобы обрабатывать как сенсорные, так и обычные браузеры (или даже новые комбинированные). Как вы это сделаете?

Ответ 1

Я ожидаю, что событие click никогда никогда не запускается (из-за иерархии, с которой браузер должен работать через события) [...]

У вас неправильные ожидания even.preventDefault().

event.preventDefault() предотвращает действие по умолчанию, которое браузер выполняет для этой комбинации элементов/событий. Например. отправив форму или следующую ссылку. Он не предотвращает выполнение любого другого обработчика событий.

e.stopPropagation() предотвращает буферизацию события, поэтому обработчики событий, добавленные к предкам, не выполняются.


Однако вы не можете использовать какой-либо из этих методов, чтобы предотвратить выполнение обработчиком другого события, поэтому установка флажка, действительно, является правильным способом для этого.

Ответ 2

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

var flag = false; 
$("#element").on( 'touchstart click', function() {
    if ( !flag ) {
        flag = true;
        setTimeout( function() {
            flag = false;
        }, 100 ); // someone else recommended 300 here but I use this value

        // action here

    };                
    return false;
} );

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