How to add a <script> element to the DOM and execute its code?
I have no idea how YUI's Node.create()
function works, so no comment on that. But a simple cross-browser script is:
window.onload = function() {
var s = document.createElement('script');
s.type = 'text/javascript';
var code = 'alert("hello world!");';
try {
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
} catch (e) {
s.text = code;
document.body.appendChild(s);
}
}
The try..catch block is necessary as most browsers like the first method but some don't and throw an error. The second method covers those. You can also simply eval the code, which is more or less equivalent and what some libraries do.
How to insert and execute script tag to the DOM using plain js
You can use insertAdjacentHTML
to insert the HTML, then go back and look for the scripts and copy the script src
or text, and insert the copy into the DOM to run it:
// Sticking with broadly-supported features:var htmlString = "<div><h1>Title</h1></div><div><script>console.log('it works');<\/script></div>";var target = document.getElementById("target");target.insertAdjacentHTML("beforeend", htmlString);var scripts = target.getElementsByTagName("script");while (scripts.length) { var script = scripts[0]; script.parentNode.removeChild(script); var newScript = document.createElement("script"); if (script.src) { newScript.src = script.src; } else if (script.textContent) { newScript.textContent = script.textContent; } else if (script.innerText) { newScript.innerText = script.innerText; } document.body.appendChild(newScript);}
<div id="target"></div>
Attach script tag code to dom element for execution , alternate for document.write
I was able to resolve it by below code, thought to update if someone in future is stuck on the same problem.
var ad = "whatever encoded here script code";
function decodeHtml(html) {
return $("<textarea/>").html(html).text();
}
function fetch(id, html) {
var elm = document.getElementById(id);
elm.innerHTML = html;
var scripts = elm.getElementsByTagName("script");
var scriptsClone = [];
for (var i = 0; i < scripts.length; i++) {
scriptsClone.push(scripts[i]);
}
for (var i = 0; i < scriptsClone.length; i++) {
var currentScript = scriptsClone[i];
var s = document.createElement("script");
// Copy all the attributes from the original script
for (var j = 0; j < currentScript.attributes.length; j++) {
var a = currentScript.attributes[j];
s.setAttribute(a.name, a.value);
}
s.appendChild(document.createTextNode(currentScript.innerHTML));
currentScript.parentNode.replaceChild(s, currentScript);
}
}
var decoded = decodeHtml(ad);
fetch('YourDivID',decoded);
Add script element to DOM without executing it
Use this to disable Javascript execution in jsdom
jsdom.defaultDocumentFeatures = {
FetchExternalResources: false,
ProcessExternalResources: false
};
If nodejs produces error disable mutation events also in jsdom
jsdom.defaultDocumentFeatures = {
FetchExternalResources: false,
ProcessExternalResources: false,
MutationEvents : false
};
Can scripts be inserted with innerHTML?
You have to use eval() to execute any script code that you've inserted as DOM text.
MooTools will do this for you automatically, and I'm sure jQuery would as well (depending on the version. jQuery version 1.6+ uses eval
). This saves a lot of hassle of parsing out <script>
tags and escaping your content, as well as a bunch of other "gotchas".
Generally if you're going to eval()
it yourself, you want to create/send the script code without any HTML markup such as <script>
, as these will not eval()
properly.
Inject and execute JavaScript into an existing DOM
script
tags added via innerHTML
and related methods (insertAdjacentHTML
, etc.) are not executed. (The exact rules are somewhere in the script
portion of the HTML specification but it's heavy going.) This may be because early on it was identified that poorly-written pages might use innerHTML
and such to append user content, and so not executing it was a quick and simple way to avoid very, very basic XSS attacks. But only very, very basic ones.
You can add a script
tag to the DOM and have it executed by creating and appending a script tag:
const script = document.createElement("script");
script.textContent = `console.log("Hi there");`;
document.body.appendChild(script);
You can do that from the console tab in devtools, for instance, rather than the DOM inspector tab.
Executing a <script> tag on append after the DOM has loaded
On a whim I made this change:
// document.getElementById('scriptMe').appendChild(s);
document.body.appendChild(s);
and boom, script runs and video loads.
Which is super interesting, because "why", right?
Edit:
In addition, trying other script injection methods discussed here.
document.write method
document.write(s.outerHTML) // s is a script node
also works. In fact, you can embed that script node in a div
and it works as well.
createContextualFragment method
// var $container = document.getElementById('scriptMe'); // does not work
var $container = document.body
var range = document.createRange()
$container.appendChild(range.createContextualFragment(script_str))
works, where script_str
is an html string literal. This will work both as "<script>....</script>"
or "<div id="myDiv"><script>...</script></div>"
but all the methods I tested ultimately needed injection to be done in body
.
codepen
Related Topics
Html "Overlay" Which Allows Clicks to Fall Through to Elements Behind It
Relative Paths in JavaScript in an External File
How to Automatically Reload a Web Page At a Certain Time
How to Get Number of Rows in ≪Textarea ≫ Using JavaScript
Jquery CSS Plugin That Returns Computed Style of Element to Pseudo Clone That Element
Change CSS of Selected Text Using JavaScript
Trigger CSS Transition on Appended Element
How to Access and Process Nested Objects, Arrays, or Json
How to Use a Variable For a Key in a JavaScript Object Literal
How to Set Focus on an Element in an HTML Form Using JavaScript
Saving Binary Data as File Using JavaScript from a Browser
Retrieving Html5 Video Duration Separately from the File
Limit Number of Lines in Textarea and Display Line Count Using Jquery
How to Retrieve the Display Property of a Dom Element
What Is the Cleanest Way to Disable CSS Transition Effects Temporarily