Recent innovation has enabled several mature technologies to be used in harmony to create Rich Internet Applications (RIA), which have similar responsiveness to that of desktop applications.
These combined technologies are collectively referreed to as "AJAX" (Asynchronous Javascript And Xml), which incorporates:
It's important to recognize that AJAX is not a technology itself but simply describes a technique combining other technologies. To fully appreciate its advantages you need to first understand the relationship between the web browser and the web server.
Typically a user action in teh web browser will send an HTTP request to the web server. The server will then process the request, calling on server-side scripts and databases as required, and then send a response of HTML and CSS data back to the browser.
The time taken for the web server to process an HTTP request, and return its response to the browser, can be lengthy. An AJAX application eradicates the need to wait for web server responses by introducing an intermediary - an AJAX "engine":
The AJAX engine, written in JS, starts when the web page has loaded into the browser. Each user action that would normally generate an HTTP request to the server now takes the form of a JS call to the AJAX engine:
In order to request XML data with AJAX an XMLHttpRequest object must first be created. This provides methods to send the request to the web server and has properties that record the progress status of that request.
IE 7 introduced native HTML DOM support for the window.XMLHttpRequest object that was already supported by Mozilla-based browsers such as Firefox. Earlier versions of IE must use a window.ActiveXObject called "Microsoft.XMLHTTP" to create an XMLHttpRequest object.
Let's creat an XMLHttpRequest object to request data from the tree.xml document.
Having created an XMLHttpRequest object, further statements can be added to the sendXmlRequest function block to send the request to the server.
An XMLHttpRequest object has a method named open that defines the nature of the requst by its three arguments. The first of which defines the request type as either GET or POST. Requests that are also sending data to the server use the POST method but those wich are just retrieving data from the server can use the GET method. The second argument specifies the URL of the target XML document. The third argument defines the asynchronicity as either true or false . As the "A" in "AJAX" stands for "asynchronous" the request asynchronicity should usually be specified as true. This allows the request and respoinse process to run in the background, hidden from the user.
The request is actually sent to the server using the XMLHttpRequest object's send method. This requests one argument that can specify data to be sent to the server for POST requests, or simply a null value for GET requests.
Additionally, some browsers provide the XMLHttpRequest object with an overrideMineType method that can be called upon the ensure that the response is treated as XML data by setting its MIME type as "text/xml". This is seldom really necessary but it doesn't do any harm to employ this feature if the overrideMimeType method is available.
To add the ability to send a request to the server for data from the XML document, tree.xml
Having sent an XMLHttpRequest, with the sendXmlRequest function on the previous page, futher functions can be added to the script to process the response.
As an XMLHttpRequest proceeds, its progress is recorded in the request's readyState property as a numeric value:
When a request completes (and its readyState value become 4) the request assigns an HTTP status code to its status property. This indicates the result of the request - 404 for a missing page, 500 for a server error, and 200 when successful. Its associated statusText property contains a text descritpion of the status code. XML data is stored in teh request's responseXML property which becomes available when a successful request has been made - when its readyState value is 4 and its status code is 200.
Add a function to load the XML response data, after first tesxting that the request was successful:
// 1. Copy tree.xml to a directory accessible via HTTP.
// 2. Create xmlhttp.html in the same directory.
// 3. Create a global variable for the XMLHttpRequest object.
var xmlHttpReq;
// 4. Function to create an XMLHttpRequest.
function sendXmlRequest()
{
// 7. Add a try catch statement to provide a default message.
try
{
// 5. Test for the HTML DOM window.XMLHttpRequest object.
if (window.XMLHttpRequest)
{
xmlHttpReq = new XMLHttpRequest() ;
}
// 6. Or test for window.ActiveXObject.
else
if (window.ActiveXObject)
{
xmlHttpReq = new ActiveXObject( "Microsoft.XMLHTTP" ) }
// 9. Set the MIME type for some old Mozilla browsers.
if(xmlHttpReq.overrideMimeType)
xmlHttpReq.overrideMimeType("text/xml");
// 10. Nominate a function to call when the requrst completes.
xmlHttpReq.onreadystatechange = loadXmlData;
// 11. Define the request type, URL, and asynchronicity.
xmlHttpReq.open( "GET", "tree.xml", true );
// 12. Send the request to the web server.
xmlHttpReq.send(null);
}
catch(error)
{
document.getElementById("box").innerHTML = "XML data is unavailable";
}
}
// 13. Create a global variable to store the XML response data.
var xmlData;
// 14. Function to load XML response data.
function loadXmlData()
{
// 15. Test the readyState and status for successful request.
if ( (xmlHttpReq.readyState == 4) && (xmlHttpReq.status == 200) )
{
// 16. Assign XML data to the variable, then call the processing function.
xmlData = xmlHttpReq.responseXML;
getXmlData();
}
}
// 17. Function to process the XML response data.
function getXmlData()
{
var data = "statusText: " + xmlHttpReq.statusText;
data += "<br>status: " + xmlHttpReq.status;
data += "<br>readyState: " + xmlHttpReq.readyState;
data += "<br>Root element name: " + xmlData.documentElement.nodeName;
document.getElementById("box").innerHTML = data;
}
// 8. Call the function after the HTML document has loaded.
window.onload = sendXmlRequest;
The ability to load XML data with XMLHttpRequest offers some exciting possibilities for a new type of web experience. Traditionally websites comprise a number of different HTML documents, navigated via hyperlinks, where eadch page represents a seperate interface to the user. This "multi-page user interface" experience differs from that of desktop applications, which typically present a single interface to the user. An AJAX web application can offer the same "single-page user interface" experience by loading a single HTML document, which can display any amount of XML data in response to user actions.
The design of an AJAX web application needs to offer an easily recognizable way for the user to interact and to designate an area of the interface to display the data required. Additionally, an alternative fallback form of interaction should be offered for those users whose browsers cannot run teh AJAX application - perhaps viewing on handheld devices or with JS disabled.
In previous example the designated display area is the rectangular <div> with the id of "box". The addition of tabs above that area would offer an easily recognizable way for the user to interact with the AJAX application. In the HTML code below, each tab is created as a separate <div> element with event-handlers assigned for their click event. The arguments passed to the event-handler identify the tab and the XML data to display.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Topics with AJAX</title>
<meta http-equiv = "Content-Type" content = "text/html;charset=UTF-8" />
<link rel = "stylesheet" title = "Div Styles" type = "text/css" href = "topics.css" />
<script type="text/javascript" src = "topics.js"></script>
</head>
<body>
<!-- Container for XML data. -->
<div id = "box">
<!-- Default content. -->
<a href= "http://www.auxy.com">
<img src = "topics.gif" alt = "Click to discover more" /></a>
</div>
<!-- Tabs to load selective XML data when clicked. -->
<div id = "tab1" onclick="getXmlData(1,'systems')">Operating<br/>Systems</div>
<div id = "tab2" onclick="getXmlData(2,'office')">Office<br/>Applications</div>
<div id = "tab3" onclick="getXmlData(3,'media')">Digital<br/>Media</div>
<div id = "tab4" onclick="getXmlData(4,'web')">Web<br/>Development</div>
<div id = "tab5" onclick="getXmlData(5,'prog')">Programming</div>
<div id = "tab6" onclick="getXmlData(6,'gfx')">Graphic<br/>Applications</div>
</body>
</html>
The second argument passed to the event-handler is, in this case, a string that matches the nodeName of an element in the XML document (topics.xml) below. This extends the books.xml document, by adding many more titles and grouping the titles by topic - systems, office, media, and so on. Each <book> element has a topic parent element plus <title> and <author> child elements - although shown collapsed for brevity.
<?xml version="1.0" encoding = "UTF-8" ?>
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="topics.xsd">
<systems>
<book id="1-84078-305-2">
<title>Linux in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-294-3">
<title>Mac OS X in easy steps</title>
<author>Nick Vandome</author>
</book>
<book id="1-84078-316-8">
<title>Windows Vista in easy steps</title>
<author>Harshad Kotecha</author>
</book>
</systems>
<office>
<book id="1-84078-319-2">
<title>Word 2007 in easy steps</title>
<author>Scott Basham</author>
</book>
<book id="1-84078-317-6">
<title>Excel 2007 in easy steps</title>
<author>Michael Price</author>
</book>
<book id="1-84078-327-3">
<title>Powerpoint 2007 in easy steps</title>
<author>Andrew Edney</author>
</book>
<book id="1-84078-320-6">
<title>Access 2007 in easy steps</title>
<author>Andrew Unsworth</author>
</book>
</office>
<media>
<book id="1-84078-298-6">
<title>Digital Photography in easy steps</title>
<author>Nick Vandome</author>
</book>
<book id="1-84078-303-6">
<title>Digital Scrapbooking in easy steps</title>
<author>John Slater</author>
</book>
<book id="1-84078-331-1">
<title>Windows Vista Media Center in easy steps</title>
<author>Andrew Edney</author>
</book>
</media>
<web>
<book id="1-84078-324-9">
<title>HTML in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-301-X">
<title>CSS in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-3315-X">
<title>JavaScript in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-314-1">
<title>Web Design in easy steps</title>
<author>Richard Quick</author>
</book>
</web>
<prog>
<book id="1-84078-323-0">
<title>C Programming in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-259-5">
<title>Java in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-301-X">
<title>C++ Programming in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-296-X">
<title>SQL in easy steps</title>
<author>Mike McGrath</author>
</book>
<book id="1-84078-329-X">
<title>Visual Basic Express in easy steps</title>
<author>Mike McGrath</author>
</book>
</prog>
<gfx>
<book id="1-84078-300-1">
<title>Photoshop CS2 in easy steps</title>
<author>Robert Shufflebotham</author>
</book>
<book id="1-84078-333-8">
<title>Photoshop Elements 5 in easy steps</title>
<author>Nick Vandome</author>
</book>
<book id="1-84078-276-5">
<title>Photoshop Projects in easy steps</title>
<author>John Slater</author>
</book>
<book id="1-84078-302-8">
<title>Illustrator CS2 in easy steps</title>
<author>Robert Shufflebotham</author>
</book>
</gfx>
</catalog>
Now we build upon the previous example to develop an AJAX web application based upon the topics.xml data document and the HTML document. Remember that both documents should be located in a directory accesssible via HTTP, as before, so XMLHttpReuest can work. The schema document (topics.xsd) against which topics.xmlvalidates also resides in teh same directory.
This application will display the title, author, and ISBN (id) of all books within the topic selected by each tab.
Hot tip: Use CSS style rules to absolutely position the "box" <div> display area and each tab <div> neatly above.
The functionality for the AJAX web application will be provided by a JavaScript document named topics.js . This must be located in the same directory as the HTML document topics.html, which should contain a <script> tag pointing to the JS file.
To add functionality for this web application:
Having added functionality to the AJAX web application, its performance can now be tested in a web browser via HTTP.
When the application fist starts, data for each book in the first topic appears in teh display area as desired. Clicking on the text within any tab <div> causes data for each book in that topic to appear in the display area - instantly!
The instant response in AJAX applications is unlike the experience on traditional websites where the user is aware of a delay as the new page gets called form the web server. It happens so fast with AJAX that the user needs to be made aware that it has happened. Some AJAX web applications use animation effects to notify the user that an update is occurring while others use style changes to notify of updates.
Where the applciatino provides tabs, as in this example, the currently selected "active" tab can be boldly colored to denote the data selection. All other "inactive" tabs can be styled with more subdued colors so they are recognizable as tabs, not simply text. This provides an easily recognizable way for the user to interact with the application, in line with the stated design requirements. The application interface can be further enhanced by styling the cursor to become a pointer when over any tab to indicate to the user that it can be clicked - like a hyperlink.
Follow the steps below to style the AJAX web application so it becomes more user-friendly.
The loop number is concatenated with the word "tab" to address each tab's id - for instance, "tab" + 6 ("tab6") on the last iteration
The tab number is concatenated with the word "tab" to address that tab's id - for instance, "tab"+1 ("tab1") for the first tab
Filename: topics.js
var xmlHttpReq = null;
function sendXmlRequest()
{
try
{
if (window.XMLHttpRequest)
{
xmlHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
if(xmlHttpReq.overrideMimeType ) xmlHttpReq.overrideMimeType("text/xml");
xmlHttpReq.onreadystatechange = loadXmlData;
xmlHttpReq.open("GET", "topics.xml", true);
xmlHttpReq.send(null);
}
catch( error )
{
document.getElementById("box").innerHTML = "XML data is unavailable";
}
}
var xmlData;
function loadXmlData()
{
if ( (xmlHttpReq.readyState == 4) && (xmlHttpReq.status == 200) )
{
xmlData = xmlHttpReq.responseXML;
getXmlData(1,"systems");
}
}
function getXmlData(num,topic)
{
// Get the first specified topic element node.
var node = xmlData.getElementsByTagName(topic)[0];
// Create a list of all <book> elements for the topic.
var nodeList = node.getElementsByTagName("book");
// Initialize a variable with an empty string.
var data = "<table>";
// Loop through all <book> element nodes.
for(i=0; i < nodeList.length; i++)
{
// Append the id attribute value to the string.
data += "<tr><td>" + nodeList[i].getAttribute("id") + "</td>";
// Loop through each child node of the <book> element node.
for( j=0; j < nodeList[i].childNodes.length; j++)
{
if( nodeList[i].childNodes[j].nodeType == 1 )
{
// Append each child node's text node value to the string.
data += "<td> " + nodeList[i].childNodes[j].firstChild.nodeValue + "</td>";
}
}
data += "</tr>";
}
data += "</table>";
// Display the table data.
document.getElementById("box").innerHTML = data;
// Style the active tab.
styleTabs(num);
}
function styleTabs(num)
{
// First set all tabs default styles.
for( i = 1; i < 7; i++ )
{
with(document.getElementById("tab"+i) )
{
style.color="gray";
style.background="thistle";
style.cursor="pointer";
}
}
// Set the active tab style.
with( document.getElementById("tab"+num) )
{
style.color="white";
style.background="red";
}
}
window.onload=sendXmlRequest;
Having styled the tabs in the AJAX web application, with the steps on the previous page, its performance can once more be tested in a web browser via HTTP.
The tabs are now clearly defined and the boldly styled tab denotes which is the relevant active tag for the data currently on display.
Placing the default arrow cursor over any tab changes the cursor to the pointer style - denoting the tab can be clicked.
When a tab gets clicked that tab's click event-handler function dynamically replaces the data on display with the data appropriate for that tab.
The test confirms that the AJAX web application is now functioning as desired but, in line with design requirements, an alternative fallback form of interaction needs to be provided for those users without AJAX capability. This is easily achieved by adding a hyperlink banner, in the HTML code, as the default content for the "box" <div> element:
<a href= "http://www.auxy.com">
<img src = "topics.gif" alt = "Click to discover more" /></a>
</div>
To test this alternative put the banner image in the same directory as teh web application then turn off the browser's JS support. For instance, in IE 7 menu bar
Reload the AJAX web application to see the banner and try the link