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

Отменить событие click в обработчике событий mouseup

Написав некоторый код перетаскивания и удаления, я хотел бы отменить события кликов в обработчике mouseup. Я решил, что предотвращение дефолта должно делать трюк, но событие click по-прежнему запущено.

Есть ли способ сделать это?


Это не работает:

<div id="test">test</div>
<script>
$("#test").mouseup (function (e) {
  var a = 1;
  e.preventDefault();
});
$("#test").click (function (e) {
  var a = 2;
});
4b9b3361

Ответ 1

У меня была та же проблема, и я тоже не нашел решения. Но я придумал хак, который, похоже, работает.

Так как обработчик onMouseUp, похоже, не может отменить щелчок по ссылке с preventDefault или stopEvent или что-то еще, нам нужно заставить ссылку отменить себя. Это можно сделать, написав атрибут onclick, который возвращает false в тег a при начале перетаскивания и удаляет его при завершении перетаскивания.

И поскольку обработчики onDragEnd или onMouseUp запускаются до того, как браузер интерпретируется щелчком мыши, нам нужно выполнить некоторую проверку, где заканчивается перетаскивание, и какая ссылка нажата и так далее. Если он заканчивается за пределами перетаскиваемой ссылки (мы перетащили ссылку, чтобы курсор больше не был в ссылке), мы удалим обработчик onclick в onDragEnd; но если он заканчивается там, где курсор находится на перетаскиваемой ссылке (щелчок будет инициирован), мы позволяем обработчику onclick удалять себя. Сложно, правильно?

НЕ ПОЛНЫЙ КОД, но просто для того, чтобы показать вам идею:

// event handler that runs when the drag is initiated
function onDragStart (args) {
  // get the dragged element
  // do some checking if it a link etc
  // store it in global var or smth

  // write the onclick handler to link element
  linkElement.writeAttribute('onclick', 'removeClickHandler(this); return false;');
}

// run from the onclick handler in the a-tag when the onMouseUp occurs on the link
function removeClickHandler (element) {
  // remove click handler from self
  element.writeAttribute('onclick', null);
}

// event handler that runs when the drag ends
function onDragEnds (args) {
  // get the target element

  // check that it not the a-tag which we're dragging,
  // since we want the onclick handler to take care of that case
  if (targetElement !== linkElement) {
    // remove the onclick handler
    linkElement.writeAttribute('onclick', null);
  }
}

Надеюсь, это даст вам представление о том, как это можно сделать. Как я уже сказал, это не полное решение, просто объясняющее концепцию.

Ответ 2

Используйте фазу захвата события

Поместите элемент вокруг элемента, для которого вы хотите отменить событие click, и добавьте к нему обработчик события захвата.

var btnElm = document.querySelector('button');

btnElm.addEventListener('mouseup', function(e){
    console.log('mouseup');
    
    window.addEventListener(
        'click',
        captureClick,
        true // <-- This registeres this listener for the capture
             //     phase instead of the bubbling phase!
    ); 
});

btnElm.addEventListener('click', function(e){
    console.log('click');
});

function captureClick(e) {
    e.stopPropagation(); // Stop the click from being propagated.
    console.log('click captured');
    window.removeEventListener('click', captureClick, true); // cleanup
}
<button>Test capture click event</button>

Ответ 3

Есть решение!

Этот подход работает для меня очень хорошо (по крайней мере, в Chrome):

в mousedown я добавляю класс к элементу, который в данный момент перемещается, а при mouseup я mouseup класс.

Все, что делает класс, это устанавливает pointer-events:none

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

Ответ 4

Проблема есть элемент. Он должен отвечать на клики. Его также нужно перетащить. Однако при перетаскивании ему не нужно запускать клик при его удалении.

Немного поздно, но, возможно, это поможет кому-то другому. Создайте глобальную переменную с именем "noclick" или что-то еще и установите для нее значение false. При перетаскивании элемента установите значение noclick равным true. В обработчике кликов, если noclick имеет значение true, установите значение false, а затем preventDefault, верните false, stopPropagation и т.д. Это не будет работать в Chrome, хотя Chrome уже имеет желаемое поведение. Просто сделайте так, чтобы функция drag только установила noclick в true, если браузер не Chrome.

Ваш обработчик клика по-прежнему будет запущен, но, по крайней мере, у него есть способ узнать, что он только что вернулся из режима drag and behave соответственно.

Ответ 5

Лучшее решение для моей ситуации было:

el.addEventListener('mousedown', (event) => {
  clickTime = new Date()
})

el.addEventListener('click', (event) => {
  if (new Date() - clickTime < 150) {
    // do something
  }
})

Это дает пользователю 150 мс для освобождения, если он занимает больше 150 мс, это считается паузой, а не щелчком

Ответ 6

Поскольку они являются разными событиями, вы не можете отменить onclick от onmouseup, если вы вызываете preventDefault или cancelBubble или что-то еще, вы прекращаете дальнейшее событие onmouseup. Событие onclick все еще ожидается, но его нужно уволить, так сказать.

Что вам нужно, это ваш собственный логический флаг, например. isDragging. Вы можете установить значение true при перетаскивании (например, внутри onmousedown или что-то еще).

Но если вы reset это ложно непосредственно из onmouseup, вы больше не будете перетаскивать, когда получаете событие onclick (isDragging == false), потому что onmouseup срабатывает перед onclick.

Итак, вам нужно использовать короткий тайм-аут (например, setTimeout(function() {isDragging = false;}, 50);), поэтому при запуске события onclick isDragging по-прежнему будет true, а ваш обработчик событий onclick может просто есть if(isDragging) return false;, прежде чем он сделает что-нибудь еще.

Ответ 7

Возможно, это возможно, но я не уверен, что вы можете управлять этим видом управления evt с помощью jQuery. Этот пример кода не должен быть далеко от вашего ожидания или, по крайней мере, дать вам направление.

function AddEvent(id, evt_type, ma_fonction, phase) {
    var oElt = document.getElementById(id);
    // modèle W3C mode bubbling
    if( oElt.addEventListener ) {
        oElt.addEventListener(evt_type, ma_fonction, phase);
    // modèle MSIE
    } else if( oElt.attachEvent ) {
        oElt.attachEvent('on'+evt_type, ma_fonction);
    }
    return false;
}

function DelEvent(id, evt_type, ma_fonction, phase) {
    var oElt = document.getElementById(id);
    // modèle W3C mode bubbling
    if( oElt.removeEventListener ) {
        oElt.removeEventListener(evt_type, ma_fonction, phase);
    // modèle MSIE
    } else if( oElt.detachEvent ) {
        oElt.detachEvent('on'+evt_type, ma_fonction);
    }
    return false;
}

    var mon_id = 'test';
    var le_type_evt = "mouseup";
    var flux_evt = false; // prevent bubbling
    var action_du_gestionnaire = function(e) {
        alert('evt mouseup on tag <div>');

        // 1ère méthode : DOM Lev 2
        // W3C
            if ( e.target )
                e.target.removeEventListener(le_type_evt, arguments.callee, flux_evt);
        // MSIE
            else if ( e.srcElement )
                e.srcElement.detachEvent('on'+le_type_evt, arguments.callee);

        // 2ème méthode DOM Lev2
        // DelEvent(mon_id, le_type_evt, action_du_gestionnaire, flux_evt);
    };


    AddEvent(mon_id, le_type_evt, action_du_gestionnaire, flux_evt);

Ответ 8

Недавно я столкнулся с той же проблемой. Вот мое решение:)

    initDrag: function (element) {
        var moved = false,
            target = null;

        function move(e) {
            // your move code
            moved = true;
        };

        function end(e) {
            var e = e || window.event,
                current_target = e.target || e.srcElement;

            document.onmousemove = null;
            document.onmouseup = null;

            // click happens only if mousedown and mouseup has same target
            if (moved && target === current_target) 
                element.onclick = click;

            moved = false;
        };

        function click(e) {
            var e = e || window.event;

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

            // this event should work only once
            element.onclick = null;
        };

        function init(e) {
            var e = e || window.event;
            target = e.target || e.srcElement;

            e.preventDefault();

            document.onmousemove = move;
            document.onmouseup = end;
        };

        element.onmousedown = init;
    };

Ответ 9

Это мое решение для перетаскивания и клика по тому же элементу.

$('selector').on('mousedown',function(){
  setTimeout(function(ele){ele.data('drag',true)},100,$(this));
}).on('mouseup',function(){
  setTimeout(function(ele){ele.data('drag',false)},100,$(this));
}).on('click',function(){
  if($(this).data('drag')){return;}
  // put your code here
});

Ответ 10

Решение, которое я использую, заключается в следующем:

var disable_click = false;

function click_function(event){
    if (!disable_click){
        // your code
    }
}

function mouse_down_function(event){
    disable_click = false; // will enable the click everytime you click
    // your code
}

function mouse_up_function(event){
    // your code
}

function mouse_drag_function(event){
    disable_click = true; // this will disable the click only when dragging after clicking
   // your code
}

прикрепить каждую функцию к соответствующему событию в соответствии с именем!

Ответ 11

Мое решение не требует глобальных переменных или тайм-аутов или изменения html-элементов, просто jquery, который, безусловно, имеет некоторый уровень в простой js.

Я объявляю функцию для onClick

function onMouseClick(event){
     // do sth
}

Я объявляю функцию для MouseDown (вы также можете сделать то же самое при наведении мыши), чтобы решить, обрабатывать событие onclick или нет

function onMouseDown(event){
     // some code to decide if I want a click to occur after mouseup or not
    if(myDecision){
        $('#domElement').on("click", onMouseClick);
    }
    else $('#domElement').off("click");
} 

Краткое примечание: вы должны убедиться, что
$('#domElement').on("click", onMouseClick); не выполняется несколько раз. Сдается мне, что в случае, если это onMouseClick будет вызываться несколько раз.

Ответ 12

$(document).mouseup(function(event){ // make sure to set the event parameter
    event.preventDefault(); // prevent default, like you said
});

Важно отметить параметр event.

EDIT: Вы хотите отменить перетаскивание?

Способ, которым я это знаю, - либо использовать bind() (для более старых версий jQuery), либо on() (для jQuery 1.7+), чтобы прикрепить событие mousedown, затем используйте unbind() или off() соответственно для отсоедините его.

$(document)
    .on("mousedown", function(){...})
    .on("mouseup", function(){
        $(document).off("mousedown");
    });

Ответ 13

$(document).mouseup(function(event){

    event.preventDefault(); // this prevents only a default action but previously assigned listeners will be called
    event.stopImmediatePropagation() // if there are  others listeners which that shouldn't call 
}

Ответ 14

Если вы хотите подавить событие click, вы добавите оператор event.preventDefault() только в обработчик события клика, а не обработчик события mouseup. Используйте приведенный ниже код, который вы получите.

<div id="test">test</div>
<script>
$("#test").mouseup (function (e) {
  var a = 1;

});
$("#test").click (function (e) {
 e.preventDefault();
  var a = 2;
});

Надеюсь, что это решает вашу проблему.