4

I'm trying to disable every click events on a web pages.

document.addEventListener("click", function (e) {
    e.preventDefault();
    e.stopImmediatePropagation();
    let clicked = e.target;
    console.log(clicked);
  });

This is supposed to prevent every click event right? But I still find cases where it is ignored (mostly with links).

What am I missing?

Skully
  • 2,882
  • 3
  • 20
  • 31
Baptiste Arnaud
  • 2,522
  • 3
  • 25
  • 55
  • 2
    You could try adding `true` at the end: `}, true);` so that the the handler gets called in the capture phase, not the bubbling phase – blex Nov 19 '20 at 17:08
  • 2
    This "stops" click events that bubbled all the way up to the root element of the document. This doesn't stop event handlers or elements on that way to react on the "click" – Andreas Nov 19 '20 at 17:08
  • No, it only prevents click events on the `document` doing anything. The event will have done its normal thing before it bubbles up that high. – Robin Zigmond Nov 19 '20 at 17:10
  • It won't bubble up if you catch it in the capture phase, so adding `true` should do the job – blex Nov 19 '20 at 17:11
  • 1
    @blex Looks like it works! Thanks man – Baptiste Arnaud Nov 19 '20 at 17:11
  • @blex do we also need the e.stopPropagation()? https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation – Ozgur Sar Nov 19 '20 at 17:17
  • 1
    @ozgur I believe the `e.stopImmediatePropagation()` used here should be enough, based on some testing and [on this](https://stackoverflow.com/questions/5299740/stoppropagation-vs-stopimmediatepropagation). _"In addition to keeping any additional handlers on an element from being executed, this method also stops the bubbling by implicitly calling event.stopPropagation()"_ – blex Nov 19 '20 at 17:23

2 Answers2

6

The problem here is at what stage the event is captured by your handler (or intercepted). The code in your question is being executed for events that bubble up to the document (events whose propagation has not been stopped by elements further down the document tree) during the final phase of propagation, not for all events that occur on document (what you are after).

In your case, you effectively want to stop the execution of the event for all descendants during the "capture" phase - look at Section 3.1 - (the first phase of event propagation).

Add true to the call to execute in the capture phase:

document.addEventListener("click", function (e) {
 // ...
}, true);

You should also only need e.stopImmediatePropagation() in your handler.

Thomas
  • 6,291
  • 6
  • 40
  • 69
0

My experience was that the button in question, that I was in the process of binding an onclick event to, through jQuery (and attempting to use e.preventdefault(); on, to stop the incorrectly assumed form post from happening), was executing inline onclick javascript code (ie. onclick="window.location.href='www.xxx.xx'").

I didn't carefully inspect the button, and see this. I just assumed that it was a submit button in a FORM, and couldn't figure out why e.preventdefault was failing.... executing the form post, and bypassing my new event binding.

I guess the same might be true if it wasn't an inline window.location.href='www.xxx.xx', and just had an event binding from code somewhere else?

Jonno
  • 436
  • 1
  • 4
  • 13