Channels ▼
RSS

JVM Languages

Getting Started with jQuery


Asynchronous Loading with jQuery

jQuery provides a fairly large number of methods to make Ajax requests. Some are simple and useful high-level methods that initiate Ajax requests to perform some of the most commonly required tasks. Others are more low-level, providing control over every aspect of the Ajax request.

We'll employ a representative handful of these methods in the solutions within this section. First, let's tackle one of the most common of Ajax interactions: obtaining dynamic content from the server.

Problem

Let's imagine that we own an eFridge -- a hypothetical high-tech refrigerator that not only keeps track of what its contents are, but also provides an Internet interface that server software can use to communicate and interact with the eFridge.

The imaginary technology used by the eFridge to keep track of its inventory is unimportant. It could be bar-code scanning, RFID (Radio Frequency Identification) tags, or some yet-to-be-imagined technology. All we care about as page authors is that we have a server component to which we can make requests in order to obtain information about the state of our food!

The page we'll focus on will present a list of the items that are in our eFridge. Upon clicking on an item in this list, more information about the item will be displayed.

For this problem, we'll assume that the page was prepopulated with the list of items by whatever server-side templating mechanism generated our page. In the next section, we'll see a technique to obtain this list dynamically from the server.

Solution

To begin, in order to use jQuery on a page it is necessary to import the jQuery library:

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

The list of items in the eFridge, which we're assuming was generated on our behalf by some server-side mechanism, is presented in a select element:

<form>
  <select id="itemsControl" name="items" size="10">
    <option value="1">Milk</option>
    <option value="2">Cole Slaw</option>
    <option value="3">BBQ Sauce</option>
    <option value="4">Lunch Meat</option>
    <option value="5">Mustard</option>
    <option value="6">Hot Sauce</option>
    <option value="7">Cheese</option>
    <option value="8">Iced Tea</option>
  </select>
</form>

For the purpose of this example, we're only showing eight items. The average refrigerator would probably contain more than this, but we all know fast-food junkies whose refrigerator contents are sometimes pretty sparse.

The server (perhaps some "eFridge driver") assigns each item an identification number that is used to uniquely identify each item_in this case, a simple sequential integer value. This identifier is set as the value for each option> representing an item.

Even though we know that we need the select control to react to user input, note that no handlers are declared within the markup that creates the select> element. This brings up another philosophy behind the design of jQuery.

One of the goals of jQuery is to make it easy for page authors to separate script from document markup, much in the same manner that CSS allows us to separate presentation from the document markup. Granted, we could do it ourselves without jQuery's help -- after all, jQuery is written in JavaScript and doesn't do anything we couldn't do -- but jQuery does a lot of the work for us, and is designed with the goal of easily separating script from document markup. So, rather than adding an onchange event handler directly in the markup of the
select> element, we'll use jQuery's help to add it under script control.

We can't manipulate the DOM elements on our page until after the document is ready, so in the script> element in our page header, we'll institute a jQuery ready() handler as we previously discussed. Within that handler, we'll use jQuery's method to add a change handler to an element, as shown in the following code fragment:

$(document).ready(function(){
   $('#itemsControl').change(showItemInfo);
});

In the ready() handler, we create a jQuery instance that wraps the select> element, which we have given the id of itemsControl. We then use the jQuery change() method, which assigns its parameter as the change handler for the wrapped element.

In this case, we've identified a function named showItemInfo(). It's within this function that we'll make the Ajax request for the item that is selected from the list:

function showItemInfo() {
   $('div#itemData').load(           #1  
     'fetchItemData.jsp',            #2
     {itemId: $(this).val()}         #3 
   );
}

  • #1 Wraps element and invokes load method
  • #2 Identifies server-side resource
  • #3 Obtains item id and passes as parameter

jQuery provides a fair number of different ways to make Ajax requests to the server. For the purposes of this solution, we'd like to fetch a pre-formatted snippet of HTML from the server (containing the item data) and load it into a waiting element, that is, a div> element having an id of itemData. The jQuery load() method (#1) serves this requirement perfectly.

This method fetches a response from a URL provided as its first parameter and inserts it into the wrapped DOM element. A second parameter to this function allows us to pass an object whose properties serve as the parameters for the request. A third parameter can be used to specify a callback function to be executed when the request completes.

First, we wrap a DOM element (#1) identified by the CSS selector div#itemData, which is an empty div> element into which we want the item data to be loaded. Then, using the load() method, we provide the URL to a JSP page (#2) that will fetch the item data identified by the itemId request parameter supplied in the second method parameter (#3).

The value of that parameter needs to be the value of the option that the user clicks on in the select> element. Because the select7> element is set as the function context of the change handler, it is available to it via the this reference. We wrap that reference and use JQuery's val() method to obtain the current selected value of the control (#3).

Since all we want to do is to load the item data into the DOM, we have no need for a callback and omit the third parameter to the load() method.

That's all there is to it.

jQuery's capabilities have taken a very common procedure that might have taken a nontrivial amount of code to implement and allow us to perform it with very few lines of simple code. The JSP page that gets invoked by this handler uses the value of the itemId request parameter to fetch the info for the corresponding item and formats it as HTML to be displayed on the page.

Our finished page, shown here after selecting a refrigerator item:

Got milk?

is laid out in its entirety in this listing:

<html>
  <head>
    <title>What's for dinner?</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
         $('#itemsControl').change(showItemInfo);
      });

      function showItemInfo() {
         $('div#itemData').load(
           'fetchItemData.jsp',
           {itemId: $(this).val()}
         );
      }
    </script>
    <style type="text/css">
      form,#itemData {
        float: left;
      }
    </style>
  </head>

  <body>
    <form>
      <select id="itemsControl" name="items" size="10">
        <option value="1">Milk</option>
        <option value="2">Cole Slaw</option>
        <option value="3">BBQ Sauce</option>
        <option value="4">Lunch Meat</option>
        <option value="5">Mustard</option>
        <option value="6">Hot Sauce</option>
        <option value="7">Cheese</option>
        <option value="8">Iced Tea</option>
      </select>
    </form>

    <div id="itemData"></div>
  </body>
</html>

Discussion

This section introduced us to one of JQuery's means of performing Ajax requests, the load() method.

The jQuery load() method is very well suited for use with server-side templating languages such as JSP and PHP that make it a snap to format and return HTML as the response. The fetchItemData.jsp file, as well as the Java classes that fake the eFridge functionality, are downloadable.

A few other important jQuery features are also exposed in this solution. For example, we used a ready()handler to trigger the execution of code that must execute before a user is allowed to interact with the page, but after the entire DOM has been constructed for the page.

We also saw the val() method, which returns the value of the wrapped input element. If more than one element is wrapped, the value of the first matched element is returned by this method.

In this solution, we assumed that the original list of eFridge contents was generated by whatever server-side resource produced the page; a JSP template, for example. That's a common expectation for a web application, but in the interest of exploring more of jQuery's Ajax abilities, let's pretend that we need to fetch that list dynamically upon page load in the next problem.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video