Prevent click event after mousedown & mouseup event
Asked Answered
S

5

10

Is it possible with jQuery to prevent a click event on the same element from being executed, after a mousedown & mouseup event has just been fired.

Any help/examples would be appreciated.

Sphingosine answered 24/5, 2012 at 23:24 Comment(2)
I don't really get it, but a mousedown followed by a mouseup would be a click, and to just have a click work once, there's the one() method ?Luckey
may this help you #8875570Duteous
L
3

No one seems to have answered this one yet, at least not in an elegant way, so I figure I'll share the solution I found by NewbeDev (source: https://newbedev.com/cancel-click-event-in-the-mouseup-event-handler )

The answer is to use the capture phase, so before the event gets triggered on your element, all of its parents receive it during what's called the "capture phase". Then after that the event is delivered to your element followed by its parents in what's called the "bubbling phase".

The solution here is to just cancel the event at the top during the capture phase so it never reaches your element for the bubbling phase.

My use case was for a slider, so the code I used worked out to something like this:

slider.addEventListener('mousedown', ev => {
    // we start sliding (details omitted)

    function captureClick(e) {
        // we cancel the event and stop it from going further.
        // preventDefault() on its own should be enough for most cases
        // Your handler can also check e.defaultPrevented to know if preventDefault() was called
        e.preventDefault();
        // e.stopPropagation();
    }

   window.addEventListener('click', captureClick, true);
   document.addEventListener('mouseup', e => {
       // cleanup - we wait an extra frame to remove our capture 
       //           in case the click event is delayed
       requestAnimationFrame(() => {
           window.removeEventListener('click', captureClick, true);
       });
   });
});
Librarianship answered 15/7, 2022 at 16:27 Comment(0)
R
2

There's an awkward approach that is to disable the button when mousedown, and enable it after a short period, like 100ms. If the mouseup happens in this period, click won't be fired.

$('#btn').on('click', function() {
  alert('clicked')
});
$('#btn').on('mousedown', function() {
  var btn = $(this);
  btn.attr('disabled', 'disabled');
  setTimeout(function() { btn.removeAttr('disabled'); }, 100);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<button id='btn'>Click me</button>
</body>
Ricketts answered 9/11, 2016 at 9:17 Comment(0)
M
1

In Chrome and Internet Explorer, not Firefox though, detaching and reattaching the element at mousedown or mouseup will prevent the click event to be triggered. In Internet Explorer, this trick does not catch double-clicks though (in Chrome it does).

But I wouldn't rely on this strange behavior, who knows if it won't change at some point. Also, beware that detaching and reattaching can also have side-effects ont the children of the detached element (iframes reloading, file fields reset, ...).

Merralee answered 23/11, 2013 at 18:29 Comment(0)
C
1

There is a solution:

const COORDS = {
  xDown: null,
  xUp: null
}

const handleOnMouseDown = e => {
  e.preventDefault()
  COORDS.xUp = null
  COORDS.xDown = e.clientX
}

const handleMouseUp = e => {
  e.preventDefault()
  COORDS.xUp = e.clientX
}

const handleOnClick = e => {
  if (COORDS.xDown !== COORDS.xUp) {
    e.preventDefault()
    console.log('drag')
  } else {
    console.log('click')
  }
}

const el = document.getElementById('test')

el.addEventListener('mousedown', handleOnMouseDown)
el.addEventListener('mouseup', handleMouseUp)
el.addEventListener('click', handleOnClick)
#test {
  padding: 20px;
  display: block; 
  background: #ccc
}
<a href="#" id="test">Link</a>
Cairngorm answered 18/11, 2019 at 8:21 Comment(0)
M
-3

Yes, it should be possible if you return false; in the mouseup handler, because the onclick is fired after a mousedown and a mouseup have occurred. This is possible in regular javascript, so it should work with jquery event handlers as well.

EDIT:

Returning a boolean value from an event handler should actually be enough for event consumption. However, as this is very flaky across browsers you should use the function for manually canceling event bubbling:

event.stopPropagation();

where event is the parameter your event handler receives.

Mandorla answered 24/5, 2012 at 23:28 Comment(3)
There can be problems with this approach if both events are fired on the same element. Can you tell me exactly what you are trying to accomplish, then I can maybe provide a workaround.Mandorla
This is a bad answer - it is false. I also tried it and it didn't work.Carp
See the one year old edit! Did you try event.stopPropagation()? Also: returning false from an event handler is the method defined in the javascript standard, even if not all browser vendors hold to that standard. Don't downvote an answer because one of the proposed solutions didn't work for you.Mandorla

© 2022 - 2024 — McMap. All rights reserved.