Отмените событие DOM «Click», если CustomEvent запускает элемент - PullRequest
0 голосов
/ 21 мая 2019

Я создаю приложение в Cordova и, как и многие другие приложения, пытаюсь реализовать события длительного нажатия, которые происходят после удержания элемента.

Я использую https://github.com/john-doherty/long-press-event, который запускает CustomEvent под названием «длительное нажатие» после удержания элемента в течение 1,5 секунд.

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

Событие длинного нажатия срабатывает, но событие 'Click' также срабатывает каждый раз, и я не могу найти, как или когда мне следует попытаться остановить его срабатывание. Я пробовал несколько мест размещения stopDefault() и stopPropogation() безрезультатно.

HTML-код со слушателем

<div class="grid-col grid-col--1">
    <div class="grid-item bd bdrs-4 bdw-1 bdc-grey-400">
        <img class="portfolio-img lightbox-img" src="https://glamsquad.sgp1.cdn.digitaloceanspaces.com/GlamSquad/artist/1/portfolio/2019-05-16-06-07-370bc89b7bfe9769740c1f68f7e103340a94aaaeaa5d6f139f841e3c022ad309de.png">
    </div>
    <div class="grid-item bd bdrs-4 bdw-1 bdc-grey-400">
        <img class="portfolio-img lightbox-img" src="https://glamsquad.sgp1.cdn.digitaloceanspaces.com/GlamSquad/artist/1/portfolio/2019-05-16-06-07-38d8d03cc6edef043d25e9099b883cd235c823a267ab03b9e740934f06c4f87e2f.png">
    </div>
</div>

пока код JS прослушивает щелчок по лайтбоксу-img или долгое нажатие на изображение портфолио

$(document).on('long-press', '.portfolio-img', (e) => {
    e.preventDefault();
    e.stopPropagation();
    console.log('Portfolio long press event.');
 });
$(document).on('click', '.lightbox-img', imageClick);

Существует ли какой-либо фактический способ вызвать событие длительного нажатия, но можно ли отменить или остановить событие щелчка?

Ответы [ 3 ]

1 голос
/ 21 мая 2019

Один из способов сделать это - отключить pointer-events в элементе, по которому вы щелкнули, с момента возникновения события long-press и до следующего события mouseup в документе.

Лучше всего, вероятно, сделать это из вашей библиотеки, так что вот ветвь этой библиотеки, которая теперь предоставляет метод preventDefaultClick() для CustomEvent:

(function (window, document) {

    'use strict';

    var timer = null;

    // check if we're using a touch screen
    var isTouch = (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));

    // switch to touch events if using a touch screen
    var mouseDown = isTouch ? 'touchstart' : 'mousedown';
    var mouseOut = isTouch ? 'touchcancel' : 'mouseout';
    var mouseUp = isTouch ? 'touchend' : 'mouseup';
    var mouseMove = isTouch ? 'touchmove' : 'mousemove';

    // wheel/scroll events
    var mouseWheel = 'mousewheel';
    var wheel = 'wheel';
    var scrollEvent = 'scroll';

    // patch CustomEvent to allow constructor creation (IE/Chrome)
    if (typeof window.CustomEvent !== 'function') {

        window.CustomEvent = function(event, params) {

            params = params || { bubbles: false, cancelable: false, detail: undefined };

            var evt = document.createEvent('CustomEvent');
            evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
            return evt;
        };

        window.CustomEvent.prototype = window.Event.prototype;
    }

    // listen to mousedown event on any child element of the body
    document.addEventListener(mouseDown, function(e) {
        var el = e.target;
        // get delay from html attribute if it exists, otherwise default to 1500
        var longPressDelayInMs = parseInt(el.getAttribute('data-long-press-delay') || '1500', 10);
        // start the timer
        timer = setTimeout(fireLongPressEvent.bind(el, e), longPressDelayInMs);
    });

    // clear the timeout if the user releases the mouse/touch
    document.addEventListener(mouseUp, function() {
        clearTimeout(timer);
    });

    // clear the timeout if the user leaves the element
    document.addEventListener(mouseOut, function() {
        clearTimeout(timer);
    });

    // clear if the mouse moves
    document.addEventListener(mouseMove, function() {
        clearTimeout(timer);
    });

    // clear if the Wheel event is fired in the element
    document.addEventListener(mouseWheel, function() {
        clearTimeout(timer);
    });

    // clear if the Scroll event is fired in the element
    document.addEventListener(wheel, function() {
        clearTimeout(timer);
    });

    // clear if the Scroll event is fired in the element
    document.addEventListener(scrollEvent, function() {
        clearTimeout(timer);
    });

    /**
     * Fires the 'long-press' event on element
     * @returns {void}
     */
    function fireLongPressEvent() {
        var evt = new CustomEvent('long-press', { bubbles: true, cancelable: true });
        // Expose a method to prevent the incoming click event
        var el = this;
        evt.preventDefaultClick = function() {
          // disable all pointer-events
          el.style["pointer-events"] = "none";
          // reenable at next mouseUp
          document.addEventListener(mouseUp, e => {
            el.style["pointer-events"] = "all";
          }, {once: true});
        };
        // fire the long-press event
        this.dispatchEvent(evt);

        clearTimeout(timer);
    }

}(window, document));

btn.addEventListener('click', e => console.log('clicked'));
btn.addEventListener('long-press', e => {
  console.log('long-press');
  e.preventDefaultClick(); // prevents the incoming 'click' event
});
<button data-long-press-delay="500" id="btn">click me</button>

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

(function (window, document) {

    'use strict';

    var timer = null;

    // check if we're using a touch screen
    var isTouch = (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));

    // switch to touch events if using a touch screen
    var mouseDown = isTouch ? 'touchstart' : 'mousedown';
    var mouseOut = isTouch ? 'touchcancel' : 'mouseout';
    var mouseUp = isTouch ? 'touchend' : 'mouseup';
    var mouseMove = isTouch ? 'touchmove' : 'mousemove';

    // wheel/scroll events
    var mouseWheel = 'mousewheel';
    var wheel = 'wheel';
    var scrollEvent = 'scroll';

    // patch CustomEvent to allow constructor creation (IE/Chrome)
    if (typeof window.CustomEvent !== 'function') {

        window.CustomEvent = function(event, params) {

            params = params || { bubbles: false, cancelable: false, detail: undefined };

            var evt = document.createEvent('CustomEvent');
            evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
            return evt;
        };

        window.CustomEvent.prototype = window.Event.prototype;
    }

    // listen to mousedown event on any child element of the body
    document.addEventListener(mouseDown, function(e) {
        var el = e.target;
        // get delay from html attribute if it exists, otherwise default to 1500
        var longPressDelayInMs = parseInt(el.getAttribute('data-long-press-delay') || '1500', 10);
        // start the timer
        timer = setTimeout(fireLongPressEvent.bind(el, e), longPressDelayInMs);
    });

    // clear the timeout if the user releases the mouse/touch
    document.addEventListener(mouseUp, function() {
        clearTimeout(timer);
    });

    // clear the timeout if the user leaves the element
    document.addEventListener(mouseOut, function() {
        clearTimeout(timer);
    });

    // clear if the mouse moves
    document.addEventListener(mouseMove, function() {
//        clearTimeout(timer);
    });

    // clear if the Wheel event is fired in the element
    document.addEventListener(mouseWheel, function() {
//        clearTimeout(timer);
    });

    // clear if the Scroll event is fired in the element
    document.addEventListener(wheel, function() {
//        clearTimeout(timer);
    });

    // clear if the Scroll event is fired in the element
    document.addEventListener(scrollEvent, function() {
//        clearTimeout(timer);
    });

    /**
     * Fires the 'long-press' event on element
     * @returns {void}
     */
    function fireLongPressEvent() {
        var evt = new CustomEvent('long-press', { bubbles: true, cancelable: true });
        // Expose a method to prevent the incoming click event
        var el = this;
        evt.preventDefaultClick = function() {
          // disable all pointer-events
          el.style["pointer-events"] = "none";
          // reenable at next mouseUp
          document.addEventListener(mouseUp, e => {
            el.style["pointer-events"] = "all";
          }, {once: true});
        };
        // fire the long-press event
        this.dispatchEvent(evt);

        clearTimeout(timer);
    }

}(window, document));

btn.addEventListener('click', e => console.log('clicked'));
btn.addEventListener('long-press', e => {
  console.log('long-press');
  e.preventDefaultClick(); // prevents the incoming 'click' event
});
<button data-long-press-delay="500" id="btn">click me</button>
0 голосов
/ 21 мая 2019

Вы можете использовать логическое значение вместе с mousedown и mouseup слушателями

var timeoutId = 0, isHold = false;

$('#ele').on('mousedown', function() {
  timeoutId = setTimeout(onEleHold, 1000);
}).on('mouseup', function() {
  if (!isHold) {
    onEleClick();
  }
  isHold = false;
  clearTimeout(timeoutId);
  timeoutId = 0;
});

function onEleHold() {
  console.log('hold');
  isHold = true;
}

function onEleClick() {
  console.log('click');
}
#ele {
  background: black;
  width: 100px;
  height: 20px;
  color: white;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="ele">Click Here</div>
0 голосов
/ 21 мая 2019

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

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

var longClickTriggered = false;

$(document).on('long-press', '.portfolio-img', (e) => {
    longClickTriggered = true;
    //e.preventDefault();   // these 2 lines are probably not needed now
    //e.stopPropagation();
    console.log('Portfolio long press event.');
});

$(document).on('click', '.lightbox-img', (e) => {
    if (!longClickTriggered) {
        imageClick();
    }
    longClickTriggered = false;
});

Я прокомментировал эти строки ...

e.preventDefault();
e.stopPropagation();

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

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