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.
Executing script elements inserted with .innerHTML
The OP's script doesn't work in IE 7. With help from SO, here's a script that does:
exec_body_scripts: function(body_el) {
// Finds and executes scripts in a newly added element's body.
// Needed since innerHTML does not run scripts.
//
// Argument body_el is an element in the dom.
function nodeName(elem, name) {
return elem.nodeName && elem.nodeName.toUpperCase() ===
name.toUpperCase();
};
function evalScript(elem) {
var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
head = document.getElementsByTagName("head")[0] ||
document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
try {
// doesn't work on ie...
script.appendChild(document.createTextNode(data));
} catch(e) {
// IE has funky script nodes
script.text = data;
}
head.insertBefore(script, head.firstChild);
head.removeChild(script);
};
// main section of function
var scripts = [],
script,
children_nodes = body_el.childNodes,
child,
i;
for (i = 0; children_nodes[i]; i++) {
child = children_nodes[i];
if (nodeName(child, "script" ) &&
(!child.type || child.type.toLowerCase() === "text/javascript")) {
scripts.push(child);
}
}
for (i = 0; scripts[i]; i++) {
script = scripts[i];
if (script.parentNode) {script.parentNode.removeChild(script);}
evalScript(scripts[i]);
}
};
Load scripts inside innerHTML
The correct way to load a script file is by creating a script
element.
var script = document.createElement("script");
script.src = "../resource/resmgr/scripts/unified_app.js";
document.head.appendChild(script);
setting innerHTML with a script inside
It looks like that your <script>
tag is being added as you expect, but the code within it is not being executed. The same failure happens if you try using document.head
(or any other DOM element, it seems). For whatever reason (possibly standards compliance, possible security), inline code inside of <script>
blocks that are added via .innerHTML
simply doesn't run.
However, I do have working code that produces similar functionality:
var script = document.createElement('script');
script[(script.innerText===undefined?"textContent":"innerText")] = 'alert(1);';
document.documentElement.appendChild(script);
Here, you add the <script>
block with documentElement.appendChild
and use textContent
or innerText
to set the content of the <script>
.
Insert script to a div via innerHTML working but not loading
There is no innerText in an external script. Also innerHTML does not render scripts
You likely want to do this:
var myDiv = document.getElementById("mydiv");var oldWrite = document.write, html=[];document.write = function(str) { html.push(str);}var script = document.createElement("script");script.src="https://gist.github.com/raselahmed7/e233c308d5bf354c9d174f80a30c6b6a.js"document.getElementsByTagName("head")[0].appendChild(script)setTimeout(function() { myDiv.innerHTML=html.join("\n") },1000)
<div id="mydiv"></div>
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>
script tag create with innerHTML of a div doesn't work
This one was trivial.
As stated in spec (8.4 Parsing HTML fragments and 8.2.3.5 Other parsing state flags,) quote:
when using innerHTML
the browser will
Create a new Document node, and mark it as being an HTML document.
If there is a context element, and the Document of the context element is in quirks mode, then let the Document be in quirks mode.
Otherwise, if there is a context element, and the Document of the
context element is in limited-quirks mode, then let the Document be in
limited-quirks mode. Otherwise, leave the Document in no-quirks mode.Create a new HTML parser, and associate it with the just created Document node.
...
and when parsing a <script>
inside
The scripting flag is set to "enabled" if scripting was enabled for
the Document with which the parser is associated when the parser was
created, and "disabled" otherwise.The scripting flag can be enabled even when the parser was originally
created for the HTML fragment parsing algorithm, even though script
elements don't execute in that case.
So it won't be executed, as long as you inject it with innerHTML
.
And using innerHTML
will prevent the <script>
element created from being executed permanently.
As stated in spec (4.3.1 The script element,) quote:
Changing the src, type, charset, async, and defer attributes dynamically has no direct effect; these attribute are only used at specific times described below.
Concluding the described below is that, it only parse the src
attribute when injecting the <script>
to the document
(no matter which, including the temporary one created when using innerHTML
.)
So, as long as you want to inject a script to the document and make it executed, you have to use script = document.createElement('script')
.
Set its attributes like src
and type
, possibly the contents inside (by using script.appendChild(document.createTextNode(content))
), then append it to the document.body
.
It's safe to use element.innerHTML to insert html returned and escaped by the server
Generally neither of these is a safe practice.
Both of them take in raw HTML content and inject it into your page. This functionality is very frequently abused by malicious actors in a type of attack called XSS (cross-site scripting).
Imagine a hypothetical scenario where you have an API endpoint that returns a user's username inside a <strong>
tag.
Assume you have no validation when the user is signing up, so they can set their username to whatever they want. They could, in theory, set their username to <script>alert(1);</script>
. From that point forward, without extremely careful sanitization, any time you insert that username into the page, using either .html()
or .innerHTML
, you might insert a script tag instead.
If a user could make a simple alert display a 1
, they could potentially load any script they wanted from an external web site using the same method. Using this exploit, they could trivially steal passwords, session cookies, and payment information using a purpose-built script.
The better solution would be to include your template in the client-side code, and insert plaintext data received from the server into that client-side template using .text()
, .innerText
, or .textContent
.
Related Topics
"Mixed Content Blocked" When Running an Http Ajax Operation in an Https Page
How to Send Formdata Objects With Ajax-Requests in Jquery
How to Launch HTML Using Chrome At "--Allow-File-Access-From-Files" Mode
Using an HTML Button to Call a JavaScript Function
Remove CSS Class from Element With JavaScript (No Jquery)
Adding Input Elements Dynamically to Form
Change Link Color of the Current Page With Css
How to Pick Element Inside Iframe Using Document.Getelementbyid
Selecting All Text in HTML Text Input When Clicked
Angularjs Post Fails: Response For Preflight Has Invalid Http Status Code 404
Get the Size of the Screen, Current Web Page and Browser Window
How to Stop Event Propagation With Inline Onclick Attribute
Get File Size, Image Width and Height Before Upload
How to Implement "Select All" Check Box in Html
How to Read the Post Request Parameters Using JavaScript