jQuery Succinctly: Core jQuery

Base Concept Behind jQuery

While some conceptual variations exist (e.g. functions like $.ajax) in the jQuery API, the central concept behind jQuery is "find something, do something." More specifically, select DOM element(s) from an HTML document and then do something with them using jQuery methods. This is the big picture concept.

To drive this concept home, reflect upon the code below.

Notice that in this HTML document we are using jQuery to select a DOM element (<a>). With something selected, we then do something with the selection by invoking the jQuery methods text(), attr(), and appendTo().

The text method called on the wrapped <a> element and set the display text of the element to be "jQuery." The attr call sets the href attribute to the jQuery Web site.

Grokking the "find something, do something" foundational concept is critical to advancing as a jQuery developer.

The Concept, Behind the Concept, Behind jQuery

While selecting something and doing something is the core concept behind jQuery, I would like to extend this concept to include creating something as well. Therefore, the concept behind jQuery could be extended to include first creating something new, selecting it, and then doing something with it. We could call this the concept, behind the concept, behind jQuery.

What I am trying to make obvious is that you are not stuck with only selecting something that is already in the DOM. It is additionally important to grok that jQuery can be used to create new DOM elements and then do something with these elements.

In the code example below, we create a new <a> element that is not in the DOM. Once created, it is selected and then manipulated.

The key concept to pick up here is that we are creating the <a> element on the fly and then operating on it as if it was already in the DOM.

jQuery Requires HTML to Run in Standards Mode or Almost-Standards Mode

There are known issues with jQuery methods not working correctly when a browser renders an HTML page in quirks mode. Make sure when you are using jQuery that the browser interprets the HTML in standards mode or almost standards mode by using a valid doctype.

To ensure proper functionality, code examples in this book use the HTML 5 doctype.

Waiting on the DOM to Be Ready

jQuery fires a custom event named ready when the DOM is loaded and available for manipulation. Code that manipulates the DOM can run in a handler for this event. This is a common pattern seen with jQuery usage.

The following sample features three coded examples of this custom event in use.

Keep in mind that you can attach as many ready() events to the document as you would like. You are not limited to only one. They are executed in the order they were added.

Executing jQuery Code When the Browser Window Is Completely Loaded

Typically, we do not want to wait for the window.onload event. That is the point of using a custom event like ready() that will execute code before the window loads, but after the DOM is ready to be traversed and manipulated.

However, sometimes we actually do want to wait. While the custom ready() event is great for executing code once the DOM is available, we can also use jQuery to execute code once the entire Web page (including all assets) is completely loaded.

This can be done by attaching a load event handler to the window object. jQuery provides the load() event method that can be used to invoke a function once the window is completely loaded. Below, I provide an example of the load() event method in use.

Include All CSS Files Before Including jQuery

As of jQuery 1.3, the library no longer guarantees that all CSS files are loaded before it fires the custom ready() event. Because of this change in jQuery 1.3, you should always include all CSS files before any jQuery code. This will ensure that the browser has parsed the CSS before it moves on to the JavaScript included later in the HTML document. Of course, images that are referenced via CSS may or may not be downloaded as the browser parses the JavaScript.

Using a Hosted Version of jQuery

When embedding jQuery into a Web page, most people choose to download the source code and link to it from a personal domain/host. However, there are other options that involve someone else hosting the jQuery code for you.

Google hosts several versions of the jQuery source code with the intent of it being used by anyone. This is actually very handy. In the code example below I am using a <script> element to include a minified version of jQuery that is hosted by Google.

Google also hosts several previous versions of the jQuery source code, and for each version, minified and non-minified variants are provided. I recommend using the non-minified variant during development, as debugging errors is always easier when you are dealing with non-minified code.

A benefit of using a Google hosted version of jQuery is that it is reliable, fast, and potentially cached.

Executing jQuery Code When DOM Is Parsed Without Using Ready()

The custom ready() event is not entirely needed. If your JavaScript code does not affect the DOM, you can include it anywhere in the HTML document. This means you can avoid the ready() event altogether if your JavaScript code is not dependent on the DOM being intact.

Most JavaScript nowadays, especially jQuery code, will involve manipulating the DOM. This means the DOM has to be fully parsed by the browser in order for you to operate on it. This fact is why developers have been stuck on the window.onload roller coaster ride for a couple of years now.

To avoid using the ready() event for code that operates on the DOM, you can simply place your code in an HTML document before the closing </body> element. Doing so ensures the DOM is completely loaded, simply because the browser will parse the document from top to bottom. If you place your JavaScript code in the document after the DOM elements it manipulates, there is no need to use the ready() event.

In the example below, I have forgone the use of ready() by simply placing my script before the document body closes. This is the technique I use throughout this book and on the majority of sites I build.

If I were to place the <script> before the <p> element, it would execute before the browser had loaded the <p> element. This would cause jQuery to assume the document does not contain any <p> elements. However, if I were to use the jQuery custom ready() event, then jQuery would not execute the code until the DOM was ready. But why do this, when we have control over the location of the <script> element in the document? Placing jQuery code at the bottom of the page avoids having to using the ready() event. In fact, placing all JavaScript code at the bottom of a page is a proven performance strategy.

Grokking jQuery Chaining

Once you have selected something using the jQuery function and created a wrapper set, you can actually chain jQuery methods to the DOM elements contained inside the set. Conceptually, jQuery methods continue the chain by always returning the jQuery wrapper set, which can then be used by the next jQuery method in the chain. Note: Most jQuery methods are chainable, but not all.

You should always attempt to reuse the wrapped set by leveraging chaining. In the code below, the text(), attr(), and addClass() methods are being chained.

Breaking the Chain With Destructive Methods

As mentioned before, not all jQuery methods maintain the chain. Methods like  text() can be chained when used to set the text node of an element. However, text() actually breaks the chain when used to get the text node contained within an element.

In the example below, text() is used to set and then get the text contained within the <p> element.

Getting the text contained within an element using text() is a prime example of a broken chain because the method will return a string containing the text node, but not the jQuery wrapper set.

It should be no surprise that if a jQuery method does not return the jQuery wrapper set, the chain is thereby broken. This method is considered to be destructive.

Using Destructive jQuery Methods and Exiting Destruction Using End()

jQuery methods that alter the original jQuery wrapper set selected are considered to be destructive. The reason is that they do not maintain the original state of the wrapper set. Not to worry; nothing is really destroyed or removed. Rather, the former wrapper set is attached to a new set.

However, fun with chaining does not have to stop once the original wrapped set is altered. Using the end() method, you can back out of any destructive changes made to the original wrapper set. Examine the usage of the end() method in the following example to understand how to operate in and out of DOM elements.

Aspects of the jQuery Function

The jQuery function is multifaceted. We can pass it differing values and string formations that it can then use to perform unique functions. Here are several uses of the jQuery function:

  • Select elements from the DOM using CSS expressions and custom jQuery expressions, as well as selecting elements using DOM references: jQuery('p > a') or jQuery(':first') and jQuery(document.body)
  • Create HTML on the fly by passing HTML string structures or DOM methods that create DOM elements: jQuery('<div id="nav"></div>') or jQuery(document.createElement('div'))
  • A shortcut for the ready() event by passing a function to the jQuery function: jQuery(function($){/* Shortcut for ready() */})

Each of these usages is detailed in the code example below.

Grokking When the Keyword This Refers to DOM Elements

When attaching events to DOM elements contained in a wrapper set, the keyword this can be used to refer to the current DOM element invoking the event. The following example contains jQuery code that will attach a custom mouseenter event to each <a> element in the page. The native JavaScript mouseover event fires when the cursor enters or exits a child element, whereas jQuery's mouseenter does not.

Inside the anonymous function that is passed to the mouseenter() method, we use the keyword this to refer to the current <a> element. Each time the mouse touches the "jQuery.com" text, the browser will alert which element has been moused-over by identifying its id attribute value.

In the previous example, it is also possible to take the this reference and pass it to the jQuery function so that the DOM element is wrapped with jQuery functionality.

So instead of this:

We could have done this:

This is possible because the jQuery function not only takes selector expressions, it will also take references to DOM elements. In the code, this is a reference to a DOM element.

The reason you might want to wrap jQuery functionality around a DOM element should be obvious. Doing so gives you the ability to use jQuery chaining, should you have need for it.

Iterating over a set of elements contained in the jQuery wrapper set is somewhat similar to the concept we just discussed. By using the jQuery each() method, we can iterate over each DOM element contained in a wrapper set. This allows access to each DOM element individually, via the usage of the this keyword.

Building upon the markup in the previous example, we can select all <a> elements in the page and use the each() method to iterate over each <a> element in the wrapper set, accessing its id attribute. Here is an example.

If you were to load the HTML in a browser, the browser would alert for the id value of each <a> element in the page. Since there are three <a> elements in the page, you get three iterations via the each() method and three alert windows.

Extracting Elements From a Wrapper Set, Using Them Directly Without jQuery

Just because you wrap jQuery functionality around an HTML element does not mean you lose access to the actual DOM element itself. You can always extract an element from the wrapper set and operate on the element via native JavaScript. For example, in the code below I am setting the title attribute of the <a> element in the HTML page by manipulating the native title property of the <a> DOM element.

As demonstrated, jQuery provides the handy get() method for accessing DOM elements at a specific index in the wrapper set.

But there is another option here. You can avoid using the get() method by simply using the square bracket array notation on the jQuery object itself. In the context of our prior code example:

This code:

Could become this:

Both allow access to the actual DOM element. Personally, I prefer square bracket notation. It is faster because it uses native JavaScript to retrieve the element from an array, instead of passing it to a method.

However, the get() method provides a slick solution for placing all of the DOM elements into a native array. By simply calling the get() method without passing it an index parameter, the method will return all of the DOM elements in the wrapper set in a native JavaScript array.

To demonstrate, let's take get() for a test drive. In the code below, I am placing all the <a> elements into an array. I then use the array to access the title property of the third <a> DOM object on the page.

Notes: Using get() will end jQuery's chaining. It will take the wrapper set and change it into a simple array of DOM elements that are no longer wrapped with jQuery functionality. Therefore, using the .end() method cannot restore chaining after .get().

Checking to See if the Wrapper Set Is Empty

Before you begin to operate on a wrapper set, it is logical to check that you have, in fact, selected something. The simplest solution is to use an if statement to check if the wrapper set contains any DOM elements.

The truth of the matter is the above if statements are not totally necessary, because jQuery will fail silently if no elements are found. However, each method chained to any empty wrapper set still gets invoked. So while we could actually forgo the use of the if statements, it is likely a good rule of thumb to use them. Invoking methods on an empty wrapper set could potentially cause unnecessary processing, as well as undesirable results if methods return values other than the wrapper set, and those values are acted upon.

Creating an Alias by Renaming the jQuery Object Itself

jQuery provides the noConflict() method which has several uses-namely, the ability to replace $ with another alias. This can be helpful in three ways: It can relinquish the use of the $ sign to another library, help avoid potential conflicts, and provide the ability to customize the namespace/alias for the jQuery object.

For example, let's say that you are building a Web application for company XYZ. It might be nice to customize jQuery so that instead of having to use jQuery('div').show() or $('div').show() you could use XYZ('div').show() instead.

Notes:By passing the noConflict() function a Boolean value of true, you can completely undo what jQuery has introduced into the Web page. This should only be used in extreme cases because it will, more than likely, cause issues with jQuery plugins.

Using .each() When Implicit Iteration Is Not Enough

Hopefully, it is obvious that if you have an HTML page (example below) with three empty <div> elements, the following jQuery statement will select all three elements on the page, iterate over the three elements (implicit iteration), and will insert the text "I am a div" in all three <div> elements.

This is considered implicit iteration because jQuery code assumes you would like to manipulate all three elements, which requires iterating over the elements selected and setting the text node value of each <div> with the text "I am a div." When this is done by default, it is referred to as implicit iteration.

This is pretty handy. For the most part, the majority of the jQuery methods will apply implicit iteration. However, other methods will only apply to the first element in the wrapper set. For example, the jQuery method attr() will only access the first element in the wrapper set when used to get an attribute value.

Notes:When using the attr() method to set an attribute, jQuery will actually apply implicit iteration to set the attribute and its value to all the elements in the wrapper set.

In the code below, the wrapper set contains all <div> elements in the page, but the attr() method only returns the id value of the first element contained in the wrapper set.

For the sake of demonstration, assume your goal is actually to get the id attribute value for each element on the page. You could write three separate jQuery statements accessing each <div> element's id attribute value. If we were to do that, it might look something like this:

That seems a bit verbose, no? Wouldn't it be nice if we could loop over the wrapper set and simply extract the id attribute value from each of the <div> elements? By using the $().each() method, we invoke another round of iteration when our wrapper set requires explicit iteration to handle multiple elements.

In the code example below, I use the $().each() method to loop over the wrapper set, access each element in the set, and then extract its id attribute value.

Imagine the possibilities ahead of you with the ability to enforce iteration anytime you please.

Notes: jQuery also provides a $.each function, not to be confused with the $().each method, which is used specifically to iterate over a jQuery wrapper set. The $.each method can actually be used to iterate over any old JavaScript array or object. It is essentially a subsitute for native JavaScript loops.

Elements in jQuery Wrapper Set Returned in Document Order

The selector engine will return results in document order as opposed to the order in which the selectors were passed in. The wrapper set will be populated with the selected elements based on the order each element appears in the document, from top to bottom.

Determining Context Used By the jQuery Function

The default context used by the jQuery function when selecting DOM elements is the document element (e.g. $('a', document)). This means that if you do not provide the jQuery function (e.g. jQuery()) with a second parameter to be used as the context for the DOM query, the default context used is the document element, more commonly known as <body>.

It is possible to determine the context in which the jQuery function is performing a DOM query by using the context property. Below I show two coded examples of retrieving the value of the context property.

Creating Entire DOM Structure, Including DOM Events, in a Single Chain

By leveraging chaining and jQuery methods, you can create not only a single DOM element, but entire DOM structures. Below I create an unordered list of jQuery links that I then add to the DOM.

The concept you need to take away from the previous example is that jQuery can be used to craft and operate complex DOM structures. Using jQuery methods alone, you can whip up most any DOM structure you might need.



Related Articles