Skip to content

Injecting iframe into page breaks eventlisteners outside of that frame

I’m having an issue where I want to load an iframe when a button is clicked by appending a modal and the iframe to the end of the body tag with a function like this:

function openDonateModal(){
if( document.querySelector('#donate-modal') != null){
    document.querySelector('#donate-modal').style.display = 'block';
} else{
   document.querySelector('body').innerHTML +=`
        <div id="donate-modal" onclick="this.style.display='none'">
                <iframe loading="lazy" src="someOtherSite.com">Loading...</iframe>
        </div>
    `
  }
}
document.querySelector('.donate-button').addEventListener('click', openDonateModal);

And this works one single time for each page refresh, after that it stops working, and I’ve found that the eventListener is not even attached to the button any more.

I thought the problem was isolated to the listener that I’m adding here, but it seems to “un-attach” all the listeners on the page, e.g. drop down menus don’t work anymore. I’ve confirmed it happens in both Firefox and Chrome.

Answer

After more testing I discovered this was to do with altering the body tag, I think appending to it technically replaced all the existing elements with exact HTML copies, but since all the JS on the page wasn’t re-executed the eventListeners for those elements were lost.

My solution was to have the outer most div of the modal already in the DOM and re-write the innerHTML of it instead of appending to the entire body. This solved the problem of the eventListener on the button as well as not breaking other functions on the site.