Run Script After Appending It to the HTML

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:

  1. Get the text of the script, and

  2. Run it

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

      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



      Leave a reply



      Submit