Подтвердить что ты не робот

Предотвращение срабатывания события клика при срабатывании события dblclick

Я обрабатываю событие click и dblclick на элементе DOM. Каждый из них выполняет другую команду, но я обнаружил, что при двойном щелчке по элементу, помимо запуска события двойного щелчка, событие click также запускается дважды. Каков наилучший подход для предотвращения такого поведения?

4b9b3361

Ответ 1

В комментарии вы сказали:

Я задерживаю обработчик кликов на 300 мс (заметная и раздражающая задержка) и даже...

Итак, похоже, что вы хотите, чтобы при щелчке, DOM немедленно создала событие щелчка, за исключением того, что щелчок является первым щелчком двойного щелчка.

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


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

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

Ответ 2

Если кто-то еще наткнется на это (как и я), ища ответ, самым лучшим решением, которое я мог бы придумать, является следующее:       

    $node.on('click',function(e){
      if(e.originalEvent.detail > 1){
         return;
        /* if you are returning a value from this
         function then return false or cancel 
         the event some other way */
      }
    });

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

Я указал себе в этом направлении, прочитав this.


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

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

 if e.originalEvent.detail === 2 //return

однако, я смог нажать ссылку 3 раза (тройной щелчок), и хотя второй клик не срабатывал, третий сделал

Ответ 3

В этом случае лучше всего немного отсрочить выполнение события с одним кликом. Попросите обработчик двойного щелчка установить переменную, которую проверит событие с одним кликом. Если эта переменная имеет конкретное значение, может быть boolDoubleClick == true, а затем не fire/handle за один клик.

Ответ 4

Вы можете использовать UIEvent.detail если хотите определить, сколько раз был UIEvent.detail элемент, и UIEvent.detail события на его основе.

Простой пример:

element.addEventListener("click", function (e) {
  if (e.detail === 1) {
    // do something if the element was clicked once.
  } else if (e.detail === 2) {
    // do something else if the element was clicked twice
  }
});

Ответ 5

AFAIK DOM Уровни 2 События не дают спецификации для двойного щелчка. Это не работает для меня в IE7 (есть шок), но FF и Opera не имеют проблем с управлением спецификацией, где я могу прикрепить все действия к событию click, но для двойного щелчка просто подождите, пока атрибут "detail" объекта события - 2. Из документов: "Если в одном и том же месте экрана происходит несколько кликов, последовательность повторяется с добавлением атрибута детали с каждым повторением".

Ответ 6

Вот что я сделал, чтобы отличить внутри модуля

       node.on('click', function(e) {

            //Prepare for double click, continue to clickHandler doesn't come soon enough
            console.log("cleared timeout in click",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            _this.clickTimeout = setTimeout(function(){
                console.log("handling click");
                _this.onClick(e);
            },200);
            console.log(_this.clickTimeout);
        });

        node.on('dblclick', function (e) {

            console.log("cleared timeout in dblclick",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            // Rest of the handler function

Ответ 7

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

var pendingClick = 0;

function xorClick(e) {
    // kill any pending single clicks
    if (pendingClick) {
        clearTimeout(pendingClick);
        pendingClick = 0;
    }

    switch (e.detail) {
        case 1:
            pendingClick = setTimeout(function() {
                console.log('single click action here');
            }, 500);// should match OS multi-click speed
            break;
        case 2:
            console.log('double click action here');
            break;
        default:
            console.log('higher multi-click actions can be added as needed');
            break;
    }
}

myElem.addEventListener('click', xorClick, false);

Обновление: Я добавил обобщенную версию этого подхода вместе с кликом polyfill для сенсорных устройств для этого репозитория Github с примерами:

https://github.com/mckamey/doubleTap.js

Ответ 8

Я знаю, что это старое, как черт, но я думал, что я опубликую так или иначе, так как я просто столкнулся с той же проблемой. Вот как я это разрешил.

 $('#alerts-display, #object-display').on('click', ['.item-data-summary', '.item-marker'], function(e) {
    e.preventDefault();

    var id;

    id = setTimeout(() => {
       // code to run here
       return false;
    }, 150);

    timeoutIDForDoubleClick.push(id);
});


$('.panel-items-set-marker-view').on('dblclick', ['.summary', '.marker'], function(e) {
    for (let i = 0; i < timeoutIDForDoubleClick.length; i++) {
       clearTimeout(timeoutIDForDoubleClick[i]);
    }

    // code to run on double click

    e.preventDefault();
});

Ответ 9


  const toggle = () => {
      watchDouble += 1;
      setTimeout(()=>{
        if (watchDouble === 2) {
          console.log('double' + watchDouble)
        } else if (watchDouble === 1) {
          console.log("signle" + watchDouble)
        }
        watchDouble = 0
      },200);

  }