Welcome to our free Ajax tutorial. This tutorial is based on Webucator's Ajax Training course.
jQuery offers a powerful yet easy-to-use set of tools to manipulate HTML pages, extending what one can do with core JavaScript. In particular, jQuery's Ajax methods allow us to write and maintain fewer lines of code, but to easily create complex functionality.
Lesson Goals
The self-proclaimed "write less, do more" JavaScript library is arguably the preferred choice for front-end developers nowadays, offering simplified yet powerful syntax, a consistent experience across a wide range of browsers, and a set of tools which fill in the gaps lacking from core JavaScript. As the jQuery website states:
jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.
As its name suggests, jQuery's core functionality is a query. We select (query) elements on a page - for example all <h2>
s, or, the third list item in a specific unordered list - and gather information about the elements or modify the elements in some manner.
To use jQuery, we first load, via a <script>
tag, the jQuery library. We can do this in one of two ways: either by downloading jQuery and hosting it locally, or by linking to a CDN-hosted version of the library. (A CDN, or content delivery network, is typically a large distributed network of servers that host a resource available for sharing. Both Google and jQuery host publicly-available copies of jQuery that you are welcome to link to from your pages.) In this course, we will use jQuery as a locally-hosted file; you'll find it among the demos and exercises in your class files, in the relevant directories.
After linking to the library, we can use jQuery code. jQuery is JavaScript, but offers a simplified - and more consistent, across various browsers - syntax. The key element of the syntax is the "$":
$('div.news').hide()
We specify a set of DOM (Document Object Model) elements - in the example above, all <div> tags of class "news" - and hide them. Of course, this is a simple example; we might have added content to those <div> tags, added a listener to them to check for user clicks, etc.
Usually, the starting point for our jQuery code is the ready method: we tell jQuery to execute our specified code only after the page's DOM has been loaded (so it's "ready"). The HTML elements on the page are fully loaded at this point, so we can manipulate any tag-based content. Because jQuery does not need to wait on external scripts, images, or other elements to load, this speeds up the page.
Let's look at a simple example:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Simple jQuery Example</title> <link href="styles.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#btn').click(function() { var numListItems = $('li').length; $('#Content').html('<p>There are ' + numListItems + ' list item(s) on this page</p>'); return false; }); }); </script> </head> <body> <button id="btn">Go</button> <ul> <li>item 1</li> <li>item 2</li> <li>item 3</li> <li>item 4</li> </ul> <div id="Content"></div> </body> </html>
We use the jQuery ready
method to run our code as soon as the DOM loads. We add a click handler for the button so that any time the button is clicked, the following occurs:
length
of the query $('li')
, which returns all of the <li>
s on the page) and assign this value to the variable numListItems
.<div>
with id Content
to display the length.jQuery provides Ajax support that abstracts away painful browser
differences. It offers both a full-featured $.ajax()
method,
and simple convenience methods such as $.get()
, $.getScript()
, $.getJSON()
,
$.post()
, and $.fn.load()
.
Most jQuery applications don't in fact use XML; instead, they transport data as plain HTML or JSON (JavaScript Object Notation).
In general, Ajax does not work across domains. Exceptions are services that provide JSONP (JSON with Padding) support, which allow limited cross-domain functionality.
jQuery generally requires some instruction as to the type of data you expect to get back from an Ajax request; in some cases the data type is specified by the method name, and in other cases it is provided as part of a configuration object. There are several options:
Note: As of jQuery 1.4, if the JSON data sent by your server isn't properly formatted, the request may fail silently. See http://json.org for details on properly formatting JSON, but as a general rule, use built-in language methods for generating JSON on the server to avoid syntax issues.
It is recommended to use the JSON format in most cases, as it provides the most flexibility. It is especially useful when your server environment is PHP, since JSON is also native to that language.
JSON:
person = {"age" : 33, "name" : "Joshua"}
XML:
<person> <age>33</age> <name>Joshua</name> </person>
The asynchronicity of Ajax catches many new jQuery users off guard. Because Ajax calls are asynchronous by default, the response is not immediately available. Responses can only be handled using a callback. So, for example, the following code will not work:
var response; $.get('foo.php', function(r) { response = r; }); console.log(response); // undefined!
Instead, we need to pass a callback function to our request; this callback will run when the request succeeds, at which point we can access the data that it returned, if any.
$.get('foo.php', function(response) { console.log(response); });
In general, Ajax requests are limited to the same protocol (http or https), the same port, and the same domain as the page making the request. This limitation does not apply to scripts that are loaded via jQuery's Ajax methods.
The other exception is requests targeted at a JSONP service on another domain. In the case of JSONP, the provider of the service has agreed to respond to your request with a script that can be loaded into the page using a <script> tag, thus avoiding the same-origin limitation; that script will include the data you requested, wrapped in a callback function you provide.
Modern browsers have for several years now shipped with built-in developer tools - tools invaluable for those of us building, testing, and maintaining Ajax-based code. Right-click on any part of a page in Chrome, Firefox, Safari, or Internet Explorer and choose "Inspect Element" to access the Developer Tools; on Safari, check "Show Develop menu in menu bar" in the "Advanced" preferences to enable this feature. The "Network" tab (known as "Timelines" in Safari) gives us a clear view of requests our browser sends and the response we receive, in real time. If something isn't going as expected with an Ajax request, this is the first place to look to track down what's wrong.
While jQuery does offer many Ajax-related convenience methods, the core $.ajax
method is at the heart of all of them, and understanding it is imperative. We'll review it first, and then touch briefly on the convenience methods.
The $.ajax
method offers
features that the convenience methods do not. Once you have gained some experience
with Ajax in jQuery, it is easiest to just use this one method.
jQuery's core $.ajax
method is a powerful and straightforward way of creating Ajax requests. It takes a configuration object that contains all the instructions jQuery requires to complete the request. The $.ajax
method
is particularly valuable because it offers the ability to specify both success
and failure callbacks. Also, its ability to take a configuration object that
can be defined separately makes it easier to write reusable code.
$.ajax(options) $.ajax(url, options)
There are many, many options for the $.ajax
method, which is
part of its power. For a complete list of options, visit http://api.jquery.com/jQuery.ajax/.
Note that the url can either be provided as a separate parameter or as part of the options object.
Here are some of the more commonly used options:
{ foo:'bar',baz:'bim' }
, or a query string, such
as foo=bar&baz=bim
.The url option is the only required property of the $.ajax
configuration
object; all other properties are optional.
$.ajax({ // the URL for the request url : 'post.php', // the data to send // (will be converted to a query string) data : { id : 123 }, // whether this is a POST or GET request type : 'GET', // the type of data we expect back dataType : 'json', // code to run if the request succeeds; // the response is passed to the function success : function(json) { $('<h1/>').text(json.title).appendTo('body'); $('<div class="content"/>') .html(json.html).appendTo('body'); }, // code to run if the request fails; // the raw request and status codes are // passed to the function error : function(xhr, status) { alert('Sorry, there was a problem!'); }, // code to run regardless of success or failure complete : function(xhr, status) { alert('The request is complete!'); } });
Note: A note about the dataType setting: if the server sends back data that is in a different format than you specify, your code may fail, and the reason will not always be clear, because the HTTP response code will not show an error. When working with Ajax requests, make sure your server is sending back the data type you're asking for, and verify that the Content-Type header is accurate for the data type. For example, for JSON data, the content type should be application/json.
Let's look at an example: we'll use jQuery to build a page we looked at previously:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>jQuery ajax - XML</title> <link href="styles.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#btn').click(function() { $.ajax({ url: "Demo", data: { FirstName: "Nat", LastName: "Dunn" }, dataType: "xml" }).done(function(xml) { var h1 = $(xml).find("h1"); $("#Content").html(h1); }); return false; }); }); </script> </head> <body> <button id="btn">Start</button> <div id="Content"></div> </body> </html>
We use jQuery's ready
method to add a listener on the button; when clicked, we invoke the jQuery ajax
method.
We use three parameters in our call to $.ajax
url: "Demo"
specifies that the Ajax request is sent to /Demo, a response route we've setup in our Node.js server; since we don't state otherwise, $.ajax
uses the default GET method.data: { FirstName: "Nat", LastName: "Dunn" }
sets the parameters included with the request; in this case, we are requesting the URL http://localhost:8080/Demo?FirstName=Nat&LastName=Dunn; that is, we include two GET parameters, FirstName
and LastName
.dataType: "xml"
parameter tells jQuery that we are expecting XML as the mime type from the response.The done
callback allows us to handle the response, if any, that we get back from the remote resource. As /Demo responds with a single <h1>
tag (<h1>Hello Nat Dunn</h1>
), we use jQuery's find
method to get the contents of the <h1>
tag - that is, "Hello Nat Dunn" - and assign the value to a local variable h1
. Lastly, we set the <div>
with id Content
to that value, using jQuery's html
method.
Let's look at another example, where we process a JSON (instead of, as in the last example, XML) response:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>jQuery ajax - JSON</title> <link href="styles.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#btn').click(function() { $.ajax({ url: "DemoJSON", data: { FirstName: "Nat", LastName: "Dunn" }, dataType: "json" }).done(function(data) { $("#Content").html(''); $.each(data, function(index, element) { $('#Content').append('<p>' + element.greeting + ', ' + element.name + '!</p>'); }); }); return false; }); }); </script> </head> <body> <button id="btn">Start</button> <div id="Content"></div> </body> </html>
Open http://localhost:8080/UsingXMLHttpRequest-Ajax-JSON.html in your browser to view the demo.
We again use jQuery's ready
method to add a listener on the button; when clicked, we invoke the jQuery ajax
method.
The key difference between this example and the last one is that this ajax call is expecting to receive a JSON response. If we examine the Node.js response route /DemoJSON?FirstName=Nat&LastName=Dunn, we see that the returned data is
[{"greeting":"hello","name":"Nat Dunn"}, {"greeting":"hola","name":"Nat Dunn"}, {"greeting":"bon jour","name":"Nat Dunn"}, {"greeting":"hallo","name":"Nat Dunn"}]
The JSON returned is an array with four elements, where each element is an object with a greeting
field ("hello" in various languages) and a name
field (the full name corresponding to the first and last names passed as GET parameters.
In UsingXMLHttpRequest-Ajax-JSON.html, we process the JSON response using jQuery's $.each
method. We first set the html of #Contents
<div>
to '', so that subsequent clicks of the button 'wipe clean' any existing content. We then iterate over the four-element JSON array and, for each element, we append a paragraph to the #Contents
<div>
with the greeting and name.
If you don't need the extensive configurability of $.ajax
, and you don't care about handling errors, the Ajax convenience functions provided by jQuery can be useful, terse ways to accomplish Ajax requests. These methods are just "wrappers" around the core $.ajax method, and simply pre-set some of the options on the $.ajax method.
The convenience methods provided by jQuery are:
$.get
- Perform a GET request to the provided URL.$.post
- Perform a POST request to the provided URL.$.getScript
- Add a script to the page.$.getJSON
- Perform a GET request, and expect JSON to be returned.In each case, the methods take the following arguments, in order:
// get plain text or html $.get('/users.php', { userId : 1234 }, function(resp) { console.log(resp); }); // add a script to the page, then run a function defined in it $.getScript('/js/myScript.js', function() { functionFromMyScript(); }); // get JSON-formatted data from the server // resp will be a single object parsed from the incoming JSON $.getJSON('/details.php', function(resp) { $.each(resp, function(k, v) { console.log(k + ' : ' + v); }); });
The $.fn.load
method is unique among jQuery's Ajax methods in
that it is called on a selection. The $.fn.load
method fetches
HTML from a URL, and uses the returned HTML to populate the selected element(s).
In addition to providing a URL to the method, you can optionally provide a
selector as part of the URL parameter; jQuery will fetch only the matching
content from the returned HTML.
$('#newContent').load('/foo.html');
$('#newContent').load('/foo.html #myDiv h1:first', function(html) { alert('Content updated!'); });
Let's look at another example, this time using jQuery's get method:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>jQuery get</title> <link href="styles.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#btn').click(function() { $.get("Demo", { FirstName: "Some", LastName: "Othername" }, function(data) { var h1 = $(data).find("h1"); $("#Content").html(h1); }, "xml" ); return false; }); }); </script> </head> <body> <button id="btn">Start</button> <div id="Content"></div> </body> </html>
This example is similar to jQuery/Demos/UsingXMLHttpRequest-Ajax.html that we reviewed previously; this time, we'll use jQuery's convenience get
method instead of the ajax
method. We again use jQuery's ready
method to add a listener on the button; when clicked, we invokeget
.
The first parameter in our call to $.get
, url: "Demo"
, specifies the remote resource we wish to connect to: http:localhost:8080/Demo. Since this is the get
method we are, of course, sending a GET
request.
The second parameter passes data to the remote resource - in our case, we pass two GET
parameters, so that the full URL is http://localhost:8080/Demo?FirstName=Some&LastName=Othername.
The third parameter is a callback function: as with the previous example, we process the returned XML, finding the contents of the <h1>
node and setting div#Contents
with its value.
The final parameter, xml
, specifies that we expect to receive an XML-formatted response.
Let's have you try out some of the concepts we've reviewed thus far with an exercise, where you can put jQuery to work.
In this exercise, you will use jQuery's ajax method to retrieve a JSON-formatted list of customers from our Northwind database, iterating over the result set to build a table from the returned data. Your page will also send along parameters to ask for the list sorted by a given field and, optionally, filtered by customer names that match a given string.
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>jQuery Exercise</title> <link href="styles.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#btn').click(function() { $.ajax({ url: "CustomerList", data: { SortOrder: $('#SortOrder').val(), CompanyNameLike: $('#CompanyNameLike').val() }, dataType: "json" }).done(function(data) { $('#Content').html('<table><thead><tr><th>Company Name</th><th>Contact Name</th><th>City</th><th>Country</th></tr></table>'); $.each(data, function(index, element) { $('#Content table').append('<tr><td>' + element.CompanyName + '</td><td>' + element.ContactName + '</td><td>' + element.City + '</td><td>' + element.Country + '</td></tr>'); }); }); return false; }); }); </script> </head> <body> <label for="CompanyNameLike">Company Name Like:</label> <br><input type="text" id="CompanyNameLike" placeholder="company name like"> <br><br> <label for="SortOrder">Sort Order:</label> <br><select id="SortOrder"> <option value="CompanyName">Company Name</option> <option value="ContactName">Contact Name</option> <option value="City">City</option> <option value="Country">Country</option> </select> <br><br> <button id="btn">Go</button> <hr> <div id="Content"></div> </body> </html>