0

I'm using eval() to execute all <script> tags after total rewrite of a div (whose code is loaded via an XMLHttpRequest):

var arr = document.getElementById('idOfDIV').getElementsByTagName('script');
         for (var n = 0; n < arr.length; n++){
                try {
                 eval(arr[n].innerHTML);
                } catch(err) {
                console.log(err);
                }
        }

It works well for inline-scripts, but has no effect on scripts like:

<script src="/path/to/externalScript.js"></script>

How come? Can I "force" the browser to load and execute also the external scripts?

NOTE: As I noted, the question may seems "strange", regarding the fact that eval() executes a string as javascript. What I need to do, is the force the browser to load external scripts contained in "pasted" DOM, and execute them.

Blazemonger
  • 90,923
  • 26
  • 142
  • 180
Carmine Giangregorio
  • 943
  • 2
  • 14
  • 35
  • 1
    um you can't really do that since the script tags don't have the source in the HTML. you could add the script tags again but that could cause a lot of leaks. – Daniel A. White Jan 23 '15 at 13:43
  • 1
    Remember: eval() is evil – Logard Jan 23 '15 at 13:43
  • 2
    I'm not clear what you're trying to do -- `eval()` runs a string as executable JavaScript code, it doesn't do anything with HTML tags. If you were using jQuery, I'd suggest the [`$.getScript()`](http://api.jquery.com/jquery.getscript/) method. – Blazemonger Jan 23 '15 at 13:45
  • @Logard: I know; but in this case is my only option. – Carmine Giangregorio Jan 23 '15 at 13:46
  • @Blazemonger: You're right, I'm updating the question with a note – Carmine Giangregorio Jan 23 '15 at 13:47
  • Incidentally, this is part of the reason why separation of concerns is a good idea -- HTML and JavaScript shouldn't be intertwined this much in the first place. I'd suggest taking all the scripts out of that `div` and combining them together somewhere else in a single function. – Blazemonger Jan 23 '15 at 13:48
  • `eval` is meant to evaluate **JavaScript** code, **not HTML**. – plalx Jan 23 '15 at 13:49
  • @plalx: I know... As I already stated, I need to have the script retrieved and then executed via eval() – Carmine Giangregorio Jan 23 '15 at 13:50
  • Use AJAX to retrieve the external file if there's an `src` attribute, and `eval()` whatever you get. – Blazemonger Jan 23 '15 at 13:51
  • eval is evaluating Javascript in this code, as `arr` is a list of – Hacketo Jan 23 '15 at 13:52

2 Answers2

3

This tag :

<script src="/path/to/externalScript.js"></script>

has empty innerHTML, so you cant eval the content

What you could do is to check if the script has an src attribute, and add a script tag in the head with this src :

function addHeadScript = function(src){
    var head = document.getElementsByTagName("head")[0];
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = src;
    head.appendChild(script);
}

...


for (var n = 0; n < arr.length; n++){
    if (arr[n].src != ""){
        addHeadScript(arr[n].src);
    }
    else {
        // Evaluate the script `innerHTML`   OR
        // Create a script tag in the head and set it's content equal to arr[n].innerHTML
    }
}
Hacketo
  • 4,978
  • 4
  • 19
  • 34
2

Here's one thing you could do:

var html = "Some html with a script <script>alert('test');</script>";

var frag = parsePartialHtml(html);

fixScriptsSoTheyAreExecuted(frag);


document.body.appendChild(frag);


function fixScriptsSoTheyAreExecuted(el) {
  var scripts = el.querySelectorAll('script'),
      script, fixedScript, i, len;

  for (i = 0, len = scripts.length; i < len; i++) {
    script = scripts[i];

    fixedScript = document.createElement('script');
    fixedScript.type = script.type;
    if (script.innerHTML) fixedScript.innerHTML = script.innerHTML;
    else fixedScript.src = script.src;
    fixedScript.async = false;

    script.parentNode.replaceChild(fixedScript, script);
  }
}


function parsePartialHtml(html) {
  var doc = new DOMParser().parseFromString(html, 'text/html'),
      frag = document.createDocumentFragment(),
      childNodes = doc.body.childNodes;

  while (childNodes.length) frag.appendChild(childNodes[0]);

  return frag;
}
plalx
  • 42,889
  • 6
  • 74
  • 90