2

I'm adding some <script/> tags from javascript to load some libraries (e.g., jquery). When all libraries are loaded, I execute main code. To wait until everything's ready, I use solution similar to the one in this answer (found it on the web).

Now, the story: http://jsfiddle.net/EH84z/

function load_javascript(src) {
    var a = document.createElement('script');
    a.type = 'text/javascript';
    a.src = src;
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(a, s);
}

load_javascript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js');

function addEvent(elm, evType, fn, useCapture) {
    //Credit: Function written by Scott Andrews
    //(slightly modified)
    var ret = 0;

    if (elm.addEventListener) {
        ret = elm.addEventListener(evType, fn, useCapture);
    } else if (elm.attachEvent) {
        ret = elm.attachEvent('on' + evType, fn);
    } else {
        elm['on' + evType] = fn;
    }

    return ret;
}

addEvent(window, "load", function() {
    console.log(window.jQuery + '  ' + window.$);
    $(document);
}, false);

It works fine in Firefox, but quite often fails in Chrome. Every second time I press jsfiddle 'run' button, callback is executed before JQuery is loaded, thus giving error in Chrome console.

Does it mean I misuse addEventListener horribly? If yes, what's the correct use for it and how do I really wait until all scripts are loaded?

Thanks!
PS Didn't test it in any other browsers yet, so please comment if it's failing somewhere else.

edit
if I wait one second (using setTimout) before testing, success rate increases to 100%. An example http://jsfiddle.net/EH84z/1/

Community
  • 1
  • 1
Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
  • Just curious, why are you trying to load a framework dynamically? – Nick Craver Oct 08 '10 at 09:19
  • @Nick It's a widget which people insert in their pages. I could give them few _script_ tags and tell to put them into _head_ element, but I image it's less confusing for the user when everything happens under the hood. – Nikita Rybak Oct 08 '10 at 09:22
  • What if jQuery's already being loaded elsewhere? Including it again will blow away any plugins they have....sometimes a dependency (like *most* jQuery plugins specify) is a better option. – Nick Craver Oct 08 '10 at 09:24
  • @Nick I don't load it again if it's already present. But I'll check out dependency mechanism, thanks. – Nikita Rybak Oct 08 '10 at 09:29
  • Also use a feature set that's older if possible, 1.3 or 1.2 at worst (though 1.3+ would be ok) unless you're depending on 1.4+ features somehow...users can't include multiple versions, so it's best to rely on one version behind to support as many as possible, but hey if you need 1.4+ functionality then that's how it goes. – Nick Craver Oct 08 '10 at 09:31
  • Sounds like you are hitting this bug http://dev.jquery.com/ticket/4196 – Blair McMillan Oct 08 '10 at 09:24

1 Answers1

4

You have to attach the load event to the jQuery script tag, not the window object.

Try this:

function load_javascript(src) {
    var a = document.createElement('script');
    a.type = 'text/javascript';
    a.src = src;
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(a, s);

    // attach it to the script tag
    addEvent(a, "load", function() {
        console.log(window.jQuery + '  ' + window.$);
        $(document);
    }, false);
}
Luca Matteis
  • 29,161
  • 19
  • 114
  • 169
  • Was just looking up the script load event. You beat me to it. +1 – spender Oct 08 '10 at 09:29
  • does it differ if you attach the event *first* and then set the src property? – Caspar Kleijne Oct 08 '10 at 09:36
  • +1, thanks! I can certainly use one event listener for each script/link tag. But there's another question then: what's the use for window's 'load' event? It's mentioned in lots of places (e.g., the answer I linked). What does it do, then? – Nikita Rybak Oct 08 '10 at 09:36
  • @Nikita: The load event on the window object is fired when all resources (the document, objects, images, css, etc) have finished rendering... the one's in the HTML... not the ones you add dynamically. You probably need to call your `load_javascript()` when the window has fired the load event... you can't manipulate the DOM until it is loaded. – Luca Matteis Oct 08 '10 at 09:42