References Used
- Javascript in 24 Hours by Michael Moncur. Sams Publishing, 2007.
AJAX Essentials
- AJAX = Asynchronous JavaScript and XML
- AJax allows Javascript to communicate asynchronously with a server and
to update a web page without having to reload it. Traditional Javascript
applications work as follows:
- The Javascript application posts a form to the web server
- The web server calculates the results and creates a completely
new web page from scratch. Even if the web page differs only slightly
from the original web page, the entire web page must be re-created.
- The web server sends the new page back to the browser. Any
pre-existing Javascript state is lost because the state is lost
as soon as the original page is sent to the server.
The roundtrip that is involved with this process can make the server
appear sluggish. It can also be tedious for the server to have to try
to remember all the form data that was entered by the user. In fact you
have probably noticed that many web sites simply forget the data that
you entered and make you re-enter it, something I find incredibly annoying.
With Ajax Javascript is able to send a request to the server without
submitting the entire form. The user is able to continue working with
the form while the server processes the result. When the server is done
it sends the result back to Javascript and Javascript can appropriately
update the form, without having to re-load the entire page. Because the
requests are asynchronous, Javascript can have multiple requests outstanding
at any given time.
- Sample Ajax Applications
- Email: An email handler can be written with a client side in Javascript
and a server side written in PhP. The Javascript side can handle the
syntactic, form-based aspects of displaying email messages in a list.
It can incrementally remove mail items from the list, add them to
the list in response to queries to the server, display email messages,
etc. Each request--delete, fetch new mail, display mail message--can
be handled with requests to the server followed by updating the
email form presented to the user.
- Incremental search: An increasingly popular feature on web-sites
is incremental search, whereby search results are refined with each
keypress by a user. On each keypress a request is sent to the server
and the server refines the search results based on the text string
entered thus far by the user. The server sends back the results to
Javascript which then updates the form with the refined set.
- Polling: Many web-sites, such as American Idol or news sites, allow
users to respond to poll questions without having to reload the
entire page. This is done by sending a request to the server to update
the vote tallies when the user presses an appropriate radio button.
- Stock quotes: Financial web-sites continuously update stock quotes
by using Ajax requests to query a server-side database for price
information and then updating the information on the client-side.
- Steps in using Ajax
- Script makes a request to the server--user can still operate
browser, such as typing text into a text field or clicking
a button
- Server-side script processes request and puts information into
one of a variety of formats, such as a JSON object, an
XML object or a text string
- JSON object/XML object/text string gets sent back to Javascript and a notification
event is triggered
- Javascript function that handles the notification event
processes the return result, which can be in one of three forms:
- plain text: you have to do your own parsing.
- XML object: you can use DOM manipulation functions
to access the data and display the result
- JSON object: as long as you have indicated to the browser that
the return type will be a JSON object, you can acess the data as
though it is a javascript object using key/value pairs.
- The major browsers all now share the same AJAX interface. Early versions
of the browsers did not but they have converged over the years.
Operations with Each Ajax Step
- Request to the server: A request to the server involves three steps:
1) getting a new XMLHttpRequest object, 2) opening the connection to
the server, and 3) sending the request to the server. The following code
accomplishes these tasks:
- Getting the new object: getting the new object requires that you
check to see whether or not you are dealing with IE5/6 or a more
recent browser
var ajaxreq = new XMLHttpRequest();
- Opening the connection: You open the connection by specifying the
type of submitting method--GET or POST--and the URL of the script
or file to be accessed on the server side:
ajaxreq.open("GET", "search.php?query=John&type=image");
If you specify the GET method, then the parameters are specified as
part of the URL string. If a parameter has special characters, such
as a '?' or a '&', then you can use javascript's encodeURIComponent
function to encode the string for safe sending. For example:
var title = "Brad's Dilemma-To Be Or Not To Be?";
var queryString = "title=" + encodeURIComponent(title.value);
ajaxreq.open("GET", "search.php?" + queryString);
Alternatively one might want a client or server-side file, in which
case you specify the file name.
An XML file will be read and
transformed to a DOM object:
ajaxreq.open("GET", "quotes.xml"); // client-side request
// server-side request
ajaxreq.open("GET", "http://web.eecs.utk.edu/~bvanderz/quotes.xml");
- Sending the request: If you specify the POST method for submitting
data, then the send method should be given a string
representing the parameters (again use encodeURIComponent if your
string has special characters). Before calling send, you will also need
to call a method called setRequestHeader as shown below.
If the GET method is specified, then
the parameter string was specified as part of the URL in the open
method. In this case you pass null to send:
ajaxreq.open("GET", "search.php?query=John&type=image");
ajaxreq.send(null);
ajaxreq.open("GET", "foo.xml"); // opening xml file so no params needed
ajaxreq.send(null);
ajaxreq.open("POST", "search.php"); // using POST so must pass param string
ajaxreq.setRequestHeader("Content-type","application/x-www-form-urlencoded");
ajaxreq.send("query=John&type=image");
- Handling the server response: When the server responds it triggers
a number of events with which you can associate a callback function.
The zybook for this course does a nice job of describing the events. Generally
the one you care about is the load event, which gets triggered
when the server finishes executing its script and successfully returns a
response. Your response handler (i.e., your callback function) will want
to do several things:
Changing HTML Content on the Client Side
Frequently an ajax response will need to change the content of html elements.
Javascript provides a way to do this by representing each html page as a
tree encapsulated in an HTML DOM object.
The only real difference is that the HTML DOM provides a few additional
convenience methods not offered by the XML DOM that are made possible by
domain-specific knowledge about HTML. For example, HTML supports ID and NAME
tags, and so the HTML DOM provides convenience methods named
getElementByID and getElementsByName.
Thus to modify an html element, one should first retrieve
the appropriate element using an HTML DOM
query command.
To retrieve the element, you should use getElementById
if the html element is identified with an id attribute and
getElementsByName if the html element is identified with a name
attribute. You can then modify the element's value by
modifying its innerHTML property.
Thus one might write:
document.getElementById('ibm').innerHTML = 98.46; // element uses id
document.getElementByName('ibm').innerHTML = 98.46; // element uses name
A more standard DOM-oriented way to perform the element change would be to
traverse the DOM tree.
The html content is in the first node of a text element and can be
accessed via the nodeValue property:
document.getElementById(ibm').firstChild.nodeValue = 98.46
Note that if the document were an XML document rather than an html document,
you would have to use the second approach, because the innerHTML
property would not be defined for nodes in an XML document. Also note that
unlike the XML DOM, you can directly modify the nodeValue rather than having
to replace the element.
Returning JSON Objects From the Server
If you are using PHP, you can encode your output as a JSON string using
json_encode. For example:
header("Content-Type: application/json; charset=UTF-8");
$jsonArray = array('insertionSuccess' => $successFlag,
'errorMessage' => $errorMessage);
echo json_encode($jsonArray);
The header function produces a statement in the string that identifies it
as a json string. The header function should be called exactly once, before
any json strings are emitted.
On the client side, your callback function might look like:
function responseHandler() {
var result = JSON.parse(this.responseText);
if (this.textstatus == "success" && result['insertionSuccess']) {
... process result ...
}
else {
alert("failed to update section\nerror message: " + result['errorMessage']);
}
}
If you need to return multiple tuples from an SQL query, then you will need to
use sub-arrays for each tuple since you can only return one JSON object, which is
constructed from the top-level array. For example:
$result = mysqli_query("SELECT name, major, gpa FROM student");
$jsonArray = array();
while($row = mysqli_fetch_array($result)) {
array_push($jsonArray[$i],array("name" => $row['name'],
"major" => $row['major'],
"gpa" => $row['gpa']));
}
echo json_encode($jsonArray);
Returning XML Documents from the Server
These days it is typically
easier to return information from the server side using
JSON. However, if you are dealing with legacy code, or if you already
have a document encoded in XML, or if you are manipulating a document
on the server-side, then your server side code may return
an XML document instead of a JSON object. This section describes how
you deal with XML documents on the server-side.
There are several issues you need to be aware of in order to make your server-side
script work in the way you anticipate:
- If you want to read an XML document then its file permission must be
set to be world readable. If you also want to be able to update the
XML document, then the file permission must be set to be both world
readable and writeable.
- You should use the DOM parser to modify the contents of an XML file. You
will need to use the createElement and replaceElement
commands to do so.
While you should be able to modify text content using the simpleXML parser,
it does not seem to work correctly in practice.
- Once you have modified your XML content, you will want to save it.
Unlike the simpleXML parser, the DOM parser does not provide a command
that both converts the XML document to a text string and writes it to
a file. Instead it only provides a command to convert the XML document
to a text string. You will need to either use fopen/fputs/fclose or the
simpler file_put_contents function to actually
save the document. For example:
$xmlDoc->formatOutput = true;
file_put_contents("quotes.xml", $xmlDoc->saveXML());
- If you want your PHP script's output to be treated as an XML document by
the client-side brower,
then you need to write out a header that tells the browser that the
document is an XML document. You can write out an appropriate header
using PHP's header command:
header('Content-Type: text/xml; charset=utf-8');
The important information in this header is the "text/xml" content-type,
which tells the browser to treat this document as an XML document.
If you fail to have your PHP script write out this header information, then
the ajax request object on the client-side will have its responseText
field set, but its responseXML field will be set to null.
- In addition to saving an XML document to a file, you may want to write
out the XML document to the client. If you want to send the
XML document to the client, use the document's saveXML command to
generate a text string and then
make sure you use PHP's echo or print commands to print the string returned
by the saveXML command. If you do not do so, then the string will not
be included in the XML document returned to the client. For example,
write this code:
echo $xmlDoc->saveXML();
instead of this code:
// missing echo command means that the text string returned by saveXML
// will not be inserted into the XML document returned to the client
$xmlDoc->saveXML();
Examples
- Interactive Quiz: This
interactive quiz allows you to answer a set of multiple choice questions about
Javascript and then displays your score at the end of the quiz. You can view the
page source to see what the page looks like. The support files are:
- quiz.js
- question.php
- questions.sql
If you want to see how this quiz works in the browser, then perform the following tasks:
- copy the contents of /home/bvanderz/webhome/javascript/{ajaxquiz.html, quiz.js, question.php, questions.sql} to a subdirectory in your webhome directory. Make sure that the permissions allow the world to read/execute the subdirectory, to read the php, sql, and html files, and to read/execute the javascript files.
- Use questions.sql to create the Questions relation in your database
- Change the $username, $password, and $dbname variables to your username, database password, and database name.
- Go to ajaxquiz.html and press the "Start Quiz" button. When you answer a question, press the "Submit" button. If you want to start over, press the "Start Quiz" button again.
In class we will do a more complicated example that involves being able to
vote for your favorite color and see the counts for each color be updated
in real-time. To do this we will actually have to write both client-side and
server-side scripts.