简体   繁体   中英

Dynamically generated Javascript returned via AJAX in JSON format will not execute when appended

I have a webpage that makes an AJAX request to a PHP script. That PHP script responds with a valid JSON object, and sets the Content-type header to application/json .

The JSON format is as follows (as reported by console.log(JSON.stringify(data)) where data is the JSON response):

{
    "content": "<script type=\"text/javascript\">console.log(\"test\");</script>"
}

I then create a div with the class of "content" (remember data is my AJAX responseText JSON object):

var content = document.createElement("div");
content.setAttribute("class", "content");
content.innerHTML = data.content;

Finally, I append the content div to an existing div on my site.

existingDiv.appendChild(content);

I examine the source in the elements tab of Google Chrome's developer tools because it does a good job of showing what is an actual DOM node, and what is just text. The script block shows up as a DOM node.

Unfortunately, the script is not executed - console.log("test"); does not output test to the developer tools console.

The only option I've seen so far is to use eval() which I'm trying to avoid like the plague. Also, my content might contain more than just a script block. It could contain other HTML markup as well.

What am I missing? How can I get this dynamically added block of Javascript to execute?

A jQuery solution is acceptable.

Setting .innerHTML does not evaluate <script> tags; it's just not what browsers do.

If you need to return JavaScript to be executed, you're better off just sending it as a string (without <script> tags) so that you can easily pass it to eval() .

edit If you do this with jQuery instead of directly setting innerHTML (that is, if you use $(something).html() ), and you add the content directly to something in the DOM (that is, not just an element that's been instantiated but not appended to the DOM), then jQuery will actively find and extract your <script> content and evaluate it.

use $.getScript() simple, cachable, straightforward :

http://api.jquery.com/jQuery.getScript/

(obviously you'll have to amend your server script that generates that json containing jscode & change headers)

A possible solution is to use new Function() as:

$(document).ready(function(){
   var script = "window.alert('hi')";
   new Function(script)();
});

As to why your script is not executing, is what @Pointy suggested (but not entirely + a way to circumvent that), as shown by this code:

<script type='text/javascript'>
$(document).ready(function()
{
    $("<script type='text/javascript'>window.alert('hi');<\/script>").appendTo(document.body); // this will work

    var container = document.createElement("div"); // this won't work
    container.innerHTML = "<script type='text/javascript'>window.alert('hi');<\/script>";
    document.body.appendChild(container);

    var script = document.createElement("script"); // this will
    script.innerHTML = "window.alert('hi');";
    document.body.appendChild(script);
});
</script>

EDIT: added a requested unit test: http://jsperf.com/eithed-hvsa

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM