I have a embeddable script that can be placed in the header of any host website. it fetched form and then attached submit event to them. it works in majority of the cases but on some websites, there are already event listeners attached to form. how can I make sure that my script works no matter the content of the host website. basically, if there are other event listeners attached to form, mine also gets executed
my current script
<script>
const handleSubmit = async (event) => {
event.preventDefault();
//my api call
};
const addEventListenersToForms = () => {
const forms = document.querySelectorAll("form");
forms.forEach((form) => {
if (!form.dataset.listenerAdded) {
form.addEventListener('submit', handleSubmit);
form.dataset.listenerAdded = 'true';
}
});
};
addEventListenersToForms();
</script>
i have tried multiple things but nothing is working out for me. one such case is captcha on form on some websites. this is just the example js code. basically my script will be deployed along with all the other code and a embeddable script will be given to users.
2
Answers
It might be due to when "addEventListenerToForms" is being called cause if it called before the DOM is fully loaded, it won’t find the forms.
There is many solutions i guess but the simplest one is wrapping your code inside DOMContentLoaded Eventlistener:
Like also commented the event listeners will be called in the order that they are add. But the order also depends on the element that they are attached to and the use of the useCapture parameter on the addEventListener() method. So, the solution depends on the event listeners that are already listening for the submit event.
First (to show the issue) an example of a setup where your event listener comes as the third out of four (five, with the overridden one):
Then an attempt to solve the issue
If you use the useCapture parameter on the addEventListener() method and set it to
true
the event listener will be in the capturing phase, and the callback function will be called before all the event listeners in the bubbling phase (default isfalse
). So, this only works if the other event listeners are NOT setting the useCapture totrue
…Btw. In your case, where you have more forms, you can just add the event listener to the document or any other parent element of all the forms, and you don’t have to track if an event listener is added or not.