Why does preventDefault () in the parent element disable the disable flag?

I recently ran into this situation (simplified here). Just wrap the checkbox with the element and apply preventDefault () on it with the click event, and the checkbox will become unavailable.

Check out this script , but here's a snapshot:

<div> <input type="checkbox"/> </div> /* Wrapper could be any element (and any ancestor element will work) */ $('div').on('click', function(e){ e.preventDefault(); }); /* Uncomment to make the checkbox work again $('input').on('click', function(e){ e.stopPropagation(); }); */ 

The behavior happens in Chrome and FF, so I assume this is intentional.

Why does the click event that was already fired with this flag not cause the flag to be enabled? preventDefault for the ancestor seems to be irrelevant for the child's checkbox behavior. It looks like the click event should bubble freely to the root of the document to change the flag.

What's going on here?

+7
source share
2 answers

Default prevention for the ancestor seems to be irrelevant for the child's checkbox behavior.

No, not at all. Event templates and all handlers (including ancestors) can affect it.

It seems that to change the flag, the click event should bubble freely to the root of the document.

Not really. He did not need to go to the root of the document, but it could not be prevented by default.

You might want to read the architecture notes in the DOM specification for event flow , default actions, and rollback events .

So what happens step by step?

  • Check the box
  • He is being checked.
  • The event is dispatched to the document root
  • (Not in IE): capture phase , nothing happens to your handlers.
  • The event arrives at <input>
  • ... and begins to bubble
  • In the <div> it is being processed. Your event listener calls the preventDefault method, setting the cancelled internal flag.
  • It bubbles, but nothing happens.
  • Since the event was canceled, the default action should not be performed, and the reset flag in its previous state.

If you uncomment the second part of the code, steps 6+ look different:

  1. The event is processed on <input> . Your listener calls the stopPropagation method
  2. ..., which leads to skipping the bubbling phase. (Div-listener will never be called)
  3. The default action was not prevented, and the check box is selected.
+9
source

preventDefault prevents the launch of the default action in the browser. Changing the specified state of the flag or after href anchors, submitting a form, etc. These are the default actions. preventDefault prevents them by allowing event propagation.

This is different from event propagation (that you can, as you noted, stop at stopPropagation ). The event will propagate throughout the listener hierarchy before invoking the default behavior of the browser (if not prevented).

+5
source

All Articles