I encountered this situation recently (simplified here). Simply wrap a checkbox with an element and apply preventDefault() on it's click event and the checkbox becomes uncheckable.
See this fiddle, but here's a snip:
<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 occurs in Chrome and FF, so I assume it is intentional.
Why does the click event, which has already been triggered on the checkbox itself not result in the checkbox getting toggled? The preventDefault
on the ancestor seems like it ought to be irrelevant to the child checkbox's behavior. It seems as if, for the checkbox change to occur, the click event needs to bubble freely all the way to the document root.
What's going on here?
The preventDefault on the ancestor seems like it ought to be irrelevant to the child checkbox's behavior.
No, not really. The event bubbles, and all handlers (including the ones on ancestors) may affect it.
It seems as if, for the checkbox change to occur, the click event needs to bubble freely all the way to the document root.
Not exactly. It doesn't need to arrive at the document root, but it must not have been default-prevented.
You might want to read the architecture notes in the DOM spec on event flow, default actions and cancelable events.
So what does happen step-by-step?
<input>
<div>
, it is handled. Your event listener calls the preventDefault
method, setting an internal cancelled
flag.If you uncomment the second part of your code, steps 6+ look different:
<input>
. Your listener calls the stopPropagation
methodpreventDefault
prevents the browser's default action from being fired. Changing the checked state of a checkbox or following the href
of an anchor, submitting a form, etc., are default actions. preventDefault
prevents them, while allowing event propagation.
This is distinct from event propagation, (which you may – as you've noted – stop by stopPropagation
). The event will propagate throughout the entire hierarchy of listeners before invoking the browser's default behavior (unless prevented).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With