Tutorial 4 : jQuery primer
If you want to go to the previous tutorial click here
If you want to go to the next tutorial click here
You can download the tutorial resources here
Introduction
Understanding jQuery begins with an understanding of JavaScript. Sometimes jQuery is treated as an independent language that can be used instead of JavaScript. Although jQuery contains many features associated with programming languages, it is best thought of as a library that enhances JavaScript in specific situations. For this reason, JavaScript has been introduced before jQuery.
Before understanding jQuery however, it is worth taking a brief look at the Document Object Model (DOM), since jQuery is primarily a library for dealing with the DOM in a browser independent manner.
Document Object Model
HTML (including XML and XHTML) documents are modelled in memory using a tree structure called the Document Object Model.
Each document has a single parent node, and this node can have children. These nodes in turn can be parents of other children. Each node in the tree (except the head node) has one, and only one parent. All nodes in the tree can have zero or more children.
DOM trees contain several kinds of nodes, the most common of which are element nodes (which represent tags) and text nodes (which represent the content inside tags).
In order to see the inherent tree structure of a document, open the tasks.html document which you can download here, and view it in the “Elements” tab of Chrome's developer tools. Any parent that has children has an arrow beside it that can be expanded. The overall parent of the whole document is the html tag at the start of the document. This has two children: head and body, and each of these have children. Even in this relatively simple document, there are some elements that are eight generations removed from the html element:

The Document Object Model is a technology and language independent API for interacting with HTML documents. The API allows developers to access nodes in the document, traverse the document, and manipulate elements in the document.
Each element in the DOM tree is represented by an object. These objects support an API that allows them to be manipulated. As you will see when we start using jQuery; sometimes we will still encounter native DOM objects, but usually they will be wrapped inside jQuery specific versions of the objects, and expose additional functionality.
All web browsers that support JavaScript support a JavaScript implementation of the DOM API. The specific version of the API they support will depend on the browser however, and this, along with inconsistencies in their implementations, can lead to issues for JavaScript programmers.
In order to see the DOM API in action, open the Chrome console and type the following:
> document
This will return the DOM representation of the HTML document, which is the exact same representation we saw from the Elements tab of the developer tools above. This may differ from the literal document: for instance if the HTML document was not well formed (e.g. it was missing closing tags), the browser will attempt to construct a well-formed representation of the document (according to the rules specified in the HTML5 specification).
The DOM API allows us to access elements based on their characteristics; for instance, we can access the table elements with:
> document.getElementsByTagName('table')
In addition to querying, traversing and manipulating the document, the DOM API also allows event listeners to be added to the nodes in the document. These can be used to detect users clicking buttons, or text being typed into input fields, along with many other types of event.
jQuery does not allow you to do anything with the DOM that could not be done using the native JavaScript API, in fact, jQuery is implemented using the native DOM API, and is therefore essentially an abstraction or wrapper of the DOM API.
Since jQuery does not do anything that cannot be done with the native DOM API you may wonder what is the use of learning jQuery. For one thing, jQuery provides a genuine cross browser implementation of the DOM API, and alleviates the quirks that are found in many browser implementations.
Rather than providing a full set of reasons for using jQuery, I encourage you to work through the examples below. They highlight the elegance and conciseness of the jQuery API, and once you begin using jQuery it is very hard to go back to the native DOM API.
Starting with jQuery
In order to use jQuery you must include the jQuery library in the HTML page. This can be achieved by serving your own copy of the jQuery library, or by utilizing a hosted version from a content delivery network (CDN), most notably Google.
| As a general rule, for production deployment you should favour CDN hosted options. These tend to provide superior performance for users than hosting your own copy. For development I generally prefer to download my own copy, since this removed the need for a network connection to run the application. | |
If you wish to use the Google hosted version of jQuery, simply include it in the head of the HTML file:
In order to serve your own copy, download the latest version of jQuery from here: http://jquery.com/download/ The examples in this book are using 2.0.3, but any recent version will be compatible.
Since Vaizr is using version 1.11.1 this file is added to the totorial resources
jQuery consists of a single JavaScript file that can be downloaded in either minimised or non-minimalized form. The non-minimalized form is useful for debugging, but either version will be appropriate. Here we will use the file which comes with the tutorial resources. Unzipped your directory structure should now look like this:

Now add the following to the head section of the tasks.html HTML file:
In order to verify you have performed these steps correctly, open the page, and open the JavaScript console. Type the following in the console:
> jQuery
function ( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new…
If this gives a result similar as displayed above and does not generate an error, jQuery is ready to go.
Selection
The first thing we are going to do with jQuery is select elements from the document.
Selecting elements obviously has no intrinsic value in its own right; we are eventually going to do something with these elements. A jQuery selection will return zero or more elements from the document. More specifically, the selection will return zero or more jQuery wrapped DOM elements from the document. This distinction will be important in later sections.
In order to perform a selection, simply include the selection criteria inside the following construct:
$('<selection criteria>')
The $ is an alias for the function called jQuery, so we could also use the following construct:
jQuery('<selection criteria>')
The $ alias tends to produce better readability, so we will use that convention in the sections below. The only time to avoid this alias is if you are using any other libraries that use the $ global variable: jQuery does support a no-conflicts mode in this case, and allows you to create a new alias.
The selection criteria utilized by jQuery is in fact essentially the same selection criteria utilized by CSS. This is enormously helpful, since it means you only need to learn the selection language once in order to use CSS and jQuery.
There are five core ways to select elements:
- Element type.
- Element attribute.
- Element class.
- Element ID.
- Pseudo classes.
All five approaches will be briefly outlined below. The first way to select an element is by its type. For instance, if we want to select all the table elements in the document, we can use the following syntax:
> $('table')
This, and all other commands in this chapter, can be run directly in the console after first loading the tasks.html page. This command will return an array of one element, and that element will be the table holding the tasks. If we want to select all the td elements in a document, we can use the following:
> $('td')
This will return an array of 9 elements.
> $('td').length
The second core way we can select elements is based on one of their attributes. If we wish to select all the elements with a placeholder attribute, the following selection can be used:
> $('[placeholder]')
Notice the use of [] brackets around the attribute name. This will find all elements with a placeholder attribute, regardless of its value.
Additionally, we may wish to specify that the element has an attribute with a specific value, in which case the following syntax can be used:
> $('[datetime="2013-10-14"]')
In this case we are mixing single and double quotes, since we wish to express the value as a string inside the string that is the selection criteria.
Selecting elements based on attributes becomes even more useful due to the fact it is possible to add your own custom attributes to HTML elements. Adding custom attributes to elements allows you to associate data with an element, and then use this data in any way we need.
For instance, we may want to denote that a cell in a table represents the name of a task; therefore we could add the following attribute to the element:
<td data-name-field="true">
In order to quickly find all name field nodes, we could then execute the following selection:
> $('[data-name-field]')
Alternatively, we may wish to associate a priority with tasks, so each tr element could include the following:
<tr data-priority="high">
or
<tr data-priority="medium">
We can then select all the high priority rows in the table with the following selection:
> $('[data-priority="high"]')
We will see below that the prefix added to this attribute (“data-“) is more than a convention, and allows for other possibilities. Binding data directly to elements turns out to be an enormously powerful concept. It provides a way to add context to elements in a manner that can be easily understood and processed by code, and therefore allows the same element to have user facing and a computer facing meaning.
| Data attributes should be specified in lower case characters only, and words should be separated with a hyphen. | |
| This is a good general rule with HTML, since all attributes are converted to lower case in the DOM anyway. | |
| As we will see below, these attributes can be returned from elements as an object via the data() method on DOM elements. This will convert the attribute names as follows: | |
data-this-is-long=”true” |
|
| is converted to the following property on the data object: | |
thisIsLong=true |
|
The next way we can select elements in a document is by class. Elements can be given one or more classes with the class attribute. All HTML elements support the class attribute (the restrictions from HTML4 applying to some elements have been removed). Inside tasks.html you will see the following examples:
<input type="text" required="required" name="task" class="large">
<tr class="even">
A class is just an arbitrary name: it is a way of grouping together otherwise unrelated elements to denote they share some characteristic. The characteristic they usually have in common is that they should have the same styles applied via CSS, and therefore the class attribute is usually associated purely with CSS.
In reality classes can be used to group elements for any reason. When using jQuery it is common to assign classes to elements purely to allow jQuery selections to efficiently find related elements.
For instance, in tasks.html every second row in the table is given the class of even. All even rows can be selected using the following selection criteria:
> $('.even')
(Note the “.” at the start of the selection criteria)
| It is possible to apply specific styles to every second row purely through CSS: | |
tr:nth-child(even) { |
|
background-color: #f8f8f8; |
|
} |
|
Using classes for reasons other than CSS matching does not go against the spirit of the HTML5 specification. The specification states that classes are one way that elements can be extended, thereby effectively creating a new type of element.
The fourth basic way to select elements is based on their ID. Any element can be given an ID using the id attribute. ID names are arbitrary, just as class names are, but ID names must be unique within a document.
| HTML5 has relaxed the rules on the values that can be used for IDs. The only rules now are that they must be unique in a document, and cannot be an empty string or contain spaces. The rules for class names are identical. | |
An element can be given an ID as follows:
<table id='tblTasks'>
Once an element has been given an ID it can be selected with the following criteria:
> $('#tblTasks')
(Note the “#” sign at the start of the selection criteria.)
The last way of selecting elements is via jQuery filters. If you are familiar with CSS, these may look the same as CSS pseudo-classes, and they essentially serve the same purpose.
Suppose we want to find the first row in a table. We could add a class to the row, but if the table was re-ordered we would need to make sure this was updated. We could also select all rows from the table into an array and choose the first element, but this is inefficient. With filters we can use the following selection criteria:
> $('tr:first')
(Filters are always prepended with a colon; this is therefore combining two selectors, one to select tr elements, and then another limiting the selection to tr elements that are in the first position amongst their siblings.)
Filters can also accept parameters; therefore we can find any arbitrary row in the table using the following filter:
> $('tr:eq(1)')
This will find the second row in the table (counting starts at 0). Alternatively we may wish to find any row except the first row, so we could use the following filter:
> $('tr:gt(0)')
This is selecting all rows with a position greater than 0. Other useful filters are as follows:
- :even finds all even numbered elements in a selection.
- :odd finds all odd numbered elements in a selection.
- :not(selection) finds all elements that do not match the selection.
- :checked finds radio buttons or check boxes that are checked.
- :selected finds options in select boxes that are selected.
- :contains(text) finds elements that contain a given piece of text.
- :empty finds all elements that have no children.
- :focus finds the element that currently has focus.
- :last finds the last element in a set.
In addition, filters can simplify the process of selecting input elements. Since most input fields use the element type of input, it is necessary to also query on the attribute type. jQuery contains the following filters for finding specific types of input field:
- :hidden
- :text
- :checkbox
- :password
- :radio
- :checkbox
- :file
- :button
for instance, this selects all text input fields:
> $(':text')
One of the nice features about jQuery filters is that you can actually write your own. For instance, jQuery does not provide a filter for finding all the date input types. We can therefore add a custom filter to our code-base as follows:
> jQuery.expr[':'].date = function(elem) {
return jQuery(elem).is( "input" ) && $( elem ).attr( "type" ) === "date";
}
(Don’t worry if this code looks unfamiliar, it will look familiar by the end of the chapter.) When executed, this will be passed all elements in the document (or the specified sub-tree of the document), and returns true or false depending on whether the specified element meets the selection criteria. The result to the caller is all the elements that evaluated to true.
| This function takes advantage of the jQuery is function. The is function is slightly unusual in that it returns true or false rather than a set of elements. | |
Once this has been added to the code-base, the following pseudo class can be used:
> $(':date')
Now that we have investigated the five main selection mechanisms, the next step is to understand how these mechanisms can be combined. We have already been briefly introduced to this concept with pseudo-classes.
The simplest way of combining filters is in cases where elements need to meet two or more selection criteria. For instance, if the :text filter did not exist, it could be written through the combination of two selection criteria. In the first instance, we would need to make sure the element was of type input:
> $('input')
Additionally, the element must have an attribute called type set to the value text:
> $('[type="text"]')
In order to join these two criteria, a single selection criterion can be written as follows:
> $('input[type="text"]')
Notice that there is no space between one criteria and the next – if a space was placed here this would mean something different, as we will see below.
We can use the same approach to match on both element type and class:
> $('input.large')
This will return all elements of type “input” that have a class of “large”.
It should never be necessary to combine selectors based on ID with other types of selector, since IDs are unique within a document.
In addition to combining selectors for criterion relating to a single element, it is often necessary to select all elements that match selection criteria within a particular sub-tree of the document.
Consider a case where we have multiple tables in the same document, but we want to return the first row in a specific table (for instance, the table with the ID tblTasks). In order to achieve this we first need to find the table called tblTasks, and then find the first row within its sub-tree.
jQuery supports several ways of doing this. The most common approach is as follows:
> $('#tblTasks tr:first')
The space denotes the fact that these are two different selections. jQuery performs this by selecting the elements that match the first selection:
$('#tblTasks')
and then executing the second selection against the sub-trees of these elements:
$('tr:first')
In fact, jQuery supports an alternative mechanism for doing this more explicitly:
> $('#tblTasks').find('tr:first')
Yet another approach to performing this same selection is to use the optional second parameter to the jQuery selector:
> $('tr:first', '#tblTasks')
The second parameter is used to specify the root of the sub-tree that the selection should occur within. This can be a useful approach when you know you are dealing with a sub-tree of the document, since you can assign the context to a variable, and then use that in all selections:
> documentContext = $('#tblTasks');
> $('tr:first()', documentContext);
It is possible to specify more than two levels of selection within a single selection criterion. For instance, we may want to find all the td elements in the last row of all the tables in the second section of the document. This can be performed as follows:
> $('section:eq(1) table tr:last td')
Sometimes we may want to be more precise about the relationship between elements. For instance, we may want to select elements that are direct children (rather than just decedents) of another element. This can be accomplished through the use of the “>” sign, for instance:
> $('select[name="category"] > option')
This will find all the option elements within a particular select element, but only because they are direct children of the select box. For instance, this will not return any results:
> $('form > option')
Traversal
Selecting a set of elements from the DOM is an important step, but is only the first step in the process. Once a set of elements has been identified a common second step is to traverse from these elements to another set of elements.
A traversal function always starts with the results of a selection, and then performs a traversal operation on these elements to return a new set of elements.
A common traversal requirement is to traverse from an element, or set of elements, to their siblings. For instance, in tasks.html input fields and their labels are siblings because they share the same parent.
Sibling-based queries can be performed through the siblings function. If we want to find all siblings for the select box with the name of category, we can perform the following query:
> $('select[name="category"]').siblings()
If we want to limit the siblings to elements of type label we can add a selector to the siblings function:
> $('select[name="category"]').siblings('label')
Two other similar functions are next and prev. These return the next and previous sibling element of the selected element. For instance, the following returns the next sibling of all labels in the document:
> $('label').next()
while this returns the previous siblings of all the input fields in the document:
> $('input').prev()
Again, these functions also accept selection criteria if necessary.
Another common traversal requirement is to find specific parents of a given element or set of elements. For instance, we may wish to find the parent of all input fields. This can be achieved with the parent function:
> $('input').parent()
We may also wish to limit this to input fields that have div elements as their parents:
> $('input').parent('div')
A slight variant on this function is the parents function. Instead of returning immediate parents, this returns all ancestors that meet the selection criteria. For instance, the following returns the section element that is the ancestor of each input field:
> $('input').parents('section')
Yet another variant on the same theme is the closest function. This allows us to find the closest ancestor that matches a given selection criteria, starting with a specific set of nodes in the initial selection. This first examines the selected node against the criteria, then works its way up the DOM tree until it finds a match. For instance, if we want to find the closest div to each label, we could use the following selection:
> $('label').closest('div')
Another example of a traversal function is returning the last element. As we have seen, a pseudo-class on the selection itself also supports this. For instance, this returns the last row in the tasks table:
> $('#tblTasks tr').last()
As with all traversal functions, the last function also supports a parameter representing selection criteria allowing you to find the last element that meets specific criteria.
The traversal functions we have examined up until this point all return a new set of elements that typically do not include any of the elements from the original selection. In some cases it is useful to retain the original selection while including additional elements found during the traversal. For instance, suppose we had returned a set of input fields, and now wish to also include all the labels in the result set. This can be achieved with the following:
> $('input').add('label')
A similar mechanism for achieving this is to augment any of the traversal functions above with a request to also add the original elements. For instance, the following call will return all labels and their closest div elements:
> $('label').closest('div').andSelf()
This particular line of code is a good time to introduce another important topic: chaining. Due to the fact that most jQuery function calls return an array of elements, and most jQuery function calls can be invoked on an array of elements, it is very easy to chain a set of function calls together, each acting on the elements returned by the call that preceded it. This process can continue almost indefinitely, for instance:
> $('input').parents('div').last().siblings().children()
If we trace this through, it is doing the following:
- Find all input elements.
- Find any div elements that are parents of these elements.
- Limit the result set to the last div element.
- Find its siblings.
- Find their children.
Chaining allows for very concise code, but it also runs the risk of becoming dense and unreadable.
| This is similar to UNIX pipelining. Pipelining allows multiple applications to be chained together with the result of one forming the input of the other. In UNIX, the key design decision that allows this is the fact that applications return text on standard output, and accept text on standard input. In jQuery the key design decision that allows this is that functions can be called on arrays of elements, and these functions return arrays of elements. | |
Manipulation
The previous two sections on selection and traversal have shown you how a set of elements can be selected from the document. This section is going to introduce you to the ways you can manipulate documents once you have a set of elements to work with.
If you look at the tasks.html document you will see that the second row in the table has a class called even assigned to it. The basic idea is that every second row in the table will be given the even class, and this will change the background colour of the row to make the table easier to read.
As mentioned previously, a real world application would be better off performing this functionality with CSS, but performing this with jQuery provides a nice introduction to DOM manipulation.
Before beginning this section, remove the even class from the second row in the table. After this, refresh the tasks.html page in the browser and ensure all the rows have a white background.
In order to manipulate elements we must first select them. The selection criteria should be fairly standard by now. We first find all the even rows in the body of the table (this ensures we do not change the background of the header row):
> $('tbody tr:even')
This will actually return two rows, since jQuery is counting from 0 the first row in the table and the third row in the table are returned. This still suits our needs, since our only real concern is that every second row is shaded.
We can then manipulate these rows as following:
> $('tbody tr:even').addClass('even')
As soon as you execute this code you will see the DOM update, and the relevant rows of the table will be shaded with a new background color.
In addition to adding classes, we can also remove classes with removeClass and toggle classes with toggleClass. Toggling is a particularly useful technique since it removes the class if the element already has it, or adds the class if the element does not already have the class. This will be used in examples later in this book.
Another requirement we may wish to implement is to add a red * next to the label for all mandatory fields. We know how to find all the mandatory fields; they are the ones with a required attribute (regardless of the value assigned to this attribute):
> $('[required]')
and we can also find their labels as follows:
> $('[required="required"]').prev('label')
The file tasks.css also contains a class called required that is defined as follows:
.required {
color: red;
}
In order to append the * to the label, we will include the * inside a span, and include that span within the label. This ensures it is separated from the label itself. We can dynamically append the span to the label as follows:
> $('[required="required"]').prev('label').append( '<span>*</span>')
If you execute this you will notice a * appear at the end of two of the labels on screen.
This is not quite the finished result, we still need to add the appropriate class to the new spans; so refresh the screen to remove these changes.
You may have noticed that the result of the call above was the labels that had been modified (rather than the spans that were appended to them). We therefore need to select the child spans to these elements, and add the required class to them:
> $('[required="required"]').prev('label').append( '<span>*</span>').children( 'span').addClass('required')
Again, we have managed to achieve the entire operation in a single line through the use of chaining.
An important aspect to understand is that these changes have updated the Document Object Model in real time. In order to see this, highlight one of the red *, and choose “Inspect Element” from the right click menu (this is a shortcut to finding a specific element in the “Elements” tab of the developer tools). You will see the following:

Many of jQuery’s manipulation functions can be utilized to insert new content either before or after existing content. Append is used to insert content inside a specific element, but other examples include:
-
after: this adds content after each element, making the new content the next sibling of the original element. If we had used this in the example above, the span would occur after the closing label tag.
-
before: this is similar to after, except the new element will appear before the original element. If we had used this in the example above, the span would have appeared immediately before the label element.
-
prepend: this creates a new child element at the start of the element (as opposed to append which created the child at the end of the element). If we had used this in the example above, the * would have appeared to the left of the label text, but the span would still be a child of the label.
-
remove: this completely removes an element from the document. You can use this to remove the newly added span elements.
-
replaceWith: this replaces an element or set of elements with a new element or set of elements.
In the examples above we have been adding content to existing elements. Instead of adding content to elements, it is also possible to create content and add it to elements. For instance, the following is a valid jQuery call:
> $('<span>*</span>')
This returns the element specified by the HTML, although obviously that element is not part of the DOM at this point. It is then possible to call manipulation functions to add this element to the document:
> $('<span>*</span>').appendTo('label')
This will append a * as a child element to each label in the document. This approach can also used with the following functions:
-
insertBefore: this function includes the new elements as siblings of the specified element or elements, but places them before them in the DOM.
-
insertAfter: this function includes the new elements as siblings of the specified element or elements, but places them after them in the DOM.
-
prependTo: this function includes the new elements as children of the specified element or elements, but places them at the start of the element, making them the first children.
The element inserted in this manner can be any HTML element or set of elements, including elements selected from the document.
In addition to adding new content to the DOM, some manipulation functions operate on characteristics of individual elements to either return information about them, or to manipulate this information. For instance, to find the value of the select element in the document we can execute:
> $('select').val()
The same function can be passed a value if we want to change the current value. If you execute the following the value of the select field will immediately change:
> $('select').val('Work')
| An important note regarding this call is that if any event listeners are registered to detect changes to this element, they will not be notified with this call. | |
| In order to notify any listeners of a change to the element, the following call could be used: | |
$('select').val('Work').change() |
|
| Event listeners will be covered in detail later in this chapter. | |
Other similar functions are:
- html: this returns or manipulates the html of an element.
- text: this returns the text (or content) of an element. The text is the content between the elements tags.
- attr: this returns or manipulates the value of an attribute on an element.
These functions are also a little different from some of the others we have examined in that they only operate on a single element. For instance, if you execute the following:
> $('div').html()
Only the HTML for the first element in the set of matched elements will be returned, rather than the HTML of all elements. Some jQuery functions are inherently limited in this way. In order to execute these functions on multiple elements, it is necessary to loop through those elements. This will be shown later in this chapter.
Events
The next aspect of jQuery to understand is events. When writing web applications, the application will need to respond to events initiated by the user.
These events may be any of the following:
- Clicking a link or button.
- Double clicking a button or link.
- Changing the value in a text field.
- Pressing a particular key inside an input field.
- Selecting an option in a select list.
- Focusing on an input field.
- Hovering the mouse over an element.
In addition to these user-initiated events, the application may wish to respond to browser-initiated events such as:
- The document has finished loading.
- The web browser window is resized.
- An error occurring.
This section will first explain the ways event listeners can be registered, and will then look at some of these events in detail.
Before beginning, we will add the examples above permanently to the tasks.html page. In order to do this, add the following block immediately before the closing