admin管理员组

文章数量:1278978

I have a string with HTML:

var str = '<div><p>Examplee</p></div><script>alert("testing!")</script>';

and then I append it to the HTML:

document.body.innerHTML += str;

and the content is appended but the script does not execute, is there a way to force it?

I have a string with HTML:

var str = '<div><p>Examplee</p></div><script>alert("testing!")</script>';

and then I append it to the HTML:

document.body.innerHTML += str;

and the content is appended but the script does not execute, is there a way to force it?

Share Improve this question asked May 4, 2018 at 15:54 nicknick 3,2596 gold badges42 silver badges85 bronze badges 5
  • Because it won't run when being appended, scripts run on page load or on an action event, you need to add a trigger to it – clearshot66 Commented May 4, 2018 at 15:55
  • And how do I add a trigger? I tried to wrap the alert in a function and call it after appending it but it doesn't work either – nick Commented May 4, 2018 at 15:57
  • stackoverflow./questions/7017241/… try this – clearshot66 Commented May 4, 2018 at 15:57
  • 1 @clearshot66: The OP doesn't appear to be using jQuery, nor did they tag jquery. – T.J. Crowder Commented May 4, 2018 at 16:02
  • @T.J.Crowder OP also never said they couldn't, hence why I didn't put it as an answer. – clearshot66 Commented May 4, 2018 at 17:20
Add a ment  | 

3 Answers 3

Reset to default 10

First, a caveat: Naturally, only do this with scripts you trust. :-)

There are a couple of ways. Basically, you need to:

  1. Get the text of the script, and

  2. Run it

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:

  • Use indirect eval (aka "global eval") on it: (0, eval)(text). This is not the same as eval(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.

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);


Presumably you don't really use += on document.body.innerHTML, which builds an HTML string for the whole page, appends to it, tears the whole page down, and then parses the new HTML to build a new one. I assume that was just an example in your question.

jQuery provides the $.getScript(url [,success]) function. You can then load and execute your code from a separate jquery file which helps to manage and control the flow of execution.

basically put your alert("testing!") script inside a separate file, for instance alert.js in the same directory.

Then you can run the script when adding your employee to the HTML.

var str = '<div><p>Examplee</p></div>';
var url = 'alert.js';    
document.body.innerHTML += str;    
$.getScript(url);

I know this may seem like more work, but it is better practice to keep your javascript out of your HTML. You can also use a callback to gather user data after the alert or notify another process that the user has been alerted.

$.getScript(url, function(){
  //do something after the alert is executed.
});

For instance maybe it would be a better design to add the employee after the alert is executed.

var str = '<div><p>Examplee</p></div>';
var url = 'alert.js'; 
$.getScript(url, function(){
  document.body.innerHTML += str;
});

Edit: I know jQuery is not tagged, but I am also no petitioning to be the accepted answer to this question. I am only offering another alternative for someone who may run into the same issue and may be using jQuery. If that is the case $.getScript is a very useful tool designed for this exact problem.

You should change the HTML after it was loaded. Try this:

document.addEventListener("DOMContentLoaded", function(event) {
    document.body.innerHTML += str;
});

本文标签: javascriptRun script after appending it to the HTMLStack Overflow