javascripthtmlevent-delegationevent-propagation

Event doesn't propagate inside form


I'm feeling like someone just modified the past, i've been capturing dispatched submit events on keydown with enter keycode from contenteditable span-s inside a form with the same code for 4 years, and now an hour ago it stopped working.

The event is propagated from inside div/span, but not form.

What is happening, why is Form not receiving absolutely normally propagated events? Isn't it supposed to? Has it never?

<form id="form">
    <span id="input">input</b>
</form>
<script>
function log(event){
 document.body.appendChild(document.createElement("div")).textContent=
 [event.target.nodeName,event.type].join(" ");
}

form.addEventListener("submit",log);

function propagate(input){
 input.dispatchEvent(new Event("submit",{bubbles:true}));
 input.parentNode.dispatchEvent(new Event("submit",{bubbles:true}));
}

propagate(input);
</script>

With div: https://codepen.io/noderanger/pen/OPyOKQQ

With form: https://codepen.io/noderanger/pen/azvVgVR

expected: print 2 lines, SPAN submit and FORM submit

actual: only FORM submit is printed


Solution

  • You can check out this answered StackOverflow question to understand how event propagations in forms work:

    Why does the form submit event fire when I have stopped propagation at the submit button level?

    But here's a short explanation of why you're having this issue:

    So the behavior you’re seeing is intentional. submit is not a “normal” bubbling event like click. In the HTML specification, submit is dispatched by the form element itself when a submission is triggered (by pressing Enter in a text input, clicking a submit button, or calling form.requestSubmit()), not as a result of bubbling from a descendant.

    When you call:

    input.dispatchEvent(new Event("submit", { bubbles: true }));
    

    on a descendant element inside a <form>, the event may be retargeted or only seen by the form, depending on the browser’s implementation. That’s why you only see the FORM submit log. The event isn’t flowing “naturally” through the DOM from the span the way a click event would.

    Cheers! Hope this helps, happy building!