reptile7's JavaScript blog is Andrew Peak's personal technical writing project: it focuses on JavaScript and the analysis of JavaScript scripts, although HTML, CSS, and anything else related to coding for the Web are also fair game.

However, we can't just follow the xmlObj.send(null); command with some sort of xmlObj.responseXML expression, as the browser will hit that expression before the data.xml data arrives and consequently the expression will return null - not what we want, needless to say. Even for an asynchronous request, it is necessary to monitor the server's response so as to ensure that the requested document is available before we attempt to act on it; fortunately, this is easily accomplished via the XMLHttpRequest readyState property.

Since IE 4, Microsoft has provided a readyState property for tracking the loading progress of an object - go here and here for its documentation - this property can be applied to most HTML element objects but is most directly applicable to objects that load data themselves: the document object, the image object, the frame object, and so on. As an object loads, it goes through a series of ≤5 readyStates, not necessarily in this order: uninitialized, loading, loaded, interactive, and complete; to detect changes in these values, a companion onreadystatechange event handler was also implemented.

When Microsoft introduced the XMLHTTP object in IE 5 for Windows, it brought on board a modified readyState property having a scale of integer values running from 0 to 4, 4 meaning all the data has been received; a corresponding onreadystatechange event handler is again used to monitor changes in these values. The XMLHTTP readyState property and onreadystatechange event handler were subsequently ported by Netscape to the XMLHttpRequest object.

At the top of the tutorial's second page, the author attempts to detail the XMLHttpRequest readyState property by correlating its 0-4 scale with the uninitialized-to-completereadyState scale for other objects. As it happens, the two scales really don't match very well. The 0 and 4 values do respectively correspond to uninitialized and complete; however:

• The 1 value means A request has been opened, but the send( ) method has not been called and has no counterpart on the non-XMLHttpRequest side.

• The 3 value maps onto the loading value, but the 2 value is also a loading-type value indicating that the HTTP headers and status of the server's response are available.

• The interactive value means User can interact with the object even though it is not fully loaded and has no counterpart on the XMLHttpRequest side.

• Moreover, the loaded value means Object has finished loading its data and seems to be equivalent to the complete value.

Getting back to the tutorial code, the xmlObj.open("GET", file); command is preceded by a function expression that listens for changes in xmlObj's readyStates:

xmlObj.onreadystatechange = function ( ) { ... }

Microsoft's XMLHttpRequest onreadystatechange page states that you must set the event handler after calling open( ); maybe this is true for recent versions of IE but it's not true for the XMLHttpRequest-supporting browsers on my computer. Mozilla's send( ) method documentation used to say Note: Any event listeners you wish to set must be set before calling send( ) but no longer does so; I find that the script isn't hurt at all if the open( ) and send( ) commands are placed before the onreadystatechange expression.

The onreadystatechange function first checks if the request operation is complete - 4 is the only xmlObjreadyState that we are really interested in:

if (xmlObj.readyState == 4) { ... }

If the if condition is true, then the onreadystatechange function next calls an updateObj( ) function

that will update the "sample data" p element of the current document. The first updateObj( ) call parameter, xmlObj (not xmlData as stated in the tutorial text), is the id value of the to-be-updated p element. As for the second updateObj( ) call parameter, what a mouthful, huh? This lengthy expression scoops up the textual content, including leading and trailing white space, of the data.xml document's data element. To see what's going on here, let's recast the expression on a feature-by-feature basis:

Per the discussion at the outset of the post, xmlObj.responseXML; gets the data.xml document as a whole. xmldoc specifically returns [object XMLDocument] with Firefox and Opera and [object Document] with Safari and Chrome.

To refresh your memory, here's the data.xml document again:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<data>
This is some sample data. It is stored in an XML file and retrieved by JavaScript.
</data>
</root>

dataNodeList[0]; gets the first-in-source-order (and only) data element in the dataNodeList NodeList. This statement's syntax is not quite standard; the W3C-kosher way to access the dataNode1 node is to use the item( ) method of the DOM NodeList interface, i.e., var dataNode1 = dataNodeList.item(0);. dataNode1 specifically returns [object Element] with all of the aforementioned browsers.

You may be wondering, "Can't we give the data element an id="dataID" attribute and then use the getElementById( ) method to grab it?" This is possible, but then we'd have to write up for the data.xml document a custom DTD that assigns the ID type to the id attribute. If you'd like to do that, be my guest. I'll pass.

dataNode1.firstChild; gets the first (and only) child node of the dataNode1data element: an object implementing the DOM Text interface and representing the textual content of the element. dataTextNode specifically returns [object Text] with all of the aforementioned browsers.

dataTextNode.data; gets the character data of the dataTextNode Text node:

This is some sample data. It is stored in an XML file and retrieved by JavaScript.

In the data.xml source, this string is preceded by an end-of-line character and four space characters and is followed by an end-of-line character and two space characters; all of this white space is picked up by the data property but will be entirely or mostly discarded when we paste dataText into the current document.

The xmlObjid and the dataText string are initially assigned respectively to obj and data identifiers. Subsequently, the obj element's firstChild.data - all of the character data between the p element start-tag and the anchor element start-tag for the View XML data link - is replaced by the data string. Recall that we earlier zeroed out the View XML data link via a this.style.display='none'; command; if you're not going to bring back the link and are willing to overwrite it, then firstChild.data can be replaced by textContent in this case as well.The author conspicuously does not provide a demo for his handiwork. How does it all go in practice? I'll give you the skinny and roll out my own demo in the following entry.