Why can't a mouseup event prevent a click event
Asked Answered
W

3

26

function h(e) {
  e.preventDefault();
  e.stopPropagation();
  e.stopImmediatePropagation();
  alert(e.type);
  return false;
}

document.querySelector('.wrapper').addEventListener('mouseup', h, false);
document.querySelector('.child').addEventListener('click', h, false);
<div class='wrapper'>
  <button class='child'>Click me</button>
</div>

I expect this to prevent the 'click' event from firing, but it doesn't. However, changing mouseup to mousedown does in fact prevent the click event.

I've also tried setting the useCapture argument to true, and that also doesn't produce the desired behavior with mouseup. I've tested this on Chrome and Firefox. Before I file bugs, I figured I'd ask here.

Is this a bug in current browsers, or is it documented behavior?

I've reviewed the W3C standard (DOM level 2), and I wasn't able to find anything that could explain this behavior, but I could have missed something.

In my particular case, I'm trying to decouple two pieces of code that listen to events on the same element, and I figured using capture events on the part that has priority would be the most elegant way to solve this, but then I ran into this problem. FWIW, I only have to support officially supported versions of FF and Chrome (includes ESR for FF).

Wages answered 20/8, 2013 at 18:45 Comment(4)
preventDefault and stopImmediatePropagation are unnecessary here (by the way), because there's no <form> so no submitting with the button, and no multiple events of the same type. And I think this is expected behavior because doesn't mouseup fire before click? So the .child's mouseup event fires (and bubbles) before its click event (which you have stopped, but it doesn't matter)Scrotum
@Scrotum - I added those in to make sure I didn't get comments like "have you tried x() or y()?". For your other comment, setting useCapture to true forces .wrapper's mouseup to happen before the bubble from child. I didn't include this code, because in either case, I should only get one alert() (with a different originating element), right?Wages
If you want to prevent a mouseclick, use this: jsfiddle.net/zhAHt/9Crapshooter
@user2645707 - That's not preventing anything. That's just a return before the alert(), which is not what I want... to actually use that I'd have to use a global...Wages
H
1

Check out this quirksmode article

The click event:

Fires when a mousedown and mouseup event occur on the same element.

So when the mouse click is released, both the mouseup and click events are fired, click doesn't wait for the mouseup callback to finish. Almost always, mouseup and click can be used synonymously.

In order to cancel the click, like you demonstrated, you can return false in the mousedown event callback which prevents the click event from ever completing.

Hoodoo answered 17/10, 2013 at 20:11 Comment(3)
That's incorrect, return false, o event.preventPropagation will stop the mouseup but no the click event.Tyrannize
@Tyrannize I think you are wrong. doing that on the mousedown seems to stop both moseup and click events from being triggered. See my answer... (I tested on chrome)Inhospitality
Just tried this and it doesn't workVoucher
N
1

Finally found a way to prevent click event from firing. Tested on latest Chromium and Firefox. It may be some bug or implementation details.

Solution

Handle onpointerdown or onpointerup event, remove the element and insert it in the same position.

<span>
    <button onpointerdown="let parent = this.parentElement; this.remove(); parent.appendChild(this);" onclick="alert();">TEST</button>
</span>

Result

onpointerdown
onmousedown
onpointerup
onmouseup
<-- no click event occures
N answered 26/12, 2022 at 21:39 Comment(1)
Works at least on Chrome, upvoted.Toothache
S
0

I just want to provide my work around for this issue:

let click_works = true
this.addEventListener('mousedown', e => {
    click_works = // condition why the click may work or not
})
this.addEventListener('click', e => {
    if (click_works) // Do your stuff
})

Hopefully, it will help someone.

Sisyphus answered 12/10, 2022 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.