Say I have an inline script in my DOM that's been commented out:
<!-- <script type='text/javascript' id='my-script'>
alert('Boo!');
</script> -->
I can successfully find said comment in the DOM, but if I
const script = comment.nodeValue;
comment.replaceWith(script);
The comment does indeed get replaced in the DOM; however, it gets replaced by a text node, not a script node.
function myFunction() {
const locator = document.getElementById('foo');
let comment = locator.nextSibling;
if ( 3 === comment.nodeType ) {
comment = comment.nextSibling;
}
if ( 8 !== comment.nodeType ) {
console.warn('Oops! That\'s not a comment!');
} else {
const script = comment.nodeValue;
comment.replaceWith(script);
}
}
<div id='foo'></div>
<!-- <script type='text/javascript' id='my-script'>
alert('Boo!');
</script> -->
<button onclick="myFunction()">Click me</button>
Is there a way to insert it as a script other than by regex parsing the comment.nodeValue and manually building up a script node?
CodePudding user response:
Here is one way you could do it without needing to resort to regex.
Basically you create a new script element and then set the new script element's attributes and innerHTML by creating a dummy script element (from the text in the comment) and reading off the attributes and innerHTML from the dummy.
Note: The reason I don't just insert dummyScriptElem
is because that doesn't cause the script to run when inserted.
const bodyElem = document.querySelector('body');
const commentElem = getAllComments(bodyElem)[0];
const scriptElemAsStr = commentElem.nodeValue;
const dummyScriptElem = createElementFromHTML(scriptElemAsStr);
//commentElem.replaceWith(dummyScriptElem); //this doesn't run the script when it's inserted so instead we create newScriptElem below and insert that instead
const newScriptElem = document.createElement('script');
//set newScriptElem's attributes and innerHTML to match script tag in commentElem
for (let attrName of dummyScriptElem.getAttributeNames()) {
const attrValue = dummyScriptElem.getAttribute(attrName);
newScriptElem.setAttribute(attrName, attrValue);
}
newScriptElem.innerHTML = dummyScriptElem.innerHTML;
commentElem.replaceWith(newScriptElem);
//util functions
function createElementFromHTML(htmlString) {
const div = document.createElement('div');
div.innerHTML = htmlString.trim();
return div.firstChild;
}
function getAllComments(rootElem) {
const comments = [];
const iterator = document.createNodeIterator(rootElem, NodeFilter.SHOW_COMMENT, () => NodeFilter.FILTER_ACCEPT, false);
let curNode;
while (curNode = iterator.nextNode()) {
comments.push(curNode);
}
return comments;
}
<!-- <script type='text/javascript' id='my-script'>
alert('Boo!');
</script> -->