53

I've been using this function to attach onload handler to a script tag, it seems to be the recommended way over the internet.
Yet, it doesn't work in internet explorer, if page is loaded already (tested in ie 8). You can see that it works in normal browsers (fires alert when script is loaded).

Am I missing something?
Thank you

Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
  • 2
    onload is not supported in IE8 and below. It works in IE9 Standards Mode. – EricLaw Jan 30 '11 at 22:36
  • 1
    @EricLaw I'm not sure what you mean, window.attachEvent('onload', fn); has worked for me so far (IE 8). It's also mentioned on [MSDN](http://msdn.microsoft.com/en-us/library/cc197055(v=vs.85).aspx) – Nikita Rybak Jan 30 '11 at 23:36
  • 1
    @NikitaRybak I am also trying to implement a way to load jquery in a script (if not already loaded) and then call a function when it is loaded. There is no `onload` for scripts in ie unfortunately. Have you found a way to do that? – Etherealone Aug 17 '12 at 09:48
  • You might find this helpful while loading scripts with async=false. http://stackoverflow.com/a/13031185/325852 – czerasz Oct 23 '12 at 13:14

2 Answers2

88

You should call jQuery.getScript, which does exactly what you're looking for.

EDIT: Here is the relevant source code from jQuery:

var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
if ( s.scriptCharset ) {
    script.charset = s.scriptCharset;
}
script.src = s.url;

// Handle Script loading
    var done = false;

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
    if ( !done && (!this.readyState ||
            this.readyState === "loaded" || this.readyState === "complete") ) {
        done = true;
        jQuery.handleSuccess( s, xhr, status, data );
        jQuery.handleComplete( s, xhr, status, data );

        // Handle memory leak in IE
        script.onload = script.onreadystatechange = null;
        if ( head && script.parentNode ) {
            head.removeChild( script );
        }
    }
};

// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
// This arises when a base node is used (#2709 and #4378).
head.insertBefore( script, head.firstChild );
Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 4
    Not really gonna work, because jquery isn't available initially: I have to load it like this. But I'll check the sources and see if it works in IE. +1 for the interesting reference, thanks! – Nikita Rybak Jan 30 '11 at 21:59
  • 1
    A great answer, thanks man, you don't have to use jQuery to learn from this perfectly valid approach, and then write something similar. :) – Eugene Kuzmenko Oct 08 '12 at 19:07
  • 2
    I think that "jQuery.handleSuccess( s, xhr, status, data ); jQuery.handleComplete( s, xhr, status, data ); " is probably not neccesary, and will cause bugs if this is used verbatim – Ben West Nov 01 '12 at 19:39
  • 7
    Just a note to others that IE9+ supports both script.onload AND script.onreadystatechange (http://bit.ly/18gsqtw), so both events will be triggered (that's 2 calls), which is why "done" is needed. Good to remember if you need to wrap this up in a module to aid multiple script loads. – James Wilkins Oct 19 '13 at 01:31
  • 1
    you can find this same code [here](http://css-tricks.com/snippets/jquery/load-jquery-only-if-not-present/) **ready to use** (without jQuery parts) – Saic Siquot Sep 22 '14 at 15:04
  • Interesting that jQuery assigns the _src_ attribute before inserting the script in the _head_. A Mozilla example [importScript()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement) does this in reverse order. One might assume that the sequence is important, but apparently not since both functions work. – Yogi Apr 21 '15 at 19:53
  • Another problem is the cache of ie ,so a timestamp for the link may be needed – aboutqx Jun 15 '16 at 07:34
12

I also had issues with script.onload = runFunction; in IE8.

I tried jQuery.getScript and it worked perfectly for my needs. The only downside is having to wait for jQuery to be loaded before adding in the script.

However, since my callback functions utilize jQuery very heavily anyway I find this an extremely acceptable and very minor downside since it creates a very easy to use, cross-browser solution.

Update:

Here is a way of doing it without using jQuery:

(a modified solution from: https://stackoverflow.com/a/13031185/1339954)

var url = 'http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js';
var headID = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.type='text/javascript';
script.src=url;

//for nonIE browsers
script.onload=function(){
        addVideo();
    }

 //for IE Browsers
 ieLoadBugFix(script, function(){
     addVideo();}
 );

function ieLoadBugFix(scriptElement, callback){
        if (scriptElement.readyState=='loaded' || scriptElement.readyState=='completed') {
             callback();
         }else {
             setTimeout(function() {ieLoadBugFix(scriptElement, callback); }, 100);
         }


 }

headID.appendChild(script);
Community
  • 1
  • 1
ngChris
  • 141
  • 1
  • 5
  • 2
    It looks like jQuery manages to work it out without polling. Try onreadystatechange instead of setting timeout – Dan Nov 05 '14 at 21:16
  • The ieLoadBugFix function does the work really well. It have tested it. I am excited how stackoverflow has helped with a solution proposed 8 years back. It is amazing – Hello Universe Feb 24 '21 at 03:04