Run script after appending it to the HTML
First, a caveat: Naturally, only do this with scripts you trust. :-)
There are a couple of ways. Basically, you need to:
Get the text of the script, and
Run it
Use indirect
eval
(aka "globaleval
") on it:(0, eval)(text)
. This is not the same aseval(text)
; it runs the code in global scope, not local scope.Create a new script element, set its text to the text, and add it
var newScript = document.createElement("script");
newScript.textContent = text;
document.body.appendChild(newScript);If doing that, might make sense to remove the original, though it doesn't really matter.
Getting the text
One option is just to go ahead and add it, then find it and grab its text:
document.body.innerHTML += str;
var scripts = document.querySelectorAll("script");
var text = scripts[scripts.length - 1].textContent;
On obsolete browsers, you may need to feature-detect textContent
vs. innerText
.
You might want to give it an identifying characteristic (id
, class
, etc.) so you don't have to find it by position like that.
Alternately, you could do what the PrototypeJS lib does and try go get it from the string with regex. You can find their source code for doing that here (look for extractScripts
).
Running it
Once you have the text of the script, you have several options:
Example that grabs the text of the script
element after adding it and uses indirect eval
:
var str = '<div><p>Examplee</p></div><script>alert("testing!")<\/script>';document.body.innerHTML += str;var scripts = document.querySelectorAll("script");(0, eval)(scripts[scripts.length - 1].textContent);
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
Will a script tag appended to an element run before the next line after .append()?
Independent of whether or not this is a good idea....
In order for the browser to interpret your dynamically inserted DOM, it has to parse the content you are providing. This is a synchronous process (assuming your JS doesn't do any AJAX requests, setTimeouts
etc). From the Google Dev blog:
When the HTML parser encounters a script tag, it pauses its process of
constructing the DOM and yields control over to the JavaScript engine;
once the JavaScript engine has finished running, the browser then
picks up from where it left off and resumes the DOM construction.
This means that the browser is guaranteed to process and execute the JS in the script tag (as well as add the DOM in the string) before it moves onto the next JS command: if (hasNext) {...
.
In your example it wouldn't matter where the <script>
tag was in relation to the rest of the dynamically inserted DOM in data
because there is no dependency between the DOM and that script. As long as it is in data
, the browser will process those commands before proceeding to the line after append
. E.g. this would work just as well
<li class="result">one</li>
<li class="result">two</li>
<script>
hasNext = true // global variable
</script>
Since your code is checking the dynamically 'injected' variable after the append
call, the variable (hasNext
) is guaranteed to exist (as long as it was in a <script>
tag in data
).
For example:
$( ".test" ).append( "<p>Test</p><script>var globalVariable = 123;" );
$( ".test" ).append( globalVariable );
will write:
<p>Test</p>123
The most likely race condition is from some server interaction not specifying the hasNext
variable, in which case the code will either use the falsey value of that variable:
if (undefined) {
alert('I won\'t be called');
} else {
alert('I will be called');
}
-OR, the more risky version-
your if (hasNext) { ... }
will use the previous value of that variable from a prior call to append
with different data
. This is quite risky and possibly the best reason for avoiding this approach.
How to execute <script> code in a javascript append
appending HTML into the DOM does not cause the browser to evaluate any script tags in said appended HTML.
If you really wanted to, you could evaluate the javascript by using eval()
:
eval($(this).find("script").text());
Need to run script after append to div in javascript
Given the issues with trying to load a <script>
that is calling document.write
through JSON your best option here may be to create a separate page, for example myAdPage.html.
In that page get the script with JSON and allow it to write its contents to that page.
You can then display the HTML of that page inside of an <iframe>
inside of your <div>
.
<div id="newdiv"><iframe src="myAdPage.html"></iframe></div>
How to append and run script on button click [JAVASCRIPT]
Try creating a new div, setting its innerHTML, then adding this new div to the DOM. Something like:
function loadScript() {
if (getCookie('cookieAccepted')) {
var serverScript = document.createElement("script");
serverScript.type = "text/javascript";
serverScript.src = "http://example.com/myscript";
var newdiv = document.createElement('div');
newdiv.innerHTML = serverScript;
document.getElementById('target').appendChild(newdiv); //<-- lets say that you have a div called target in your html (<div id="target"></div>)
} else {
alert('Please enable cookies')
}
}
How to execute javascript code after appendChild
Don't wrap it in a div, create the script tag directly. This worked for me:
var scriptTag = document.createElement("script");
scriptTag.src = "http://example.com/myscript.js";
bodyTag.appendChild(scriptTag);
Related Topics
Redirect to Url After Form Submit in React
Mobile Safari Sometimes Does Not Trigger the Click Event
I Want a Code to Fill in the Form Automatically
How to Calculate the Sum of Table Column in Angular 2+
Javascript: How to Redirect a Page After Validation
Update Value in Localstorage Array by Existing Key
How to Get the Ajax Response from Success and Assign It in a Variable Using Jquery
Stop Just One Dropdown Toggle from Closing on Click
How to Trigger Click Event on Select Element (Not Change)
Angular - How to Get Result of a Json Object
Pdf Blob - Pop Up Window Not Showing Content
How to Make a Owl Carousel With Arrows Instead of Next Previous
Destroy Chart.Js Bar Graph to Redraw Other Graph in Same <Canvas>
How to Prevent Invalid Characters from Being Typed into Input Fields
Reload Table After Deleting an Item from It With React
How to Redirect to Another Page in Reactjs When a If Condition Is Executed