I am going through http://docs.jquery.com/How_jQuery_Works and find the requirement of enclosing $.click()
event in $(document).ready()
even a litt
Yes, you need to make sure that the DOM element to which you are adding the click handler exists, any you know this by the document being ready.
Javascript usually starts executing as soon as the tag is read. This means that in the standard practice of putting scripts in the head, there are NO elements created yet for you to bind a click handler to. Even the body element doesn't exist yet. Using jQuery.ready delays executing your code until all DOM elements have been loaded.
It's not the actual call to .click()
which is the concern here, but rather the selector for the element on which it's called.
For example, if there is an element with id="myButton"
then you would reference it with:
$('#myButton')
However, if that element isn't yet loaded (that is, if the document isn't yet ready and you don't know what elements are currently loaded), then that selector won't find anything. So it won't call .click()
on anything (either to bind the event or to fire it, depending on the argument(s) to .click()
).
You can use other approaches, such as the jQuery .on() function, which can bind events to common parent elements and filter "bubbled up" events from ones added later later in the life of the document. But if you're just using a normal selector and calling a function then the selector needs to find something within the DOM in order for the function to do anything.
The problem the $(document).ready(..)
method is trying to solve is the tension between the execution of the javascript code for the page and the time at which controls in the page are bound. The ready
function will fire once the document is ready and DOM elements are available hence the javascript code can make reasonable assumptions about the DOM
The most common example is the location of javascript code with respect to the DOM elements it's trying to operate on. Consider
<script>
$('#target').click(function() {
alert('It was clicked');
});
</script>
<div id="target">Click Me</div>
In this particular example the javascript will not function as intended. When the script block is entered the click
line is run and there currently is no DOM element with the id target
hence the handler binds to nothing. There is nothing really wrong with the code, it just had the unfortunate timing to run before the DOM element was created.
In this example the problem is obvious because the code and DOM element are visually paired together. In more complex web pages though the javascript is often in a completely separate file and has no visual guarantees about load ordering (nor should it). Using the $(document).ready(..)
abstraction removes the question of ordering as a potential source of problems and facilitates proper separation of concerns
The How jQuery Works document uses the example of binding a .click()
inside of $(document).ready()
to be certain that the element to which the .click()
event is bound has been created when the function executes.
The .click()
called with a function as its parameter does not execute the .click()
on the nodes matching its preceding selector, but rather binds the function to the matching nodes' onclick
.
If you were to attempt to do something like this:
$('a').click(function(){
alert('clicked me');
});
...in the document <head>
or before any <a>
element had been rendered, the event would not get bound to any node since no node matching the $('a')
selector existed at the time the function executed.
Furthermore, if you did it when some <a>
tags had been created, only those already created would get the bound event. <a>
tags created after the function was bound wouldn't have the .click()
binding.
So in jQuery (and other JavaScript frameworks), you'll often see the convention of adding event handlers, binding widgets, etc, inside a $(document).ready(function(){});