Screencasts

Using AJAX with jQuery

Download Files ↓

Show Notes

Overview

jQuery has an arsenal of tools for you to include dynamic data in your web application. There are many different techniques which may suit one situation over another. In this screencast we'll show you several ways that jQuery can load information off the web, which you can start using to enhance your projects right away.

What You'll Learn:

  • How to load fragments of HTML into container elements using the .load() method
  • How to transverse XML and use JSON to load data dynamically into multiple parts of a page
  • Why JSON is preferred data format over XML
  • How to set global and local callbacks
  • Best practices for jQuery development

Links

Script

Welcome to the Using AJAX with jQuery screencast. This episode builds off of some basic jQuery knowledge that we’re going to assume you already know. If you’re new to jQuery, we recommend that you first watch our Introduction to jQuery screencast, which you can download now at Screencasts.org.

Introduction

jQuery has an arsenal of tools for you to include dynamic data in your web application. There are many different techniques which may suit one situation over another. In this screencast we'll show you several ways that jQuery can load information off the web, which you can start using to enhance your projects right away.

History

What is AJAX?

AJAX is a term that describes loading data dynamically without loading a new page. The browser sends a request in the background, and upon success or error, a callback is triggered and then the data can be displayed or used. While AJAX stands for Asyncronous Javascript And XML, the term AJAX now tends to cover all dynamically loaded content, whether it’s XML, HTML, JSON or even JavaScript.

Why use jQuery for AJAX?

Historically, browsers implemented AJAX calls using different methods. Programmers would need to setup if-statements to apply different code for different browsers. jQuery abstracts these differences away so the programmer doesn’t have be concerned with browser compatibility.

AJAX rules

When planning your web application’s functionality, it’s important to know that you can’t load data from external domains directly via AJAX. If for some reason you do need to load data from another domain, you’ll need to create a server-side proxy script to trick the browser into thinking the data is from the local domain. The only exception to this is JSON. JSON stands for JavaScript Object Notation. You can load JSON from an external domain by specifying a callback to pass the JSON data into. This is called JSONP, or JSON with padding.

AJAX in jQuery Example

There are many ways of including dynamic data in jQuery which will suit various situations.

In our example we have an image gallery. We have several pages with images on them, and in our later example they’ll have a set of comments. The code for this example is in the show notes.

As you can see we have an image gallery with 5 images. When you click each of the links in the menu a new page loads. You may notice on some social networks and image galleries, that the page doesn’t reload when you click on a next link. This leaves the page template behind, and simply swaps out the image and any additional content.

The .load() method

The simplest way to do this is by using the .load() method.

What we want to do is swap out the image and the caption without loading an entirely new page.

First, in the gallery1 folder, open up picture1.html in your editor. As you can see, within the container div we have two paragraph tags, one with an image and another with a caption.

<p>
    <img src="../images/flower1-300.jpg" alt="Picture 1" />
</p>
<p class="caption">
    Picture 1
</p>

At the bottom of the file we have jQuery already included, ready for us to code.

Let’s create a script tag for us to place our code.

We need to attach a click listener to our menu links.

$("#menu a").click(function(){
    return false;
});

In our anonymous function we need to load the path of the link.

$("#menu a").click(function(){
    $("#container").load(this.href);
    return false;
});

The .load() method works by calling it on the jQuery representation of a given element. Once it’s called, it loads the HTML fragment from the path passed into it as the first argument.

In this example, the div will have the contents of the fragment.html file loaded within it.

$("div").load("path/to/fragment.html")

If the fragment contains more information than what’s needed, you’ll need to specify the CSS selector for the content you wish to load into your element.

In this example the div will only have elements with the class "dynamic_data" loaded into it.

$("div").load("path/to/fragment.html  .dynamic_data")

In our example we want to load the path of the link we’ve just clicked, this.href, into our container div. As you can see, this doesn’t load as we’d like it, because the fragment we’re loading isn’t a fragment, but a full HTML page. So we need to select the content we want to inject. This can be done by adding the CSS selector " #container p".

$("#menu a").click(function(){
    $("#container").load(this.href + " #container p");
    return false;
});

Now let’s refresh picture1.html, and when we click on all the links, the image and caption get replaced on the same page without reloading.

The .load() method is great for swapping out content in one container element. But if you notice in our example, the content changes, but the title of the page doesn’t. If we want the title to be replaced, we need to go about it another way.

The .ajax() method

jQuery offers a powerful .ajax() method that can be used in any situation to load dynamic data into your web page.

The .ajax() method takes a set of key value pairs of attributes. The two keys you’ll set values for are probably going to be url and success.

Once the data is loaded, we can then manipulate and transverse the data with jQuery in the same way as the current page in the current window. All you do is pass the data from the success callback into the jQuery selector method as a second argument.

To take our example further we’re going to load an XML file via AJAX in the background when the page loads. We’re going to store the data in memory so we don’t have to keep doing requests every time a link is clicked. The XML file will contain only the necessary information needed for the image gallery, so we’re saving on bandwidth too.

First, lets open up pictures.xml.

<?xml version="1.0" encoding="UTF-8"?>
<pictures>
    <picture caption="Picture 1" source="../images/flower1-300.jpg" />
    <picture caption="Picture 2" source="../images/flower2-300.jpg" />
    <picture caption="Picture 3" source="../images/flower3-300.jpg" />  
    <picture caption="Picture 4" source="../images/flower4-300.jpg" />
    <picture caption="Picture 5" source="../images/flower5-300.jpg" />
</pictures>

As you can see, we have the root element pictures, and contained within it, the five pictures with their respective captions and sources. While this file is static XML - this could be dynamically created on the server-side using Ruby, PHP or ASP.

Lets remove our code from before and start fresh.

It’s a good idea to store elements you’ll be using over and over again in variables. This saves jQuery from transversing the DOM every time we want to use it. Another good idea is to put a dollar sign before jQuery-selected elements, so you always know what you’re working with.

var $pictures, $menu_links = $("#menu a"), $title = $("title"), $image = $("#container img"), $caption = $(".caption");

Next, lets use the ajax() method to load the XML file. We’ll set the url key to "pictures.xml", and set the success key to the anonymous callback function. Once the data loads, we want to store the jQuery representation of the picture tags.

...
$.ajax({
    url: "pictures.xml",
    success: function(data){
        $pictures = $("picture", data);
    }
});

jQuery allows you to transverse other HTML and XML documents by passing a second argument, which tells jQuery what context it’s selecting in. So with our XML document, data is being passed in to our callback. To load the pictures, we need to first pass in “picture” as the element, and pass in data as a second argument, for the context.

We then need to add a click listener to each link. Notice how the links within the menu div, and picture elements in the XML, are in the same order.

...
$menu_links.click(function(){
   var index = $menu_links.index(this);
   var $picture = $pictures.filter(":eq(" + index + ")");
});

Once the link is clicked, we need to inspect what index the link is within the menu, and select the appropriate picture from our $pictures variable, using that index. Now we have the appropriate $picture selected . We can now use that to populate the image caption and page title.

...
$menu_links.click(function(){
   var index = $menu_links.index(this);
   var $picture = $pictures.filter(":eq(" + index + ")");
  $caption.text($picture.attr("caption"));
  $image.attr("src", $picture.attr("source"));
  $title.text("Gallery 1 - " + $picture.attr("caption"));
  return false;
});

When we refresh the page, you’ll now see that all three of the desired elements, the image, the caption and the page title, are all updating dynamically.

XML/HTML Difficulties

Working with XML or HTML can often feel verbose when trying to get at the data you really want. It can also be confusing switching between the different documents that you’re transversing.

JSON

Many people are starting to use JSON as their data-type-of-choice. A JSON representation of your data is smaller than its XML equivalent, which reduces the bandwidth used between server and client. And since JSON is JavaScript, there’s no need for conversion before using the data.

Using XML with JavaScript requires a reformatting of the data into something JavaScript can understand and access. So using JSON results in a less verbose way of accessing data.

Another great benefit of using JSON is that since it’s native JavaScript, it’s going to have better peformance on the client-side.

So lets update our gallery to use JSON. If we open the pictures.json file, we see the same 5-picture array as we do in our XML.

[   
    {"picture": {"caption":"Picture 1", "source":"../images/flower1-300.jpg"} },
    {"picture": {"caption":"Picture 2", "source":"../images/flower2-300.jpg"} }, 
    {"picture": {"caption":"Picture 3", "source":"../images/flower3-300.jpg"} }, 
    {"picture": {"caption":"Picture 4", "source":"../images/flower4-300.jpg"} }, 
    {"picture": {"caption":"Picture 5", "source":"../images/flower5-300.jpg"} }
] 

Now, lets modify our AJAX code to support the new, smaller JSON format.

Let’s change "pictures.xml" to "pictures.json". Because the data returned is now a JSON object, we don’t need jQuery to inspect the data. So it’s simply $pictures = data. Let’s also drop the dollar sign, since this is now a purely JSON object.

var pictures, $menu_links = $("#menu a"), $title = $("title"), $image = $("#container img"), $caption = $(".caption");

$.ajax({
    url: "pictures.json",
    success: function(data){
        pictures = data;
    }
});
...

Now we can modify the functionality when we click a link. We get the linked picture’s JSON representation by accessing the object at the position index in the array of pictures. We can then access its atributes via dot-notation. So getting to the picture caption is as simple as picture.caption, and the source is simply picture.source.

...
$menu_links.click(function(){
   var index = $menu_links.index(this);
   var picture = pictures[index].picture;
  $caption.text(picture.caption);
  $image.attr("src", picture.source);
  $title.text("Gallery 1 - " + picture.caption);
  return false;
});

The code is now cleaner and easier to read. Let’s see if it works in our browser. We hit refresh and click on the links, and yes, it still works. Great.

.get() method

Another way we can simplify our code is by using the .get() convenience method. Get refers to the HTTP GET method, so if you are loading from a path that responds to the GET method, this is ideal. You don’t need to specify the key-value pairs. All you need to do is pass in the url as your first argument, and then the success callback as the second.

So, using the .get() method, our code now looks like this.

...
$.get("pictures.json", function(data){
   pictures = data;
});
...

Other arguments can be passed into this method. For further information, see the jQuery API documentation.

When we check the code in the browser, we can see we’re getting the desired functionality.

Other Convenience Methods

jQuery also offers a range of convenience methods that abstract the .ajax() method away, in the same way as the .get() method. They all take the same arguments, but they’re for different types of requests.

.post()

The .post() method, as you’d expect, is for POST requests. This may be handy when you’re submitting a form, and the server will only respond to a POST request.

.getJSON()

The .getJSON() method can be used for loading JSON via a GET request on your local domain. Or, if you provide a callback parameter in the URL, it will automatically know it’s a JSONP request for local and external data sources.

.getScript()

The .getScript() method is used if you want to include a new JavaScript file in your page that you want to be executed. Once it’s loaded, it will execute.

For more alternative usages of these methods please visit the jQuery API documentation website.

Callbacks

So let’s move on to our second example. If you open up picture1.html from the gallery2 folder in your browser, you’ll see a new section where there’s a comments form and list of comments.

When you open it up in you editor, you’ll notice a paragraph with the id "error" and another paragraph with the id "loading". These are hidden in the CSS.

...
<p id="error">
    An error has occurred Please try again later!
</p>
...
<p id="loading">
    Processing Comment...<br />
    <img src="../images/loading.gif">
</p>
...

It’s always a good idea to give users clear feedback on the progress of what’s happening in your application. For example, it’s a good idea to show a loading message or image for things that are processing in the background, or show an error message if there’s a problem.

So in our example, let’s show the "error" paragraph whenever there is a problem retrieving data via AJAX.

.ajaxSetup() Method

This is done by using the .ajaxSetup() method. The .ajaxSetup() method takes the same key-value pairs that the .ajax() method would take.

Let’s pre-select the error paragraph, and cache it in the the variable $error.

var pictures, $menu_links = $("#menu a"), $title = $("title"), $image = $("#container img"), $caption = $(".caption"),
$error = $("#error");
...

Now, let’s compose the .ajaxSetup() method, and give the error key an anonymous function to display the "error" paragraph whenever there’s a problem.

...
$.ajaxSetup({
    error:function(){
        $error.show();
    }
});
...

Let’s test this out by changing the path in the .get method to “pictures.json1”, which is an invalid file name. Now let’s refresh our browser. Great, we’re seeing our error message just as expected. Now let’s remove the 1, and refresh. Now that the file name is correct, the error message is not shown.

Let’s move on to the form. When we click submit, we want to do five things:

  1. First, we want to hide the form.
  2. Second, we want to submit the form via AJAX.
  3. Third, we want to show the loading paragraph.
  4. Fourth, we want to append the new comment to the end of the comments list.
  5. Fifth, we want to hide the loading paragraph.

As we’ve done before, let’s cache these elements that we’re going to use. So let’s assign the form to $form, the loading paragraph to $loading, and the comments container to $comments.

var pictures, $menu_links = $("#menu a"), $title = $("title"), $image = $("#container img"), $caption = $(".caption"),
$error = $("#error"), $form = $("form"), $loading = $("#loading"), $comments = $("#comments");
...

We want to bind an anonymous function to the form’s submit handler. When we submit the form, we want to hide it by calling the .hide() method on the $form object. After that, we need to setup the .ajax() method with the key value pairs. The type is "POST", URL is the form’s action attribute, and the data is the serialised contents of the form. We can get the serialised contents by using jQuery’s serialize() method on the $form object.

Before we send the request, let’s show the "loading" paragraph. We do this by specifying an anonymous function for the beforeSend key. Then, when the data is successfully returned, we’ll append that to our comments container. Note that the URL is a static HTML file - if you were doing this on a production system, you’d have the server return an HTML fragment with your newly-persisted comment.

...
$form.submit(function(){
    $form.hide();
    $.ajax({
       type: "POST",
       url: $form.attr("action"),
       data: $form.serialize(),
       beforeSend: function(){
            $loading.show();
       },
       success: function(data){
           $comments.append(data);
       }
    });
});
...

When we refresh the page now and fill in the form, we see that the "loading" paragraph gets shown, and the data gets appended to the comments container. However, we haven’t hidden the "loading" paragraph on completion.

We do this by simply creating an anonymous function for the complete key. This function gets executed after the success and error callbacks. This is exactly when we want to hide our loading paragraph.

...
$form.submit(function(){
    $form.hide();
    $.ajax({
       type: "POST",
       url: $form.attr("action"),
       data: $form.serialize(),
       beforeSend: function(){
            $loading.show();
       },
       complete: function(){
           $loading.hide();
       },
       success: function(data){
           $comments.append(data);
       }
    });
});
...

When we refresh the page and submit the comment again, we see the loading paragraph appearing and disappearing successfully. Great. It does happen very quickly since our requests are on our local machine. However, in a production environment, this will show longer, depending on the speed of the connection and the processing on the server.

But showing a loading message like this really keeps the user informed, which is always important.

What we’ve learned:

In this Using AJAX with jQuery screencast we’ve covered many topics:

  • We’ve shown how to load fragments of HTML into container elements using the .load() method.
  • We’ve shown how to transverse XML and use JSON to load data dynamically into multiple parts of a page.
  • We’ve shown how JSON is the preferable data format, because of its lightweight nature over the wire (which is great for mobile connections), its readability in the code, and its native JavaScript nature which gives it a performance edge over HTML and XML.
  • And we’ve shown how to set global and local callbacks, in order to give users useful feedback and visual hints.

We hope you’ve learned several valuable ways to use AJAX in your projects. Of course, strategies will vary from project to project, depending on constraints or requirements.

Thank you for your time and we hope you’ll have fun putting your new skills to use.

If you have any questions, feedback or suggestions please email feedback@screencasts.org.

Be sure to follow us on Twitter, subscribe to our RSS feed and newsletter to be notified about jQuery and other web development screencasts as they become available. See you next time.

← Latest Episodes

blog comments powered by Disqus