0

I'm loading a javascript external file from another javascript file present in the document and since its loaded, I want to call a function from the loaded js file. Here is the load function:

function loadScript(url) {
    var head = window.top.document.getElementsByTagName('head')[0];
    var script = window.top.document.createElement('script');
    script.src = url;
    script.type= "text/javascript";
    head.appendChild(script);
    if(script.readyState) {  //IE
        script.onreadystatechange = function() {
            if ( script.readyState === "loaded" || script.readyState === "complete" ) {
                script.onreadystatechange = null;
                console.log("[BANDEAU] script loaded");
                testAlert();
            }
        };
    } else {  //Others
        script.onload = function() {
            console.log("[BANDEAU] script loaded");
            testAlert();
        };
    }
}

So it works nice because the javascript file is succesfuly loaded but I cannot access the testAlert() method from the loaded javascript file, as I try in the code above, right after printing that the script is loaded. When I try to get the type of the function with typeOf on window[testAlert], I get an undefined. But when I try to execute the testAlert() method in the developer console, it works perfectly. Does anyone see what I'm doing wrong ?

Does the position in the DOM between the caller javascript file and the loaded javascript file might be the reason ?

linusg
  • 6,289
  • 4
  • 28
  • 78
Hubert Solecki
  • 2,611
  • 5
  • 31
  • 63
  • Why are you appending the script to `window.top` instead of `window`? – Pointy Dec 15 '16 at 15:40
  • 1
    To put it another way: when that code runs, is `window` the same as `window.top` or not? If they're different, then that's your problem. – Pointy Dec 15 '16 at 16:27

2 Answers2

2

You need to assign the load handlers BEFORE changing the src

function loadScript(url) {
  var head = document.getElementsByTagName('head')[0]; // window.top in frames/iFrames
  var script = document.createElement('script');
  script.type = "text/javascript";

  if (script.readyState) { //IE
    script.onreadystatechange = function() {
      if (script.readyState === "loaded" || script.readyState === "complete") {
        script.onreadystatechange = null;
        console.log("[BANDEAU] script loaded");
        testAlert(); // window.top.testAlert() if needed
      }
    };
  }
  else {
    script.onload = function() {
      console.log("[BANDEAU] script loaded");
      testAlert(); // window.top.testAlert() if needed
    };
  }
  script.src = url;
  head.appendChild(script);
}
mplungjan
  • 169,008
  • 28
  • 173
  • 236
1

In addition to what mplungjan said, I'm pretty sure you'd have to do an eval() on the loaded script in order to have a legitimate address for the call to testAlert().

Also, check out this link for more info.

Community
  • 1
  • 1
  • Keep in mind that eval() is dangerous, so I wouldn't recommend it as a long-term solution. The link I provided features more mature (and safer) solutions. – Dan Schaefer Dec 15 '16 at 16:09
  • This is untrue. The OP is creating a ` – Pointy Dec 15 '16 at 16:27
  • 1
    True. The parent does run the code, but the `loadScript()` function won't automatically receive a pointer to `testAlert()`. But I see your answer in the above comment, and that totally works; reference `testAlert()` with `window.parent.testAlert()`. That's a lot better than my idea of using eval(). – Dan Schaefer Dec 15 '16 at 17:32
  • Thanks everyone for your answers. The problem was that I called the function within an iFrame, juts noticed that so I needed to call the function on the parent pointer. – Hubert Solecki Dec 16 '16 at 10:16