Ajax From Scratch
Here we will go through the core technical steps to implement Ajax.
Our goal will be to display parts of an XML file as an XHTML table within the current page.
We will achieve this by using Javascript to make an asynchronous call to retrieve the XML file from the server. This will be done through browser specific objects that enable server communication. These will be cast into a variable that can be handled cross browser. We can think, then, of "a XHR object". Once we have retrieved the XML file we will traverse it using the DOM to build the XHTML table. Lastly we insert the newly created table into the page.
The example code below will contain all that is needed for the demo at the start of the page. To see the code that actually does the job use your browsers' View > Source
command to look at the code in the <head>
section of this page.
The example code below is simplified. In production you will want to employ a robust, cross browser, and easy to use AJAX library. A good library is Ajax Toolbox by Matt Kruse. A list of libraries can be found at Ajax Patterns > Javascript Remoting Frameworks, a wiki by Michael Mahemoff.
Demo
Tested in IE 5.0, IE 6.0 and Firefox 1.5. Under windows.
The XML file
We start with a simple XML file.
<?xml version="1.0"?> <aircraft> <type code="B734"> <manufacturer>Boeing</manufacturer> <model>737-400</model> <seats>168</seats> <engineType>jet</engineType> <ceiling>37000</ceiling> </type> <type code="BE58"> <manufacturer>Beechcraft</manufacturer> <model>Baron 58</model> <seats>6</seats> <engineType>propeller</engineType> <ceiling>20688</ceiling> </type> ... </aircraft>
Create the XHR object
Using Javascript as our programming language we create a particular object within the DOM
that enables communication with the server.
This will be XMLHttpRequest
for gecko based browsers and others, eg Firefox, or XMLHTTP
for Microsoft Internet Explorer.
We use the cross browser technique, object detection, to determine which of these objects we want. We name whichever object as XHR. From then on we can treat it in a browser independent way.
/* Globals */ Xhr = ajaxCreateXhr(); function ajaxCreateXhr() { var xhr; try { if (window.XMLHttpRequest) { // Mozilla, Safari,... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE xhr = new ActiveXObject("Msxml2.XMLHTTP"); } } catch (e) { var errorMessage = "Your browser does not support the creation" + "of an XHR instance."; throw new Error(errorMessage); return false; } return xhr; }
The Asynchronous Call
Next we make an a asynchronous call to retrieve the
XML file.
An asynchronous call allows other code to continue executing while
the data request goes on it's journey to and from the server.
In order for the code to know when that journey has ended
we assign a function the to Xhr.onreadystatechange
function ajaxSendRequest(url) { Xhr.onreadystatechange = ajaxHandleResponse; try { Xhr.open('GET', url, true); // True for asynchronous call. Xhr.send(null); } catch (error) { var errorMessage = "There was a problem retrieving the XML data. " + "\nFirst, Try running from a web server, eg http://localhost," + "rather than file system.\n" + "XMLHttpRequest Error Message: \n" + ((Xhr.statusText == "") ? "" : "statusText " + Xhr.statusText); throw new Error(errorMessage); return false; } }
Handling the Sever Response
ajaxHandleResponse()
is called after the data request
has returned from the server. This simply passes execution
to a "success" function if no problems arise.
function ajaxHandleResponse() { var readyStateCode = { Completed:4 }; var httpStatusCode = { Ok:200 // The request has succeeded }; if (Xhr.readyState == readyStateCode.Completed) { if (Xhr.status == httpStatusCode.Ok) { ajaxOnSuccess(); } else { var errorMessage = "" errorMessage = "There was a problem with the response. \n"; errorMessage += "HTTP Request Status Code: " + Xhr.status + "\n"; errorMessage += "HTTP Request Status Text: " + Xhr.statusText; throw new Error(errorMessage); return false; } } }
Using A Successful Response
The ajaxHandleResponse()
function passes execution to ajaxOnSuccess()
. We handle
the successful response according to the specifics of our application.
In this example, somewhat typical, we use the DOM to traverse the XML now stored in the XHR
object.
We create the XHTML table as we
traverse the DOM.
Then we insert the table into our desired place in the current web page.
function ajaxOnSuccess() { var xmlDomDocument = Xhr.responseXML; // Application Specific Code Bellow var xhtmlString = ""; var memberChildren; var nodeType = new Object(); nodeType.element = 1; xhtmlString += "<table ID="Table1">"; xhtmlString += "<thead><tr>"; xhtmlString += "<td>Manufacturer<\/td>"; xhtmlString += "<td>Model<\/td>"; xhtmlString += "<td>Seats<\/td>"; xhtmlString += "<td>Engine Type<\/td>"; xhtmlString += "<td>Ceiling<\/td>"; xhtmlString += "<\/tr><\/thead>"; xhtmlString += "<tbody>"; var members = xmlDomDocument.getElementsByTagName("type"); for (var i = 0; i < members.length; i++) { xhtmlString += "<tr>"; memberChildren = members[i].childNodes; for (var j = 0; j < memberChildren.length; j++){ if (memberChildren[j].nodeType == nodeType.element) { xhtmlString += "<td>" + memberChildren[j].firstChild.nodeValue + "<\/td>"; } } xhtmlString += "<\/tr>"; } xhtmlString += "<\/tbody>"; xhtmlString += "<\/table>"; // Insert into the web page. document.getElementById("output").innerHTML = xhtmlString; }
Kick the whole thing off
Initiating the Asynchronous call:
function startAjax(){ ajaxSendRequest("aircraft.xml"); }