disabling click events for all elements that contain a certain class

It seems a very straight forward problem but I cannot find a proper way of solving this. How would I be able to have one master class that disables all the click events for this element.

Let’s say I have a lot of different buttons and if any of these buttons contain the class btn-disabled I want it to disable all the click events attached to this element.

Example

$(document).on('click', '.btn-disabled', function() {
  return false;
});

$(document).on('click', '.button:not(.btn-special)', function() {
    alert('You have clicked the button!');
});

$(document).on('click', '.button.btn-special', function() {
    alert('You have clicked the special button!');
});

<div class='button'>
  Enabled Button
</div>

<div class='button btn-special'>
  Enabled Special Button
</div>

<div class='button btn-disabled'>
  Disabled Button
</div>

<div class='button btn-special btn-disabled'>
  Disabled Special Button
</div>

JSFiddle: https://jsfiddle.net/1eyrpbLo/1/

I expected for the disabled buttons to not have any alerts popping up but instead they currently just work like the non-disabled buttons. What am I missing?

Answer

One of the big problems is that jQuery only attaches and listens to bubbling events. If you attach a listener to the document, it will only ever run after all intermediate listeners (between the clicked element and the document) have fired.

I’d use vanilla JS instead, so that you can attach a listener in the capturing phase, before the event captures down to the target. Then stopPropagation will prevent the event from reaching the target in the first place.

document.addEventListener(
  'click',
  (e) => {
    if (e.target.closest('.btn-disabled')) {
      e.stopPropagation();
    }
  },
  true // attach in capturing phase
);

If you do this, you can then add listeners as you wish to any buttons (or even to the document) using jQuery – and any clicked buttons that happen to have a btn-disabled class (or an ancestor element with a btn-disabled class) will not have their click handlers fire, regardless of whether the listener is attached to the button or a parent element.