21

I have a web page. When this web page is loaded, I want to execute some JavaScript. This JavaScript uses JQuery. However, it appears that when the page is loaded, the jQuery library has not been fully loaded. Because of this, my JavaScript does not execute properly.

What are some best practices for ensuring that your jQuery library is loaded before executing your JavaScript?

Villager
  • 6,569
  • 22
  • 65
  • 87

5 Answers5

58

There are several answers already, each of them work great but all of them depend on making sure jQuery is downloaded synchronously before any dependencies try to use it. This approach is very safe, but it can also present an inefficiency in that no other resources can be downloaded/run while the jQuery library script is being downloaded and parsed. If you put jQuery in the head using an embedded tag, the users browser will be sitting idle while downloading and processing jQuery when it could be doing other things like downloading images, downloading other scripts, etc.

If you are looking for speedy responsiveness on startup, every millisecond counts.

A huge help to me over the last year or so has been Steve Souders, first when he was at Yahoo, and now at Google. If you have time, check out his slides for Even Faster Web Sites and High Performance Web Sites. Excellent. For a huge paraphrase, continue here.

When attaching javascript files to the DOM, it has been found that putting an inline <script> tag in the <head> of the document causes most browsers to block while that file is being downloaded and parsed. IE8 and Chrome are exceptions. To get around this, you can create a "script" element via document.createElement, set the appropriate attributes, and then attach it to the document head. This approach does not block in any major browser.

<script type='text/javascript'>
    // Attaching jQuery the non-blocking way.
    var elmScript = document.createElement('script');
    elmScript.src = 'jQuery.js'; // change file to your jQuery library
    elmScript.type = 'text/javascript';        
    document.getElementsByTagName('head')[0].appendChild( elmScript );
</script>

This ensures that jQuery, while downloading and parsing, is not blocking the downloading and parsing of any other images or javascript files. But this could present a problem if you have a script that depends on jQuery finishes its download before jQuery does. jQuery won't be there and you will get an error saying $ or jQuery is undefined.

So, to ensure that your code will run, you have to do some dependency checking. If your dependencies are not met, wait for a little while and try again.

<script type='text/javascript'>
runScript();

function runScript() {
    // Script that does something and depends on jQuery being there.
    if( window.$ ) {
        // do your action that depends on jQuery.
    } else {
        // wait 50 milliseconds and try again.
        window.setTimeout( runScript, 50 );
    }
}
</script>

Like I said earlier, there are no problems with the approaches shown before, they are all valid and all work. But this method will ensure that you are not blocking the download of other items on the page while waiting for jQuery.

This approach will work for any file, so if you have to include 10 js files, you can attach each of them using this method. You just have to make sure your check function checks for every dependency before running.

superUntitled
  • 22,351
  • 30
  • 83
  • 110
Shane Tomlinson
  • 3,310
  • 3
  • 19
  • 12
  • 1
    Fantastic answer, wish I could upvote it more! I'm using this technique now and it works great. (BTW looks like you may have a typo with an unwanted space in `elmScript .src` and `elmScript .type`.) – Alex Angas Nov 11 '10 at 23:30
  • i like this answer. also solve my problem in anther question posted. – murvinlai Mar 22 '11 at 18:50
  • 2
    If `$` is used by another javascript library, make sure to replace it with `jQuery`. – lordcheeto Aug 27 '12 at 09:27
  • Rather than a set timeout, I employ a setInterval that loops every 50 milliseconds (or some interval of your choosing, but not too short because an http request must have enough time to ask-answer), and within each loop a check condition asks if the dynamically created script function has completed before performing the next dynamic script creation. I confess, though, that even when such functions report completion, I still sometimes (however rarely) get a "JQuery not a function" js error. Hence, I am reading this page :/ – TARKUS Jul 03 '13 at 11:58
  • @GregoryLewis, Shane's script calls itself if jquery is not defined so no need for using setInterval instead of setTimeout. – Mike Grace Sep 05 '13 at 20:30
13

The jQuery library should be included in the <head> part of your page:

<script src="/js/jquery-1.3.2.min.js" type="text/javascript"></script>

Your own code should come after this. JavaScript is loaded linearly and synchronously, so you don't have to worry about it as long as you include the scripts in order.

To make your code execute when the DOM has finished loading (because you can't really use much of the jQuery library until this happens), do this:

$(function () {
    // Do stuff to the DOM
    $('body').append('<p>Hello World!</p>');
});

If you're mixing JavaScript frameworks and they are interfering with each other, you may need to use jQuery like this:

jQuery(function ($) { // First argument is the jQuery object
    // Do stuff to the DOM
    $('body').append('<p>Hello World!</p>');
});
Blixt
  • 49,547
  • 13
  • 120
  • 153
  • 3
    Acually it's a bad practice to load 3rd-party libraries synchronously! If you depend on the order in which they are loaded it's best practice to include the script **at the end of body**, so it's not render-blocking, and is still loaded synchronously, e.g. scripts that are included afterwards are executed after execution of this one. – Andy Apr 06 '16 at 09:13
2

There could be two issues. First, you need to make sure that jQuery is included before any scripts that use it. This can be tricky if you have javascript embedded in partials. If you load jQuery in the header and all of your other script in a script block at the end of the body, you can be sure that jQuery is loaded before your other code. I try to put everything at the end of the body, with jQuery being the first script loaded.

Second, you need to make sure that the DOM is fully loaded before trying to use it in your scripts. jQuery provides a ready method for this. Wrap your code inside the ready method and you can be (more) sure that the DOM is available for you to work with. Not all images may be loaded, but you should be ok with most everything else. For images you may have to take more pains to make sure that they are loaded if that is critical to your code.

<script type='text/javascript' src='.../path-to-jquery/jquery.js'></script>
$(document).ready( function() {
   ...your code here...
});

or (shorthand)

<script type='text/javascript' src='.../path-to-jquery/jquery.js'></script>
$(function() {
   ... your code here...
});
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • I am in the same situation and i can't be sure jquery is fully loaded or not. Because $(document).ready() isn't working and i couldn't write code "if jquery isn't loaded load it again". Is there any way to achieve this? – uzay95 Mar 31 '10 at 06:18
1

When a browser encounters a script element it blocks which means that as long as you have a script element that loads jQuery before any script that wants to use jQuery, you should be fine, e.g.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
    // jQuery is available

    $(document).ready(function(){
        // ...
    });
</script>

See JavaScript Load Order for some additional commentary on this topic.

Community
  • 1
  • 1
Walter Rumsby
  • 7,435
  • 5
  • 41
  • 36
0

In general, you just use the following basic "document loaded" test in jquery. Straight from the beginners jquery tutorial:

 $(document).ready(function() {
   // do stuff when DOM is ready
 });

I can think of any reason why this should not work, there are certainly millions of sites using jquery that relies on precisely this bit of code.

Egil Hansen
  • 15,028
  • 8
  • 37
  • 54
  • Sometimes we use client scripts that by themselves, do not load jquery. These are simple bootstrap scripts that load a remote script. It is in the remote script where I want to load my external libraries, like jQuery. Therefore, I have to do some dynamic DOM modification, like adding jQuery scripts after the fact. It is in these remote scripts where you will find the problems addressed by this question. – TARKUS Sep 06 '13 at 12:09