Search code examples
javascripthtmlcheckboxpreventdefaultdom-events

Canceling checkbox's click event prevents checking it?


I need to have a list of checkboxes with the condition that at least one of them must be checked.
The following code produces that effect.

document.querySelector('div').addEventListener('click', function(evt){
    if( this.querySelectorAll('input:checked').length == 0 )
        evt.preventDefault() ;
}) ;
<div>
    <input type=checkbox checked>
    <input type=checkbox>
    <input type=checkbox>
</div>

That's fine, however, I don't understand why this code even works.

Firstly, I'm doing a .preventDefault() on the click event only after I've checked the condition that says there are no checkboxes checked. So canceling the click event at this point should make no difference.

Secondly, the code works even if you try to check the checkboxes using the keyboard, which is totally weird because I'm only canceling the click event.

Please explain why the code works the way it does.


Solution

  • While an input event listener is running, its effect on the element's state is actually already performed. If event.preventDefault() is called, this change is undone when the listener returns. This allows a checkbox event handler to test the new state of the checkbox, and allows the handler for a keyboard event on a text input to test the value that includes the new input.

    The reason it works when you use the keyboard is that the click event is a high-level event that encompasses all the different ways to click on a checkbox: you can do it with the mouse, with they keyboard, with a touchscreen, etc. If you want to listen to a specific mode of clicking, you would have to use mousedown, keypress, etc.