Monday, August 29, 2011

Asynchronous JavaScript and XML (AJAX)

I am looking at the W3Schools tutorial on AJAX. The tutorial begins with the statements:

AJAX is not a new programming language, but a new way to use existing standards. AJAX is the art of exchanging data with a server, and update parts of a web page - without reloading the whole page.

It is the exchanging data with a server phrase which interests me.

AJAX was made popular in 2005 by Google, with Google Suggest. Google Suggest [uses] AJAX to create a very dynamic web interface: When you start typing in Google's search box, a JavaScript sends the letters off to a server and the server returns a list of suggestions.

I used the same concept in the 90's in a VB application I created for the WA Trotting Association to help them maintain a database of competition entrants. So that idea is not new, but I guess doing it on a web page must be.

Apparently modern browsers (IE7+, Firefox, Chrome, Safari, and Opera) support the keystone of AJAX, the XMLHttpRequest object. Earlier versions of Internet Explorer (IE5 and IE6) use the MS ActiveXObject. The code examples in the tutorial allow for older IE versions, but in the example quoted below, I have edited this out for simplicity of analysis.

<html>

<head>
<script type="text/javascript">
function loadXMLDoc()
{
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
</script>
</head>

<body>
<div id="myDiv"><h2>Let AJAX change this text</h2></div>
<button type="button" onclick="loadXMLDoc()">Change Content</button>
</body>

</html>

The HTML code above sets out a web page comprising a header and a button (see below).

The header is enclosed within the <div> tag. A <div> tag usually divides a big web page into sections. It seems a bit redundant here, so I tried removing it, and labeling the header instead:

<h2 id="myDiv">Let AJAX change this text</h2>

It still worked, but the text, invoked by the button click, all appeared in the header style.

The JavaScript is all contained in the function loadXMLDoc, which is called by the button click event.

Within the function, the variable xmlhttp is declared and set as a new XMLHttpRequest object. I'd love to find this XMLHttpRequest object in a reference library, but I can't find it on the W3Schools JavaScript/DOM reference page. So from the tutorial I learn of two methods: open() and send(). The open() method seems to require the following parameters:

  • method - the type of request: GET or POST
  • url - the location of the file on the server
  • async - true (asynchronous) or false (synchronous)

The send() method allows the following parameter:

  • string: Used for POST requests

In the code above, the open() method is used with

  • method = "GET",
  • url = "ajax_info.txt" and
  • async = true.

The text contained in the file ajax_info.txt is:

<p>AJAX is not a new programming language.</p>
<p>AJAX is a technique for creating fast and dynamic web pages.</p>

Now from the code, it seems the XMLHttpRequest object has at least 3 properties:

  • .readyState
  • .status
  • .responseText

Just by reading the code it is not clear whether .responseText is populated by .open or .send. Intuitive logic would suggest the former, but in that case it is not clear what .send doing in there as well, although in the tutorial it says:

To send a request to a server, we use the open() and send() methods of the XMLHttpRequest object

And it shows the two methods being used one after the other, as they are in the code. The lesson then goes on to say a little more about the .responseText property and one more:

  • .responseText - holds the response data as a string
  • .responseXML - holds the response data as a XML data

It gives a further example using XML, which I shall skip at this stage, because on the next page we get clarification on the .readyState and .status properties, together with one I had failed to notice, .onreadystatechange. The last one appears to be both a property and an event:

  • The onreadystatechange event is triggered every time the readyState changes.
  • The onreadystatechange property stores a function (or the name of a function) to be called automatically each time the readyState property changes.
  • The readyState property holds the status of the XMLHttpRequest.

I have to say this leaves a question mark over what the .status property holds - a question not answered by the tutorial. What it does give is a list of acceptable values for these properties. For .readyState these are:

  • 0: request not initialized
  • 1: server connection established
  • 2: request received
  • 3: processing request
  • 4: request finished and response is ready

For .status these are:

  • 200: "OK"
  • 404: Page not found

By my calculation the property changes four times with every server request, so the onreadystatechange event must be triggered four times. I guess that explains the conditional clause in the function:

xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}

This function is called four times, but it only does anything on the fourth occasion, when "the request finished and response is ready" and the .status property is "OK". (And on closer reading this is mentioned in the tutorial.)

At first I was confused by the above code segment, because I didn't realize it is an unnamed function within the function loadXMLDoc() and is called by a different event. The loadXMLDoc() function is called be the button click event, while the unnamed function is both contained by the onreadystatechange property and called by the onreadystatechange event.

So when the button is clicked, everything inside the tag labeled "myDiv" is replaced with the text in the file. In its original version this appears as regular text (see below).

In my alternative version both paragraphs appear as headers because they both fall within the header tag (see below).

If the button is clicked again, nothing appears to happen, because the text is replaced by identical text. Again, I was initially confused here, because I thought the conditional clause had something to do with what was being displayed.

Anyway, this is all a bit disappointing, because I also misunderstood the exchanging data with a server phrase to mean exchanging data with a database on a server, not a measly old text file.