innerHTML made event listeners ineffective in one website but not in others

In one website, I have appended HTML to the <body> with innerHTML ( which was a mistake and I should have used insertAdjacentHTML() ).

newHTML = document.querySelector("body");
newHTML.innerHTML +=`
<!-- -->
`;

I have learned that innerHTML (when used on the <body> tag), makes all event listeners ineffective.
Indeed, even that most minor HTML change to the body tag with innerHTML prevented me to listen to the click event on a “burger” navigation menu of that website until refreshing the page.
I couldn’t replicate this behavior here on sitepoint.com but I could replicate it on cnn.com and the only way I can explain this is that sitepoint doesn’t use any JavaScript for its “burger” navigation menu but CNN do uses JavaScript for its mobile menu.
Would you have anything to add upon my conclusion?

It does – if you inspect the burger menu with the browser dev tools and switch to the “Event Listeners” tab, you can see a couple of click handlers but none added to the menu directly. This is an example of the previously mentioned event delegation pattern: by just adding an event listener to some ancestor element (which may simply be the document body), you can add, swap and remove elements without the need to add new event listeners.

Now discourse uses the UI framework ember.js, which does a lot of stuff under the hood to dynamically create and update the element tree; but at its core the idea might look something like this:

document.body.addEventListener('click', event => {
  const toggleBtn = event.target.closest('.header-dropdown-toggle')

  if (toggleBtn) {
    toggleBtn.classList.toggle('active')
  }
})

This way you don’t need to add an event listener to the toggle button itself at any point, and it will still work if you cleared the body at some point or add another toggle button, say.

Sorry for the nitpicking but the event listeners are still effective, the elements they were added to have just been removed from the page’s DOM tree and replaced with new ones.

1 Like

Thanks a lot for your time helping me, to me there is an element of grace in it !

And thanks also for helping me understand that the event listeners remain in place and effective, but if the DOM value they effect would be changed (even with the new HTML being identical to the previous), they won’t effect the new DOM value naturally — but we can make them to with some event delegation artificially ! Now I just need to learn what event delegation really is ! :slight_smile:

1 Like

Happy to help! As for a deeper understanding of event delegation, just check out the above link – it’s really well explained there IMO with lots of examples and everything. :-)

I had two typos in my reply above, which are now fixed.

Yes, I have checked that article but it’s very hard for me to read; I assume that at least in part it has to do with me being a non native speaker of English and what I grasp as significant longevity and density in the article; I should try to find a different, more “modular” introduction to the subject.