When exactly the $(document).ready callback is executed?

JavascriptJquery

Javascript Problem Overview


Suppose that we attach a .click() handler to an anchor (<a>) tag in the $(document).ready callback. This handler will cancel the default action (following the href) and show an alert.

What I would like to know is when exactly the callback will execute and is it possible for the user to click on the anchor (the document has been shown in the browser) but the event hasn't been attached yet.

Here are different HTML pages that contain an anchor but the order of inclusion of the scripts is different. What's the difference (if any) between them? Will different browsers behave differently?

Page1:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
	$(function() {
	    $('a').click(function() {
		    alert('overriding the default action');
		    return false;
		});
    });
    </script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
</body>
</html>

Page2:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Page3:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

So is it possible that a user gets redirected to the href by clicking on the anchor and never sees the alert (ignoring the case of javascript disabled of course)? Could this happen in any of the examples I provided?

All that I need is to make sure that the click event handler has been attached to the anchor before the user has any possibility to click on this anchor. I know that I can provide an empty href and then progressively enhance it in javascript but this is a more general question.

What will happen in case that the HTML is quickly generated by the web server but the jquery library takes time to be fetched from a distant server? Will this influence my scenario? What's the order of inclusion of the scripts compared to loading the DOM? Could they be done in parallel?

Javascript Solutions


Solution 1 - Javascript

Example 3 will have the highest chance of the user being able to click on the link without the handler having attached itself yet. Since you are loading the jQuery library after the link is rendered, if Google's servers are a little slow (or the DNS lookup takes a second or so), or the users computer is slow to process jQuery, the link will not have its click handler attached when the user tries to click it.

Another situation where this might happen is if you have a very large or slow loading page and this link is at the top. Then the DOM may not be fully ready when parts of it are visible. If you are running into a problem like this, the safest thing to do is:

  1. Load jQuery in the head (example 1 or 2)
  2. Attach the click event immediately after the <a> element, but not in a DOMReady callback. This way it will be called immediately and will not wait for the rest of the document.

Once an element is rendered, it can be grabbed from the DOM, and subsequently jQuery can access it:

<a href="http://www.google.com">Test</a>
<script type="text/javascript>
    // No (document).ready is needed. The element is availible
    $('a').click(function() {
        alert('overriding the default action');
        return false;
    });
</script>

Additionally, building on user384915's comment, if the action is fully dependent on JavaScript, then don't even render it as part of the HTML, add it after jQuery is ready:

<script type="text/javascript">
jQuery(function($){
   $("<a />", { 
      style: "cursor: pointer", 
      click: function() {
        alert('overriding the default action');
        return false;
      },
      text: "Test"
   }).prependTo("body");
});
</script>

Solution 2 - Javascript

You have a couple of different questions here

> When exactly the $(document).ready > callback is executed?

It is executed as soon as the DOM is fully loaded. NOT when everything (such as images) are finished downloading like .load() would be. It is (in general) before that, basically it is when the page its self is built.

> What I would like to know is when > exactly the callback will execute

When it is clicked.

> is it possible for the user to click > on the anchor (the document has been > shown in the browser) but the event > hasn't been attached yet.

Yes, it is possible. But putting it in the .ready() give you the best chance that it will not. There are only 2 ways to do it to be 'more sure' that it will not. These are actually using the 'onclick' on the link its self, and putting the javascript directly after the link (and not in the .ready()) so that is executed immediately after the link is created.

Also, there is no difference between how the 2 code samples you provided will work. However, in the second one you do not need to put the code in the .ready(), because it exists after the link, it will always be executed after the link has been created. If you removed it from the .ready() it would be the first of the 2 ways I described above.

Additionally, instead of putting 'return false;' in your callback, it is better to use .preventDefault() and .stopPropagation() this will let you specify if you want to prevent the default action or stop the event from bubbling, or both.

Solution 3 - Javascript

It depends on many things. If you have chunked encoding for example it is possible that a user will get a chunk but because the document is not ready yet the the listener will not be attached.

The jQuery ready event is the DOMContentLoaded event in W3C compliant browsers (standardized in the HTML5 specification), and some alternatives of this in others (like readystate in IE).

> DOMContentLoaded (MDC) > > Fired at the page's Document object > when parsing of the document is > finished. By the time this event > fires, the page's DOM is ready.

Because this happens before rendering it would be a solid assumption that a callback executed after this event will be able to prevent user interaction on a not-ready page.

But as as Peter Michaux pointed out in his article due the the differences of how browsers implement this event "a robust technique for early enlivenment is not possible across the big four browsers."

So I would say that you can't rely 100% on jQuery ready event, but most of the time it will work just fine.

Solution 4 - Javascript

In YUI, there are the methods onContentReady() and onAvailable(). unfortunately there is no equivalent to that in jQuery. However there is a plugin that was inspired by them:

http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/

This should allow you to bind the events to the anchor before the DOM is fully loaded.

Solution 5 - Javascript

Your third example provides the greatest chance of the user clicking without the override handler having been attached. The browser generally downloads and parses each <script> before moving on to the next. You're pulling in jQuery from an external source (Google) -- which, while likely reliable, could be unavailable or slow to load. You've got both <script> blocks at the end of your document <body>, so previous areas of the page will probably already have been downloaded and rendered to screen while these last two scripts are handled. While this approach is advocated to present a responsive page load experience to the user, they could click during this uncertain period, and of course the override handler would not yet have been attached.

There's an interesting YUIblog article on scripts and load order here.

Solution 6 - Javascript

For sure it's possible to "cheat" the alert warning (even if the Javascript is enabled). Try to drag the link in the url field and you will see that it will be executed without that warning. This is especially problematic if the link is triggering the delete action.

About the document.ready callback - I have such problem too. Let me explain. We doing a project where all forms are displaying in popups (jQuery window). So when the popup is closed (for now) the page is reloaded, and I had cases when I am redirected to another screen instead of opening a new popup.

Totally agree with user384915 about putting javascript directly on the onClick event or even better to href tag.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDarin DimitrovView Question on Stackoverflow
Solution 1 - JavascriptDoug NeinerView Answer on Stackoverflow
Solution 2 - JavascriptMatt EvanoffView Answer on Stackoverflow
Solution 3 - JavascriptgblazexView Answer on Stackoverflow
Solution 4 - JavascriptKen EarleyView Answer on Stackoverflow
Solution 5 - JavascriptKen RedlerView Answer on Stackoverflow
Solution 6 - JavascriptNik ChankovView Answer on Stackoverflow