Introduction to AJAX

AJAX = Asynchronous JavaScript and XML

A hot, current buzz word is "Web 2.0". This term may mean a number of things, but it signals a technical evolution from static HTML pages to those that are responsive to user actions...particularly when this means updating only portions of the web page and not the whole web page. It is simply a more economical use of time and server load to update portions of web pages than whole pages. Hence the shift to the AJAX paradigm = Asynchronous JavaScript and XML [ XML = Extensible Markup Language ].

"Asynchronous" = your web page talks to its server and then waits for the server's response (i.e., the server might be busy doing something else). When the server responds, the web page patches in the new content and thus updates only a portion of the web page. Note that your reader might be reading the text on your web page, admiring the graphics on your web page, etc., etc., and is not aware of all this activity in the background.

"JavaScript" = JavaScript handles all the addressing the server, waiting for the server, and then inserting new content into the web page. This implies that the fundamental technologies of AJAX have all been around for some time, but just now are being used in combination to produce AJAX effects.

"XML" = this is a standard information structure that is used for sharing information.



HTTP - Hypertext Transfer Protocol

Http is a communications protocol used by computers to send files back and forth. It is basicly a request/response protocol where POST or GET are popular request methods.

XMLHttpRequest

JavaScript uses the XMLHttpRequest object to do the work of sending requests for files to a server and receiving files back from a server. Hence one will come across JavaScript code such as:

var myHttpObject = new XMLHttpRequest();
// Create a new XMLHttpRequest object
myHttpObject.open("GET", "myFile.txt", true);
// A request to the server to "open" the file "myFile" 
      in the GET fashion where asynchronous mode is "true"

You've probably found yourself in asynchronous conversations with your significant other lots of times. It means that you say something and wait for a response. Eventually, you get a response. That's asynchronous. If your significant other responds IMMEDIATELY then you're lucky enough to be in a synchronous relationship. :-)

Your little JavaScript finds itself in an asynchronous relationship with its web server. The server might be busy at the moment of the request, so your program has to wait for something to happen. This is expressed in code as

  {
      var myHttpObject = new XMLHttpRequest();
      myHttpObject.open("GET", "myFile.txt", true);
      myHttpObject.onreadystatechange = handleResponse;
      //  Fires when the server eventually responds
  }
  function handleResponse()
  {
   ... do something when the server responds
  }
  

JavaScript security

For security reasons, an XMLHttpRequest can only be made back to the original server ("the same domain") and not to a third party server. This means that we will locate our web page and the files that it requests via XMLHttpRequest in the same subdirectory on the same server.

Looking ahead to Greasemonkey

Greasemonkey is a Firefox extension that will permit us to make XMLHttpRequests to many different domains. The implication of this ability is that you can mash together many different web sources in a single webpage.



Our first AJAX example

On my web server, in the same subdirectory where this web pages lives, I created a text file named "first.txt" that contains just the following:

  This little file lives on a server. 
   

Here is a JavaScript function that is embedded in this page that fires when you press the button "First AJAX"



   <script type="text/javascript">
   
   function doFirstAJAX()
   {   
    //  Declare our XMLHttpRequest Object
    var myHttp = false;
    
    //  Deal with cross browser issues in creating an XMLHttpRequest object

    if(navigator.appName == "Microsoft Internet Explorer")
    {
      myHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else
    {
      myHttp = new XMLHttpRequest();
    }
    
    //  Request the file 'first.txt'    
    myHttp.open("GET", "first.txt", true);
    
    //  When the server responds, give the response to the function 'handleResponse'

    myHttp.onreadystatechange=handleResponse;
    
    //  Send the response
    myHttp.send(null);
    
    function handleResponse()
    {
    
    //  When the response has been completely received
      if(myHttp.readyState == 4)
      {
        //  Show the response in an alert box       
        alert(myHttp.responseText);
      }
    }
  }
   </script>
   
   

Your turn!

Create a web page called "myFirstAJAX.htm". FTP it up to your web server, which would probably be your student account on the Dante machine.

Use Notepad to create a text file called "first.txt" with a sentence declaring your favorite flavor of ice cream. FTP it up to the same subdirectory as the web page "myFirstAJAX.htm".

Edit your myFirstAJAX.htm web page by adding a button:


<input type="button" value="First AJAX" onclick="doFirstAJAX()"></input>
   

and a JavaScript function:

<script type="text/javascript">
    
    var myHttp;
    
	function doFirstAJAX()
	{
		myHttp = false;
		
		if(navigator.appName == "Microsoft Internet Explorer")
		{
		  myHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
		  myHttp = new XMLHttpRequest();
		}
		
		myHttp.open("GET", "first.txt", true);
		myHttp.onreadystatechange=handleResponse;
		myHttp.send(null);
       }
	
	
    function handleResponse()
    {
		  if(myHttp.readyState == 4)
		  {
			alert(myHttp.responseText);
		  }
    }
</script>
   

XML - Extensible Markup Language

You probably have heard a lot about XML - a file format specifically designed for sharing across the Internet. It is composed of balanced, open/closed tags in a simple text file. The only fancy flourish about an XML file is that it has a processing instruction at the top declaring that it is XML. Here is an example.


<?xml version="1.0" encoding="UTF-8" ?> 
<person>
<name>Terry Brooks</name>
<name>Jane Brooks</name>
</person>
 

AJAX when the delivery is structured as XML

The delivery from the server in our first example above was structured rather simply as simple text. Things get more interesting when the delivery is structured as XML.

The XMLHttpRequest code doesn't change that much...just target an XML file and indicate that the response is XML.

// Note that we're calling for an XML file

http.open("GET", "myXMLFile.xml", true);

http.onreadystatechange=function() {

if(http.readyState == 4) {
   // The response text to our XMLHttpRequest object is XML
   var resp = http.responseXML;


What is interesting to witness is how different web browser represent the downloaded XML document. Here is the document again. Note the number of "name" nodes.

<?xml version="1.0" encoding="UTF-8" ?> 

<person>
<name>Terry Brooks</name>
<name>Jane Brooks</name>

</person>
 

FIREFOX




Notice how FireFox fetches the XML file and then gives us the nodes as "text node", "Name node", "text node", "Name node", etc. What FireFox is doing is representing end-of-lines as text nodes. What this means is that if we want to fetch information from an XML document -- and the browser is Firefox -- we'll have to account for the text nodes.

Yikes!


INTERNET EXPLORER




On the other hand, Internet Explorer ignores end-of-lines and gives us just the name nodes.

Aren't cross browser issues exciting?

Yikes!

Unpacking the XML nodes

The demonstration above tells us that we'll have to use different mappings into our XML delivery depending on the browser. But note that we've already had to deal with cross browser issues in creating our XMLHttpRequest object.

"person" is the root node. In Firefox the count of child nodes would be:

So if the browser is Firefox, then nodes 1 and 3 are the good ones.

If the browser is Internet Explorer the count of the child nodes would be:

Our second AJAX example


Here is a cross-browser example of AJAX with an XML delivery. If you browser is IE, then the results are colored orange and if your browser is Firefox, the results are colored blue.



Hello World!


Here is the script that does this magic


 
var http = false;
//  Create a boolean for browser type
var isIE = false;

//  Determine type of browser	   
if(navigator.appName == "Microsoft Internet Explorer") 
 {
   http = new ActiveXObject("Microsoft.XMLHTTP");
   isIE = true;
 } 
else 
 {
   http = new XMLHttpRequest();
 }
   
 http.open("GET", "terryXML.xml", true);
 http.onreadystatechange=function() 
  {
   if(http.readyState == 4) 
    {
      var resp = http.responseXML;
      //  Start at the root node	  
      var root = resp.documentElement;
      //  Collect all the child nodes

      var children = root.childNodes;
	    
	if (isIE)
        {
            var i = document.getElementById("secondBox");
            i.innerHTML =
            "<span style='color:orange'>" +
            //  Aim at the "name" nodes in IE			
            children[0].firstChild.nodeValue +
            children[1].firstChild.nodeValue +
            "</span>";
         }
         else
         {
            var i = document.getElementById("secondBox");
            i.innerHTML = 
            "<span style='color:blue'>" +
            //  Aim at the "name" nodes in FireFox			
            children[1].firstChild.nodeValue +          
            children[3].firstChild.nodeValue +
            "</span>";
						
         }
        }
       }
      http.send(null);
 
 
 

HTML

 
 <div id="secondBox" style="height: 50px; width: 200px"></div>
 
 

Creating individual nodes

    var i = document.getElementById("secondBox");
    var j = document.createElement("p");
    j.setAttribute("style","color:red;");
    var jText = document.createTextNode(children[1].firstChild.nodeValue);
    j.appendChild(jText);
    i.appendChild(j);

    var k = document.createElement("p");
    k.setAttribute("style", "color: orange");
    var kText = document.createTextNode(children[3].firstChild.nodeValue);
    k.appendChild(kText);
    i.appendChild(k);
 
 

Testing for "name" nodes

    //alert(children.length);
	 
    var holder = "";
    for (var j = 0; j < children.length; j++)
        {
            if (children[j].nodeName == "name")
               {
                 holder += children[j].firstChild.nodeValue + "\n";
               }			
        } 
    alert(holder);