How to detect if javascript files are loaded?

I don't have a reference for it handy, but script tags are processed in order, and so if you put your $(document).ready(function1) in a script tag after the script tags that define function1, etc., you should be good to go.

<script type='text/javascript' src='...'></script>
<script type='text/javascript' src='...'></script>
<script type='text/javascript'>
$(document).ready(function1);
</script>

Of course, another approach would be to ensure that you're using only one script tag, in total, by combining files as part of your build process. (Unless you're loading the other ones from a CDN somewhere.) That will also help improve the perceived speed of your page.

EDIT: Just realized that I didn't actually answer your question: I don't think there's a cross-browser event that's fired, no. There is if you work hard enough, see below. You can test for symbols and use setTimeout to reschedule:

<script type='text/javascript'>
function fireWhenReady() {
    if (typeof function1 != 'undefined') {
        function1();
    }
    else {
        setTimeout(fireWhenReady, 100);
    }
}
$(document).ready(fireWhenReady);
</script>

...but you shouldn't have to do that if you get your script tag order correct.


Update: You can get load notifications for script elements you add to the page dynamically if you like. To get broad browser support, you have to do two different things, but as a combined technique this works:

function loadScript(path, callback) {

    var done = false;
    var scr = document.createElement('script');

    scr.onload = handleLoad;
    scr.onreadystatechange = handleReadyStateChange;
    scr.onerror = handleError;
    scr.src = path;
    document.body.appendChild(scr);

    function handleLoad() {
        if (!done) {
            done = true;
            callback(path, "ok");
        }
    }

    function handleReadyStateChange() {
        var state;

        if (!done) {
            state = scr.readyState;
            if (state === "complete") {
                handleLoad();
            }
        }
    }
    function handleError() {
        if (!done) {
            done = true;
            callback(path, "error");
        }
    }
}

In my experience, error notification (onerror) is not 100% cross-browser reliable. Also note that some browsers will do both mechanisms, hence the done variable to avoid duplicate notifications.


When they say "The bottom of the page" they don't literally mean the bottom: they mean just before the closing </body> tag. Place your scripts there and they will be loaded before the DOMReady event; place them afterwards and the DOM will be ready before they are loaded (because it's complete when the closing </html> tag is parsed), which as you have found will not work.

If you're wondering how I know that this is what they mean: I have worked at Yahoo! and we put our scripts just before the </body> tag :-)

EDIT: also, see T.J. Crowder's reply and make sure you have things in the correct order.


Take a look at jQuery's .load() http://api.jquery.com/load-event/

$('script').load(function () { }); 

Further to @T.J. Crowder 's answer, I've added a recursive outer loop that allows one to iterate through all the scripts in an array and then execute a function once all the scripts are loaded:

loadList([array of scripts], 0, function(){// do your post-scriptload stuff})

function loadList(list, i, callback)
{
    {
        loadScript(list[i], function()
        {
            if(i < list.length-1)
            {
                loadList(list, i+1, callback);  
            }
            else
            {
                callback();
            }
        })
    }
}

Of course you can make a wrapper to get rid of the '0' if you like:

function prettyLoadList(list, callback)
{
    loadList(list, 0, callback);
}

Nice work @T.J. Crowder - I was cringing at the 'just add a couple seconds delay before running the callback' I saw in other threads.