Skip to content
Advertisement

Replace DOM with javascript and run new scripts

I am trying to replace the whole DOM on page load to do a no-js fallback for a user created knockout page.

I have it replacing the DOM, but when I do the scripts included in the new document aren’t running. I was wondering if theres any way of forcing them to run.

JavaScript

template contains the following encoded

JavaScript

how can I get the alert to run?

Advertisement

Answer

As you’ve discovered, the code in the script tags in the text you assign to innerHTML is not executed. Interestingly, though, on every browser I’ve tried, the script elements are created and placed in the DOM.

This means it’s easy to write a function to run them, in order, and without using eval and its weird effect on scope:

JavaScript

Naturally the scripts can’t use document.write.

Note how we have to create a new script element. Just moving the existing one elsewhere in the document doesn’t work, it’s been marked by the browser as having been run (even though it wasn’t).

The above will work for most people using innerHTML on an element somewhere in the body of the document, but it won’t work for you, because you’re actually doing this on the document.documentElement. That means the NodeList we get back from this line:

JavaScript

…will keep expanding as we add further scripts to the document.documentElement. So in your particular case, you have to turn it into an array first:

JavaScript

…and later in continueLoading, you have to manually remove entries from the array:

JavaScript

Here’s a complete example for most people (not you), including the scripts doing things like function declarations (which would be messed up if we used eval): Live Copy | Live Source

JavaScript

And here’s your fiddle updated to use the above where we turn the NodeList into an array:

HTML:

JavaScript

Script:

JavaScript

This approach just occurred to me today when reading your question. I’ve never seen it used before, but it works in IE6, IE8, Chrome 26, Firefox 20, and Opera 12.15.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement