DOMParser appending <script> tags to <head>/<body> but not executing
You should use:
const sHtml = '<script>window.alert("Hello!")</script>';
const frag = document.createRange().createContextualFragment(sHtml)
document.body.appendChild( frag );
Using DOMParser()
as described in the question will correctly set the <head>
and <body>
contents of the page, but more work is necessary to get any existing <script>
tags to execute.
The basic approach here is to pull a list of all <script>
tags in the page after the contents have been set, iterate over that list and dynamically create a new <script>
tag with the contents of the existing one and then add the new one to the page.
Example:
// create a DOMParser to parse the HTML content
var parser = new DOMParser();
var parsedDocument = parser.parseFromString(data, 'text/html');
// set the current page's <html> contents to the newly parsed <html> content
document.getElementsByTagName('html')[0].innerHTML = parsedDocument.getElementsByTagName('html')[0].innerHTML;
// get a list of all <script> tags in the new page
var tmpScripts = document.getElementsByTagName('script');
if (tmpScripts.length > 0) {
// push all of the document's script tags into an array
// (to prevent dom manipulation while iterating over dom nodes)
var scripts = [];
for (var i = 0; i < tmpScripts.length; i++) {
scripts.push(tmpScripts[i]);
}
// iterate over all script tags and create a duplicate tags for each
for (var i = 0; i < scripts.length; i++) {
var s = document.createElement('script');
s.innerHTML = scripts[i].innerHTML;
// add the new node to the page
scripts[i].parentNode.appendChild(s);
// remove the original (non-executing) node from the page
scripts[i].parentNode.removeChild(scripts[i]);
}
}