I’ve been working on a website where we display YouTube videos in a modal overlay. This seems simple: absolutely position a div and centre YouTube’s iframe embed within it. When the user tires of the video remove the iframe and hide or remove the div. It works great, then I fired up Internet Explorer for testing.
In IE this is what appears in the Javascript console, after the iframe is removed:
With the iframe gone html5player.js and its code shouldn’t exist anymore and therefore should not throw errors. It turns out that when an iframe is removed from a web page IE doesn’t completely purge the contents of the iframe from memory right away, if ever.
How do we fix it?
The errors occurred when using jQuery to set the innerHTML of the containing div to an empty string, so I started trying to explicitly remove the iframe’s DOM node using pure Javascript. Element.removeChild() the node instead of destroying it, so that didn’t kill the errors. The docs for IE’s removeNode() don’t specify if the node is held in memory, but the errors continued with it as well.
Some Googling turned up, (I forget where), that setting the iframe’s src attribute to an empty string might help. This makes sense because it’s the equivalent of navigating the iframe to a new page, which should unload any Javascript. Trying to set src=” worked, most of the time. When it didn’t work IE went crazy and became unusable.
In the end I took the approach of trying to wipe out the contents of the iframe as thoroughly as possible, first by changing the iframe’s src to an empty string, then by accessing the iframe’s DOM with Javascript and setting its document element to null. This did the trick. Here’s the function:
// note: modal is the div that contains the YouTube iframe
// jquery is used for some selecting, but the guts of the removal are pure Javascript
function purgeVideo() {
// purge video must be called while the video is still displayed on the page,
// so doing a jQuery fadeOut(purgeVideo) may throw errors, (I think because
// fadeOut sets display:none before calling its callback).
if( modal ) {
// get the iframe, declare variables
var ifr = $('iframe', modal), rifr;
// if the iframe is found get the underlying DOM node from jQuery
if ( ifr.length > 0 ) {
rifr = ifr.get(0);
}
// make extra sure the DOM node exists before starting to work on it.
if( rifr ) {
// set src to '' to start removing YouTube and get around cross-domain access restrictions
rifr.src = '';
// now set the document element of the iframe to null, (I think this is IE-specific)
if ( rifr.documentWindow ) {
rifr.documentWindow.document = null;
rifr.documentWindow = null;
}
// delete the iframe, (also removes it from DOM).
delete rifr;
}
// this won't throw an error, even if the iframe is gone, (we're back to jQuery here).
ifr.remove();
// remove anything else, (titles, etc), from the modal overlay
modal.html('');
}
}