How to Bridge the Client-Server Gap using AJAX (Part I)
In recent years, it has become common to judge sites based on their use of
specific technologies. One of the most prominent buzzwords used to describe
new web applications is AJAX-powered. This label has been used to mean
many different things, as the term encompasses a group of related capabilities
and techniques. This is covered in a two part series. In this article by
Jonathan Chaffer and Karl Swedberg, we will learn :
- The technologies involved
- Loading data on demand
- Choosing a data format
- Passing data to the server
- Keeping an eye on the request
Technically, AJAX is an acronym standing for Asynchronous
JavaScript and XML. The technologies involved in an AJAX solution
include:
- JavaScript, to capture
interactions with the user or other browser-related events - The XMLHttpRequest object,
which allows requests to be made to the server without interrupting other
browser tasks - XML files on the server, or
often other similar data formats such as HTML or JSON - More JavaScript, to interpret the data from the server and present
it on the page
Many frameworks have sprung up to assist developers in taming it, because of
the inconsistencies in the browsers’ implementations of the
XMLHttpRequest object; jQuery is no exception.
Let us see if AJAX can truly perform miracles.
Loading data on demand
Underneath all the hype and trappings, AJAX is just a means of loading data
from the server to the web browser, or client, without a visible
page refresh. This data can take many forms, and we have many options for what
to do with it when it arrives. We’ll see this by performing the same basic task
in many ways.
We are going to build a page that displays entries from a dictionary, grouped
by the starting letter of the dictionary entry. The HTML defining the content
area of the page will look like this:
<div id="dictionary"> </div>
Yes, really! Our page will have no content to begin with. We are going to use
jQuery’s various AJAX methods to populate this <div> with
dictionary entries.
<div class="letters">
<div class="letter" id="letter-a">
<h3><a href="#">A</a></h3>
</div>
<div class="letter" id="letter-b">
<h3><a href="#">B</a></h3>
</div>
<div class="letter" id="letter-c">
<h3><a href="#">C</a></h3>
</div>
<div class="letter" id="letter-d">
<h3><a href="#">D</a></h3>
</div>
</div>
As always, a real-world implementation should use progressive enhancement to
make the page function without requiring JavaScript. Here, to simplify our
example, the links do nothing until we add behaviors to them with jQuery.
As always, a real-world
implementation should use progressive enhancement to make the page
function without requiring JavaScript. Here, to simplify our example, the links
do nothing until we add behaviors to them with jQuery.
Adding a few CSS rules, we get a page that looks like this:

Now we can focus on getting content onto the page.
Appending HTML
AJAX applications are often no more than a request for a chunk of HTML. This
technique, sometimes referred to as AHAH (Asynchronous HTTP and
HTML), is almost trivial to implement with jQuery. First we need some HTML
to insert, which we’ll place in a file called a.html alongside our main
document. This secondary HTML file begins:
<div class="entry">
<h3 class="term">ABDICATION</h3>
<div class="part">n.</div>
<div class="definition">
An act whereby a sovereign attests his sense of the high
temperature of the throne.
<div class="quote">
<div class="quote-line">Poor Isabella's Dead, whose
abdication</div>
<div class="quote-line">Set all tongues wagging in the
Spanish nation.</div>
<div class="quote-line">For that performance 'twere
unfair to scold her:</div>
<div class="quote-line">She wisely left a throne too
hot to hold her.</div>
<div class="quote-line">To History she'll be no royal
riddle —</div>
<div class="quote-line">Merely a plain parched pea that
jumped the griddle.</div>
<div class="quote-author">G.J.</div>
</div>
</div>
</div>
<div class="entry">
<h3 class="term">ABSOLUTE</h3>
<div class="part">adj.</div>
<div class="definition">
Independent, irresponsible. An absolute monarchy is one
in which the sovereign does as he pleases so long as he
pleases the assassins. Not many absolute monarchies are
left, most of them having been replaced by limited
monarchies, where the sovereign's power for evil (and for
good) is greatly curtailed, and by republics, which are
governed by chance.
</div>
</div>
The page continues with more entries in this HTML structure. Rendered on its
own, this page is quite plain:

Note that a.html is not a true HTML document; it contains no
<html>, <head>, or <body>, all of which
are normally required. We usually call such a file a snippet or
fragment; its only purpose is to be inserted into another HTML document,
which we’ll accomplish now:
$(document).ready(function() {
$('#letter-a a').click(function() {
$('#dictionary').load('a.html');
return false;
});
});
The .load() method does all our heavy lifting for us! We specify the
target location for the HTML snippet by using a normal jQuery selector, and then
pass the URL of the file to be loaded as a parameter to the method. Now, when
the first link is clicked, the file is loaded and placed inside <div
id=”dictionary”>. The browser will render the new HTML as soon as it is
inserted:

Note that the HTML is now styled, whereas before it was plain. This is due to
the CSS rules in the main document; as soon as the new HTML snippet is inserted,
the rules apply to its tags as well.
When testing this example, the dictionary definitions will probably appear
instantaneously when the button is clicked. This is a hazard of working on our
applications locally; it is hard to account for delays in transferring documents
across the network. Suppose we added an alert box to display after the
definitions are loaded:
$(document).ready(function() {
$('#letter-a a').click(function() {
$('#dictionary').load('a.html');
alert('Loaded!');
return false;
});
});
However, when this particular code is tested on a production web server, the
alert will quite possibly have come and gone before the load has completed, due
to network lag. This happens because all AJAX calls are by default
asynchronous. Otherwise, we’d have to call it SJAX, which hardly has the
same ring to it! Asynchronous loading means that once the HTTP request to
retrieve the HTML snippet is issued, script execution immediately resumes
without waiting. Sometime later, the browser receives the response from the
server and handles it. This is generally desired behavior; it is unfriendly to
lock up the whole web browser while waiting for data to be retrieved.
If actions must be delayed until the load has been completed, jQuery provides
a callback for this. An example will be provided below.
Working with JavaScript objects
Pulling in fully-formed HTML on demand is very convenient, but there are
times when we want our script to be able to do some processing of the data
before it is displayed. In this case, we need to retrieve the data in a
structure that we can traverse with JavaScript.
With jQuery’s selectors, we could traverse the HTML we get back and
manipulate it, but it must first be inserted into the document. A more native
JavaScript data format can mean even less code.
Retrieving a JavaScript object
As we have often seen, JavaScript objects are just sets of
key-value pairs, and can be defined succinctly using curly braces ({}).
JavaScript arrays, on the other hand, are defined on the fly with square
brackets ([]). Combining these two concepts, we can easily express some very
complex and rich data structures.
The term JavaScript Object Notation (JSON) was coined by
Douglas Crockford to capitalize on this simple syntax. This notation can offer a
concise alternative to the sometimes-bulky XML format:
{
"key": "value",
"key 2": [
"array",
"of",
"items"
]
}
For information on some of
the potential advantages of JSON, as well as implementations in many programming
languages, visit http://json.org/
.
We can encode our data using this format in many ways. We’ll place some
dictionary entries in a JSON file we’ll call b.json, which begins as
follows:
[
{
"term": "BACCHUS",
"part": "n.",
"definition": "A convenient deity invented by the...",
"quote": [
"Is public worship, then, a sin,",
"That for devotions paid to Bacchus",
"The lictors dare to run us in,",
"And resolutely thump and whack us?"
],
"author": "Jorace"
},
{
"term": "BACKBITE",
"part": "v.t.",
"definition": "To speak of a man as you find him when..."
},
{
"term": "BEARD",
"part": "n.",
"definition": "The hair that is commonly cut off by..."
},
To retrieve this data, we’ll use the $.getJSON() method, which fetches
the file and processes it, providing the calling code with the resulting
JavaScript object.
Global jQuery functions
To this point, all jQuery methods that we’ve used have been attached to a
jQuery object that we’ve built with the $() factory function. The
selectors have allowed us to specify a set of DOM nodes to work with, and the
methods have operated on them in some way. This $.getJSON() function,
however, is different. There is no logical DOM element to which it could apply;
the resulting object has to be provided to the script, not injected into the
page. For this reason, getJSON() is defined as a method of the global
jQuery object (a single object called jQuery or $ defined once
by the jQuery library), rather than of an individual jQuery object
instance (the objects we create with the $() function).
If JavaScript had classes like other object-oriented languages, we’d call
$.getJSON() a class method. For our purposes, we’ll refer to this
type of method as a global function; in effect, they are functions that
use the jQuery namespace so as not to conflict with other function
names.
To use this function, we pass it the file name as before:
$(document).ready(function() {
$('#letter-b a').click(function() {
$.getJSON('b.json');
return false;
});
});
This code has no apparent effect when we click the link. The function call
loads the file, but we have not told JavaScript what to do with the resulting
data. For this, we need to use a callback function.
The $.getJSON() function takes a second argument, which is a function
to be called when the load is complete. As mentioned before, AJAX calls are
asynchronous, and the callback provides a way to wait for the data to be
transmitted rather than executing code right away. The callback function also
takes an argument, which is filled with the resulting data. So, we can
write:
$(document).ready(function() {
$('#letter-b a').click(function() {
$.getJSON('b.json', function(data) {
});
return false;
});
});
Here we are using an anonymous function as our callback, as has been
common in our jQuery code for brevity. A named function could equally be
provided as the callback.
Inside this function, we can use the data variable to traverse the
data structure as necessary. We’ll need to iterate over the top-level array,
building the HTML for each item. We could do this with a standard for
loop, but instead we’ll introduce another of jQuery’s useful global functions,
$.each(). Instead of operating on a jQuery object, this function takes an
array or map as its first parameter and a callback function as its second. Each
time through the loop, the current iteration index and the current item
in the array or map are passed as two parameters to the callback function.
$(document).ready(function() {
$('#letter-b a').click(function() {
$.getJSON('b.json', function(data) {
$('#dictionary').empty();
$.each(data, function(entryIndex, entry) {
var html = '<div class="entry">';
html += '<h3 class="term">' + entry['term'] + '</h3>';
html += '<div class="part">' + entry['part'] + '</div>';
html += '<div class="definition">';
html += entry['definition'];
html += '</div>';
html += '</div>';
$('#dictionary').append(html);
});
});
return false;
});
});
Before the loop, we empty out <div id=”dictionary”> so that we
can fill it with our newly-constructed HTML. Then we use $.each() to
examine each item in turn, building an HTML structure using the contents of the
entry map. Finally, we turn this HTML into a DOM tree by appending it to the
<div>.
This approach presumes that
the data is safe for HTML consumption; it should not contain any stray <
characters, for example.
All that’s left is to handle the entries with quotations, which takes another
$.each() loop:
$(document).ready(function() {
$('#letter-b a').click(function() {
$.getJSON('b.json', function(data) {
$('#dictionary').empty();
$.each(data, function(entryIndex, entry) {
var html = '<div class="entry">';
html += '<h3 class="term">' + entry['term'] + '</h3>';
html += '<div class="part">' + entry['part'] + '</div>';
html += '<div class="definition">';
html += entry['definition'];
if (entry['quote']) {
html += '<div class="quote">';
$.each(entry['quote'], function(lineIndex, line) {
html += '<div class="quote-line">' + line + '</div>';
});
if (entry['author']) {
html += '<div class="quote-author">' + entry['author'] +
'</div>';
}
html += '</div>';
}
html += '</div>';
html += '</div>';
$('#dictionary').append(html);
});
});
return false;
});
});
With this code in place, we can click the B link and confirm our
results:

The JSON format is concise,
but not forgiving. Every bracket, brace, quote, and comma must be present and
accounted for, or the file will not load. In most browsers, we won’t even get an
error message; the script will just silently fail.
Executing a script
Occasionally we don’t want to retrieve all the JavaScript we will need when
the page is first loaded. We might not know what scripts will be necessary until
some user interaction occurs. We could introduce <script> tags on
the fly when they are needed, but a more elegant way to inject additional code
is to have jQuery load the .js file directly.
Pulling in a script is about as simple as loading an HTML fragment. In this
case, we use the global function $.getScript(), which, like its siblings,
accepts a URL locating the script file:
$(document).ready(function() {
$('#letter-c a').click(function() {
$.getScript('c.js');
return false;
});
});
Scripts fetched in this way are run in the global context of the
current page. This means they have access to all globally-defined functions and
variables, notably including jQuery itself. We can therefore mimic the JSON
example to prepare and insert HTML on the page when the script is executed, and
place this code in c.js:.
var entries = [
{
"term": "CALAMITY",
"part": "n.",
"definition": "A more than commonly plain and..."
},
{
"term": "CANNIBAL",
"part": "n.",
"definition": "A gastronome of the old school who..."
},
{
"term": "CHILDHOOD",
"part": "n.",
"definition": "The period of human life intermediate..."
},
{
"term": "CLARIONET",
"part": "n.",
"definition": "An instrument of torture operated by..."
},
{
"term": "COMFORT",
"part": "n.",
"definition": "A state of mind produced by..."
},
{
"term": "CORSAIR",
"part": "n.",
"definition": "A politician of the seas."
}
];
var html = '';
$.each(entries, function() {
html += '<div class="entry">';
html += '<h3 class="term">' + this['term'] + '</h3>';
html += '<div class="part">' + this['part'] + '</div>';
html += '<div class="definition">' + this['definition'] + '</div>';
html += '</div>';
});
$('#dictionary').html(html);
Now clicking on the C link has the expected result:

Loading an XML document
XML is part of the acronym AJAX, but we haven’t actually loaded any XML yet.
Doing so is straightforward, and mirrors the JSON technique fairly closely.
First we’ll need an XML file d.xml containing some data we wish to
display, excerpted here:
<?xml version="1.0" encoding="UTF-8"?>
<entries>
<entry term="DEFAME" part="v.t.">
<definition>
To lie about another. To tell the truth about another.
</definition>
</entry>
<entry term="DEFENCELESS" part="adj.">
<definition>
Unable to attack.
</definition>
</entry>
<entry term="DELUSION" part="n.">
<definition>
The father of a most respectable family, comprising
Enthusiasm, Affection, Self-denial, Faith, Hope,
Charity and many other goodly sons and daughters.
</definition>
<quote author="Mumfrey Mappel">
<line>All hail, Delusion! Were it not for thee</line>
<line>The world turned topsy-turvy we should see;
</line>
<line>For Vice, respectable with cleanly fancies,
</line>
<line>Would fly abandoned Virtue's gross advances.
</line>
</quote>
</entry>
<entry term="DIE" part="n.">
<definition>
The singular of "dice." We seldom hear the word,
because there is a prohibitory proverb, "Never say
die." At long intervals, however, some one says: "The
die is cast," which is not true, for it is cut. The
word is found in an immortal couplet by that eminent
poet and domestic economist, Senator Depew:
</definition>
<quote>
<line>A cube of cheese no larger than a die</line>
<line>May bait the trap to catch a nibbling mie.</line>
</quote>
</entry>
</entries>
This data could be expressed in many ways, of course, and some would more
closely mimic the structure we established for the HTML or JSON used earlier.
Here, however, we’re illustrating some of the features of XML designed to make
it more readable to humans, such as the use of attributes for term
and part rather than tags.
$(document).ready(function() {
$('#letter-d a').click(function() {
$.get('d.xml', function(data) {
});
return false;
});
});
This time it’s the $.get() function that does our work. In general,
this function simply fetches the file at the supplied URL and provides the plain
text to the callback. However, if the response is known to be XML because of its
server-supplied MIME type, the callback will be handed the XML DOM
tree.
Fortunately, as we have already seen, jQuery has substantial DOM traversing
capabilities. We can use the normal .find(), .filter() and other
traversal methods on the XML document just as we would on HTML:
$(document).ready(function() {
$('#letter-d a').click(function() {
$.get('d.xml', function(data) {
$('#dictionary').empty();
$(data).find('entry').each(function() {
var $entry = $(this);
var html = '<div class="entry">';
html += '<h3 class="term">' + $entry.attr('term')
+ '</h3>';
html += '<div class="part">' + $entry.attr('part')
+ '</div>';
html += '<div class="definition">';
html += $entry.find('definition').text();
var $quote = $entry.find('quote');
if ($quote.length) {
html += '<div class="quote">';
$quote.find('line').each(function() {
html += '<div class="quote-line">'
+ $(this).text() + '</div>';
});
if ($quote.attr('author')) {
html += '<div class="quote-author">'
+ $quote.attr('author') + '</div>';
}
html += '</div>';
}
html += '</div>';
html += '</div>';
$('#dictionary').append($(html));
});
});
return false;
});
});
This has the expected effect when the D link is clicked:

This is a new use for the DOM traversal methods we already know, shedding
some light on the flexibility of jQuery’s CSS selector support. CSS syntax is
typically used to help beautify HTML pages, and thus selectors in standard
.css files use HTML tag names such as div and body to
locate content. However, jQuery can use arbitrary XML tag names, such as
entry and definition here, just as readily as the standard HTML
ones.
The advanced selector engine inside jQuery facilitates finding parts of the
XML document in much more complicated situations, as well. For example, suppose
we wanted to limit the displayed entries to those that have quotes that in turn
have attributed authors. To do this, we can limit the entries to those with
nested <quote> elements by changing entry to
entry:has(quote). Then we can further restrict the entries to those with
author attributes on the <quote> elements by writing
entry:has(quote[author]). The line with the initial selector now
reads:
$(data).find('entry:has(quote[author])').each(function() {
This new selector expression restricts the returned entries
correspondingly:

Choosing a data format
We have looked at four formats for our external data, each of which is
handled natively by jQuery’s AJAX functions. We have also verified that all four
can handle the task at hand, loading information onto an existing page when the
user requests it and not before. How, then, do we decide which one to use in our
applications?
HTML snippets require very little work to implement. The external data
can be loaded and inserted into the page with one simple method, which does not
even require a callback function. No traversal of the data is necessary for the
straightforward task of adding the new HTML into the existing page. On the other
hand, the data is not necessarily structured in a way that makes it reusable for
other applications. The external file is tightly coupled with its intended
container.
JSON files are structured for simple reuse. They are compact, and easy
to read. The data structure must be traversed to pull out the information and
present it on the page, but this can be done with standard JavaScript
techniques. Since the files can be parsed with a single call to JavaScript’s
eval(), reading in a JSON file is extremely fast. Any use of
eval() does carry inherent risks, however. Errors in the JSON file can
cause silent failure or even side effects on the page, so the data must be
crafted carefully by a trusted party.
JavaScript files offer the ultimate in flexibility, but are not really
a data storage mechanism. Since the files are language-specific, they cannot be
used to provide the same information to disparate systems. Instead, the ability
to load a JavaScript file means that behaviors that are rarely needed can be
factored out into external files, reducing code size unless and until it is
needed.
XML documents are the kings of portability. Because XML has become the
lingua franca of the web service world, providing data in this format
makes it very likely the data can be reused elsewhere. For example, Flickr and del.icio.us, export XML
representations of their data, which has allowed many interesting mashups
of their data to arise. The XML format is somewhat bulky, though, and can be a
bit slower to parse and manipulate than other options.
With these characteristics in mind, it is typically easiest to provide
external data as HTML snippets, as long as the data is not needed in other
applications as well. In cases where the data will be reused but the other
applications can also be influenced, JSON is often a good choice due to its
performance and size. When the remote application is not known, XML provides the
greatest assurance that interoperability will be possible.
More than any other consideration, we should determine if the data is already
available. If it is, chances are it’s in one of these formats to begin with, so
our decision may be made for us.
Passing data to the server
Our examples to this point have focused on the task of retrieving
static data files from the web server. However, the AJAX technique really
comes into its own only when the server can dynamically shape the data
based on input from the browser. We’re helped along by jQuery in this task as
well; all of the methods we’ve covered so far can be modified so that data
transfer becomes a two-way street.
Since demonstrating these
techniques requires interaction with the web server, we’ll need to use
server-side code for the first time here. The examples given will use the
PHP scripting language, which is very widely used as well as freely
available. We will not cover how to set up a web server with PHP here; help on
this can be found on the websites of Apache or PHP, or
from your site’s hosting company.
Performing a GET request
To illustrate the communication between client and server, we’ll write a
script that only sends one dictionary entry to the browser on each request. The
entry chosen will depend on a parameter sent from the browser. Our script will
pull its data from an internal data structure like this:
<?php
$entries = array(
'EAVESDROP' => array(
'part' => 'v.i.',
'definition' => 'Secretly to overhear a catalogue of the
crimes and vices of another or yourself.',
'quote' => array(
'A lady with one of her ears applied',
'To an open keyhole heard, inside,',
'Two female gossips in converse free —',
'The subject engaging them was she.',
'"I think," said one, "and my husband thinks',
'That she's a prying, inquisitive minx!"',
'As soon as no more of it she could hear',
'The lady, indignant, removed her ear.',
'"I will not stay," she said, with a pout,',
'"To hear my character lied about!"',
),
'author' => 'Gopete Sherany',
),
'EDIBLE' => array(
'part' => 'adj.',
'definition' => 'Good to eat, and wholesome to digest, as
a worm to a toad, a toad to a snake, a snake to a pig,
a pig to a man, and a man to a worm.',
),
'EDUCATION' => array(
'part' => 'n.',
'definition' => 'That which discloses to the wise and
disguises from the foolish their lack of
understanding.',
),
);
?>
In a production version of this example, the data would probably be stored in
a database and loaded on demand. Since the data is a part of the script here,
the code to retrieve it is quite straightforward. We examine the data that has
been posted and craft the HTML snippet to display:
<?php
$term = strtoupper($_REQUEST['term']);
if (isset($entries[$term])) {
$entry = $entries[$term];
$html = '<div class="entry">';
$html .= '<h3 class="term">';
$html .= $term;
$html .= '</h3>';
$html .= '<div class="part">';
$html .= $entry['part'];
$html .= '</div>';
$html .= '<div class="definition">';
$html .= $entry['definition'];
if (isset($entry['quote'])) {
$html .= '<div class="quote">';
foreach ($entry['quote'] as $line) {
$html .= '<div class="quote-line">'. $line .'</div>';
}
if (isset($entry['author'])) {
$html .= '<div class="quote-author">'. $entry['author']
.'</div>';
}
$html .= '</div>';
}
$html .= '</div>';
$html .= '</div>';
print($html);
}
?>
Now requests to this script, which we’ll call e.php, will return the HTML
snippet corresponding to the term that was sent in the GET parameters.
For example, when accessing the script with e.php?term=eavesdrop, we get
back:

Once again, we note the lack of formatting we saw with earlier HTML snippets,
because CSS rules have not been applied.
Since we’re showing how data is passed to the server, we will use a different
method to request entries than the solitary buttons we’ve been relying on so
far. Instead, we’ll present a list of links for each term, and cause a click on
any of them to load the corresponding definition. The HTML we’ll add for this
looks like:
<div class="letter" id="letter-e">
<h3>E</h3>
<ul>
<li><ahref="e.php?term=Eavesdrop">Eavesdrop</a></li>
<li><ahref="e.php?term=Edible">Edible</a></li>
<li><ahref="e.php?term=Education">Education</a></li>
<li><ahref="e.php?term=Eloquence">Eloquence</a></li>
<li><ahref="e.php?term=Elysium">Elysium</a></li>
<li><ahref="e.php?term=Emancipation">Emancipation</a>
</li>
<li><ahref="e.php?term=Emotion">Emotion</a></li>
<li><ahref="e.php?term=Envelope">Envelope</a></li>
<li><ahref="e.php?term=Envy">Envy</a></li>
<li><ahref="e.php?term=Epitaph">Epitaph</a></li>
<li><ahref="e.php?term=Evangelist">Evangelist</a></li>
</ul>
</div>
Now we need to get our JavaScript code to call the PHP script with the right
parameters. We could do this with the normal .load() mechanism, appending
the query string right to the URL and fetching data with addresses like
e.php?term=eavesdrop directly.
Instead, though, we can have jQuery construct the query string based on a map
we provide to the $.get() function:
$(document).ready(function() {
$('#letter-e a').click(function() {
$.get('e.php', {'term': $(this).text()}, function(data) {
$('#dictionary').html(data);
});
return false;
});
});
Now that we have seen other AJAX interfaces that jQuery provides, the
operation of this function seems familiar. The only difference is the second
parameter, which allows us to supply a map of keys and values that become part
of the query string. In this case, the key is always term but the value
is taken from the text of each link. Now, clicking on the first link in the list
causes its definition to appear:

All the links here have addresses given, even though we are not using them in
the code. This provides an alternative method of navigating the information for
users who have JavaScript turned off or unavailable (a form of progressive
enhancement). To prevent the links from being followed normally when
clicked, the event handler has to return false.
Performing a POST request
HTTP requests using the POST method are almost identical to those using GET.
One of the most visible differences is that GET places its arguments in the
query string portion of the URL, whereas POST requests do not. However, in AJAX
calls, even this distinction is invisible to the average user. Generally, the
only reason to choose one method over the other is to conform to the norms of
the server-side code, or to provide for large amounts of transmitted data; GET
has a more stringent limit. We have coded our PHP example to cope equally well
with either method, so we can change from GET to POST simply by changing the
jQuery function we call:
$(document).ready(function() {
$('#letter-e a').click(function() {
$.post('e.php', {'term': $(this).text()}, function(data) {
$('#dictionary').html(data);
});
return false;
});
});
The arguments are the same, and the request will now be made via POST. We can
further simplify the code by using the .load() method, which uses POST by
default when it is supplied with a map of arguments:
$(document).ready(function() {
$('#letter-e a').click(function() {
$('#dictionary').load('e.php', {'term': $(this).text()});
return false;
});
});
This cut-down version functions the same way when a link is clicked:

Serializing a form
Sending data to the server often involves the user filling out forms. Rather
than relying on the normal form submission mechanism, which will load the
response in the entire browser window, we can use jQuery’s AJAX toolkit to
submit the form asynchronously and place the response inside the current
page.
To try this out, we’ll need to construct a simple form:
<div class="letter" id="letter-f">
<h3>F</h3>
<form>
<input type="text" name="term" value="" id="term" />
<input type="submit" name="search" value="search"
id="search" />
</form>
</div>
This time we’ll return a set of entries from the PHP script by searching for
the supplied search term as a substring of a dictionary term. The data structure
will be of the same format as before, but the logic will be a bit different:
foreach ($entries as $term => $entry) {
if (strpos($term, strtoupper($_REQUEST['term']))
!== FALSE) {
$html = '<div class="entry">';
$html .= '<h3 class="term">';
$html .= $term;
$html .= '</h3>';
$html .= '<div class="part">';
$html .= $entry['part'];
$html .= '</div>';
$html .= '<div class="definition">';
$html .= $entry['definition'];
if (isset($entry['quote'])) {
foreach ($entry['quote'] as $line) {
$html .= '<div class="quote-line">'. $line .'</div>';
}
if (isset($entry['author'])) {
$html .= '<div class="quote-author">'.
$entry['author'] .'</div>';
}
}
$html .= '</div>';
$html .= '</div>';
print($html);
}
}
The call to strpos() scans the word for the supplied search string.
Now we can react to a form submission and craft the proper query parameters by
traversing the DOM tree:
$(document).ready(function() {
$('#letter-f form').submit(function() {
$('#dictionary').load('f.php',
{'term': $('input[name="term"]').val()});
return false;
});
});
This code has the intended effect, but searching for input fields by name and
appending them to a map one by one is cumbersome. In particular, this approach
does not scale well as the form becomes more complex. Fortunately, jQuery offers
a shortcut for this often-used idiom. The .serialize() method acts on a
jQuery object and translates the matched DOM elements into a query string that
can be passed along with an AJAX request. We can generalize our submission
handler as follows:
$(document).ready(function() {
$('#letter-f form').submit(function() {
$.get('f.php', $(this).serialize(), function(data) {
$('#dictionary').html(data);
});
return false;
});
});
Now the same script will work to submit the form, even as the number of
fields increases. When we perform a search, the matched entries are
displayed:

Keeping an eye on the request
So far, it has been sufficient for us to make a call to an AJAX method and
patiently await the response. At times, though, it is handy to know a bit more
about the HTTP request as it progresses. If such a need arises, jQuery offers a
suite of functions that can be used to register callbacks when various
AJAX-related events occur.
The .ajaxStart() and .ajaxStop() methods are two examples of
these observer functions, and can be attached to any jQuery object. When an AJAX
call begins with no other transfer in progress, the .ajaxStart() callback
is fired. Conversely, when the last active request ends, the callback attached
with .ajaxStop() will be executed. All of the observers are global, in
that they are called when any AJAX communication occurs, regardless of what code
initiates it.
We can use these methods to provide some feedback to the user in the case of
a slow network connection. The HTML for the page can have a suitable loading
message appended:
<div id="loading"> Loading... </div>
This message is just a piece of arbitrary HTML; it could include an animated
GIF image to provide a throbber, for instance. In this case, we’ll add a few
simple styles to the CSS file, so that when the message is displayed, the page
looks like:

In keeping with the spirit of progressive enhancement, however, we
won’t put this HTML markup directly on the page. It’s only relevant for us when
JavaScript is available, so we will insert it using jQuery:
$(document).ready(function() {
$('<div id="loading">Loading...</div>')
.insertBefore('#dictionary')
});
Our CSS file will give this <div> a display: none; style
rule so that the message is initially hidden. To display it at the right time,
we just register it as an observer with .ajaxStart():
$(document).ready(function() {
$('<div id="loading">Loading...</div>')
.insertBefore('#dictionary')
.ajaxStart(function() {
$(this).show();
});
});
We can chain the hiding behavior right onto this:
$(document).ready(function() {
$('<div id="loading">Loading...</div>')
.insertBefore('#dictionary')
.ajaxStart(function() {
$(this).show();
}).ajaxStop(function() {
$(this).hide();
});
});
Voilà! We have our loading feedback.
Once again, note that these methods have no association with the particular
ways in which the AJAX communications begin. The .load() attached to the
A link and the .getJSON() attached to the B link both cause
these actions to occur.
In this case, this global behavior is desirable. If we need to get more
specific, though, we have a few options at our disposal. Some of the observer
methods, like .ajaxError(), send their callback a reference to the
XMLHttpRequest object. This can be used to differentiate one request from
another, and provide different behaviors. Other more specific handling can be
achieved by using the low-level $.ajax() function.
The most common way of interacting with the request, though, is the success
callback, which we have already covered. We have used this in several of our
examples to interpret the data coming back from the server and to populate the
page with the results. It can be used for other feedback too, of course.
Consider once again our .load() example:
$(document).ready(function() {
$('#letter-a a').click(function() {
$('#dictionary').load('a.html');
return false;
});
});
We can create a small enhancement here by making the loaded content fade into
view rather than appear suddenly. The .load() can take a callback to be
fired on completion:
$(document).ready(function() {
$('#letter-a a').click(function() {
$('#dictionary').hide().load('a.html', function() {
$(this).fadeIn();
});
return false;
});
});
First, we hide the target element, and then initiate the load. When the load
is complete, we use the callback to show the newly-populated element by fading
it in.
Summary
In the first part of the series we have learned that AJAX methods provided by
jQuery can help us to load data in several different formats from the server
without a page refresh. We can execute scripts from the server on demand, and
send data back to the server.
In the next part we’ll learn how to deal with common challenges of asynchronous loading techniques, such as
keeping handlers bound after a load has occurred and loading data from a
third-party server.
If you have read this article you may be interested to view :
- How
to Bridge the Client-Server Gap using AJAX (Part II) - How to Add Flair to your Actions with jQuery

Leave a Reply