1

In my CMS I add modules to the page via Javascript, these modules may include external JS files which get registered on page load into a collaborated external file.

When the modules are added via JS these scripts are therefore not registered until the page is reloaded.

Is there a way for me to register these scripts dynamically via the javascript calls in the mean time?

Anthony Main
  • 6,039
  • 12
  • 64
  • 89

2 Answers2

5

You can add a script tag to your page using the following code:

var head  = document.documentElement.childNodes[0];
var sTag  = document.createElement("script");
sTag.src  = "/path/to/script.js";
sTag.type = "text/javascript";
head.appendChild(sTag);

You could also use document.getElementsByTagName("head")[0] for the head var. Alternatively, you could use document.write, like so:

document.write(
    '<script src="path/to/script.js" type="text/javascript"><\/script>'
);
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • Would this actually register the javascript functions though? – Anthony Main Jan 12 '10 at 13:25
  • Yes it would however only *after* its downloaded and parsed the file. Its a good idea to have a callback in the bottom of your script which can call a function in your page to let you know when its loaded and ready or you can poll for the existance of a function in your file using setInterval – Pete Duncanson Jan 12 '10 at 13:29
  • Don't use `'` - it is pointless in an external JS file and invalid in an HTML file. If you want embedded scripts containing that string, use: `<\/script>'` – Quentin Jan 12 '10 at 13:30
  • Well, they would be registered after the current javascript is parsed, meaning if you reference those functions before they are parsed an error would occur. To avoid this you would have to delay calling those functions (using either the onload event or a timer with a timeout length of 0). – Andy E Jan 12 '10 at 13:31
  • @David Dorward, I did explain why the closing script tag was split up. @Pete, you beat me to it :) – Andy E Jan 12 '10 at 13:32
  • Great thanks, I'll give it a go this afternoon and award answer if all gravy. Im suprised that browsers work like that, would have thought all the functions were added onload or something instead of reparsing the dom – Anthony Main Jan 12 '10 at 13:33
  • @Andy E — yes, but you did it wrong. That approach depends on bugs or error recovery in HTML parsers. – Quentin Jan 12 '10 at 13:33
  • Scripts are parsed by the scripting engine, not the DOM rendering engine, so whenever a new tag is added to the DOM it's just handed to the scripting engine for parsing. – Andy E Jan 12 '10 at 13:34
1

I made the following function, inspired by the jQuery's $.getScript method, it takes an url and a callback argument.

The callback is very useful, it is executed when the script has been loaded successfully, and you are ready to use it.

This function also takes care of removing the script elements from the DOM to avoid well known memory leaks:

loadScript("myLib.js", function () {
  // myLib is loaded
  //..
});

function loadScript(url, callback) {
  var head = document.getElementsByTagName("head")[0],
      script = document.createElement("script"),
      done = false;

  script.src = url;
  // Attach event handlers for all browsers
  script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState ||
      this.readyState == "loaded" || this.readyState == "complete") ) {
      done = true;
      callback(); // Execute callback function
      // Prevent memory leaks in IE
      script.onload = script.onreadystatechange = null;
      head.removeChild( script );
    }
  };
  head.appendChild(script);
}
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • Nice function :) Although, I'm not sure I understand what benefit there is with removing the script from the DOM afterwards, wouldn't the contents already be parsed and loaded into memory? What would be gained by removing the element? You've got me curious now! :) – Andy E Jan 12 '10 at 15:08
  • It's about IE :(, it has problems and starts to leak memory, it needs also the script event handlers (`onload` and `onreadystatechange`) to be nullified in order to garbage collect correctly... IE sucks... – Christian C. Salvadó Jan 12 '10 at 15:24
  • I've had problems with adding script tags to fetch JSONP (in IE) before and removing the tags caused a huge memory leak each time - each script file could be at least 30k. I didn't have any event handlers attached, but it was still leaking. In the end i went back to XMLHttpRequest and bog standard JSON. But yeah, IE does suck. – Andy E Jan 12 '10 at 19:09