Go To Content
codylindley.com

codylindley.com

AXAH (Asynchronous XHTML and HTTP) - Crawl before you AJAX

The ability to update content asynchronous (remote scripting/changing a web page dynamically without a browser refresh) is the mythical power behind AJAX! Whether or not you agree with this notion is not important. Let’s just assume you agree, and because you agree, it would then be fair to say that using XML to grasp the power of AJAX would not necessarily be all that pertinent. What is vital is the basic understanding of the technique used (hidden requests to the server) to update content asynchronously.

With that said, the purpose of this article is to give an overview of AJAX without the use of XML. By focusing on the asynchronous and javascript parts of AJAX, I hope to ease the learning curve typically associated with AJAX. This article will detail the javascript required to dynamically update a web page with XHTML fragments instead of XML. If you are thinking this sounds an awful lot like AHAH (Asychronous HTML and HTTP), then you would be correct. This is pretty much the AHAH method. The exception is that my technique will be called AXAH (Asychronous XHTML and HTTP). I know, semantics really. Anyhow, I don't want to draw a dividing line between XML and XHTML. In theory they are the same thing, but today we are going to think of XHTML markup as a simple text string instead of well structured XML. I'll explain in a minute, but first let's have a look at our very simple demo or you can download the files for viewing on your own server. Make sure you are familiar with the source code for this demo before you proceed (a simple view source will do it).

If its not obvious, the example I created demonstrates how to update the content in a web page without a browser refresh. Let's take a moment and think about how simple this really is. All that is going on here is my browser is making a hidden (no visual refresh) HTTP (Hyper Text Transfer Protocol) request. Visual HTTP requests happen all the time when we surf the web using a browser. For example when I go from Yahoo.com to Google.com I 'm simply making an HTTP request for a new URL. The browser makes the request (because you load the new URL somehow), the URL changes, and the browser changes by removing the current content from a prior request and replacing it with the newly requested content. Of course this is all done over HTTP. With JavaScript making this type of request can be accomplished seamlessly (No visual browser re-fresh). Using a JavaScript object, a hidden HTTP request can retrieve new content (usually in the form of a text string or XML) in the background. Once the JavaScript has the requested information, it can then be manipulated and added to the current content by using the Document Object Model. If I lost you with my last couple of statements you might want to spend sometime brushing up on the basics of JavaScript and the DOM.

With the 50 thousand foot view of the AXAH technique under our belt, let's jump straight into the JavaScript and have a look at the event that starts the hidden HTTP request in my simple demo. In my particular example I have foregone the use of unobtrusive JavaScript by adding an onclick event to the <a> element (unobtrusive techniques have been ignored for the sake of clarity). When you click on a link in the example the javascipt function getAXAH(); is called/executed. The function has two arguments, "URL" and "elementContainer". The "URL" is the location of the content on the server the HTTP request is trying to access. In this example we are providing a URL to a specific xhtml document located on the server. The "elementContainer" argument is the value of an ID attribute on a specific element in the current content where the new content should be encapsulated. In my example I'm using a <div> element with an id attribute value of "content." Below is the <a> element from my example that will load the bold, blue Lorem Ipsum text:

<a href="Lorem-ipsum-blue.htm" onclick="getAXAH('Lorem-ipsum-blue.htm','content');return false;">
Load blue Lorem Ipsum <strong>bold</strong> text
</a>

Now that we understand how the getAXAH(); is called, and what parameters are passed to the function let's have a look at the function itself:

function getAXAH(url,elementContainer){
    document.getElementById(elementContainer).innerHTML = '<blink class="redtxt">Loading...<\/blink>';
    var theHttpRequest = getNewHttpObject();
    theHttpRequest.onreadystatechange = function() {processAXAH(elementContainer);};
    theHttpRequest.open("GET", url);
    theHttpRequest.send(false);

        function processAXAH(elementContainer){
           if (theHttpRequest.readyState == 4) {
               if (theHttpRequest.status == 200) {
                   document.getElementById(elementContainer).innerHTML = theHttpRequest.responseText;
               } else {
                   document.getElementById(elementContainer).innerHTML="<p><span class='redtxt'>Error!<\/span> HTTP request return the following status message: " + theHttpRequest.statusText +"<\/p>";
               }
           }
        }

}

The first statement found inside the function locates the element using the getElementById(); method by crawl the DOM to find the element with the correct ID. Once we find the correct element, the innerHTML property can be reset by giving it a new value. In the case of our function I am giving a new string value which contains XHTML. The innnerHTML property will essentially replace all markup and content with a given element. In our case, the given element is a <div> element.

On the next line I am creating a new variable (theHttpRequest) with a value that is returned by the getNewHttpObject(); function. Since we are calling a function from within another function let's have a look at that function before we proceed.

function getNewHttpObject() {
    var objType = false;
    try {
        objType = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
        try {
            objType = new ActiveXObject('Microsoft.XMLHTTP');
        } catch(e) {
            objType = new XMLHttpRequest();
        }
    }
    return objType;
}

The getNewHttpObject(); has one purpose, return the appropriate object type for doing an HTTP request based on which browser the user has. We have to do this because Microsoft has yet to give support for the XMLHttpRequest object that most modern browsers use today. In fact there are two implementations from Microsoft (Msxml2.XMLHTTP and Microsoft.XMLHTTP). The getNewHttpObject(); uses the different objects themselves to detect which browser the user has and then return that particular object type to the getAXAH(); function. This is really silly, but we can't ignore the fact that the majority of people on the web still use Internet Explorer. Due to this, we need an extra function that determines the appropriate object based on browser. Now lets look at the getAXAH(); function again.

With the correct object stored in the "theHttpRequest" variable we can use the common methods, properties and events associated with the various HTTP request objects. For instance, on the next line of the getAXAH(); function we use the "theHttpRequest" variable (storing the request object type) to set the "onreadystatechange" event for that object. This event is fired each time the status of the object changes. You can even access the status of the current state with this property, but more on that in a minute. Just keep it in mind that when the onreadystatechange event occurs the processAXAH(); is invoked.

Now that we have set what happens on a state change, let's move to the next line. Here we invoke the open(); method for our request object. This method sets up the call to the server. Several parameters (5 total, 2 required and 3 optional) can be used here but we are only using two. The first argument is the the type of request (GET, POST, or PUT) being made. The second argument is the URL of the resource we are requesting. In my code, this parameter is being set by a parameter passed from the getAXAH(); function. The next line of code actually sends the request. The argument used with the send(); method is set to false because we are not sending any content with our request, we are only requesting information.

If you remember back to the onreadystatechange event, you will see that I assigned a function to this event. This function is processAXAH(); and includes our "elementContainer" as a parameter. In other words I reused the "elementContainer" parameter in our embedded function. I am passing the same parameter in the getAXAH(); function right on to the processAXAH(); function embedded in the getAXAH(); function.

Looking at the getAXAH(); function it should be clear (if I haven't made it clear yet) that each time the onreadystatechange event is fired the getAXAH(); function is also executed. The getAXAH(); function purpose is to check the ready state of the request and the http status code return from the server. Looking at the function you will see that the first statement inside the function is checking if the readystate is equal to 4. The readystate has five possible values (0=uninitializewd, 1=loading, 2=loaded, 3=interactive, 4=complete), but due to cross browser compatibility we are only concerned with a complete value (4=complete). So we check to see if the state has a value equal to 4, and if it does, we then check to see if the http request status returned by the server is equal to 200. This 200 status value simply means that the http status is ok and the information was found. If you provided the wrong information in the URL parameter or don't have the file the request is looking in the correct location the http request status will likely return a 404 error. A 404 server status means the request content could not be found. In the code I have written the javascript so that if the status value is anything but a 200 status error a error message is added to the page via the dom. If the status of the server returns a 200 value we then take the requested content and update our content <div> with the content found in one of the XHTMLdocuments on the server. This is done by that statement shown below.

document.getElementById(elementContainer).innerHTML = theHttpRequest.responseText;

Notice that we are traversing the DOM with the getElementById(); method to find the <div> with an Id value of "content" (elementContainer is a parameter that represents the string "content") and then setting the innerHTML property of that particular element with the content requested. The content requested is accessible from the responseText property of the request object. Had we been working with XML today the response property would have been responseXML instead of responseText. To show how simple remote scripting is I have chosen to update my page with a simple text string, and thus I am using the responseText property to return the information as a text version instead of an XML object. Our text string just so happens to also be valid XHTML. So when we append this string of text back into the page using the DOM the browser also parses the tags inside the text string. Had we used the responseXML property extrapolating the information sent back from the server would have been much more complicated depending upon how the information is used. And with that said, we have successfully updated our page with a hidden JavaScript call to the server. Really pretty easy, don’t you think?

With a basic knowledge of the AXAH technique firmly understood I think a person could reasonably be expected to grasp more complex AJAX examples. So if, and when, you think you're ready here are a couple of AJAX examples to get you rolling.

 
  1.   #1 Comment Posted by Dennis Bullock on Jan 28, 02:36 PM

    This is kinda funny. I was reading this acticle and I thought…...I know I have read this before and then it came to me….Godbit! I had seen this on Godbit. At first I was thinking bad things about you and then after going over there I discovered you are one of the guys. Thought it was funny. You guys are great and I hope I can contribute some time. You know could I maybe interview you for posting on my site as I am a fellow designer.

    Thanks…..

  2.   #2 Comment Posted by some guy on Mar 4, 01:00 PM

    this is a very useful and simple way to approach AJAX. (it’s what i came to your site for before ranting about specializations on your other post.) thanks for making this code available.

  3.   #3 Author Comment on Mar 6, 09:48 AM

    @some guy – You are very welcome. Glad you can use the code.

  4.   #4 Comment Posted by theo boomsma on Mar 6, 11:02 AM

    Is it possible to stack two of these calls on one single onclick event? I mean can I open in a navigation bar page1.htm and in the content page2.htm at the same time…

  5.   #5 Author Comment on Mar 7, 08:34 AM

    Yes, the two calls would just have to be in a single function/object that uses the getAXAH(); function.

  6.   #6 Comment Posted by theo boomsma on Mar 27, 05:57 AM

    Thanks .. works great
    How do I load and start a javascript scroller from the AXAH script?

  7.   #7 Comment Posted by theo boomsma on Mar 28, 07:18 AM

    Just for sharing … function AJAXPage(url,elementContainer){for (i=1; i

  8.   #8 Comment Posted by one guy on Mar 31, 05:07 AM

    innerHTML won’t work with true xhtml. (tested with firefox myself)

    I think someone has missed the fact that any document that specifies itself as xhtml in doctype, but text/html in content type – will be treated as HTML (by ALL browsers i care about: opera, ie, firefox, netscape)! NOT XHTML!

    AXAH => more like AH ;)

    random (relevant) googling:
    link

  9.   #9 Comment Posted by Sejal on Apr 19, 08:42 AM

    Can we find out what is the status of a event which got fired..ie whether it has failed or suceeded?

  10.   #10 Author Comment on Apr 22, 09:03 AM

    @Sejal – Yup, the readystatus will tell you this.

  11.   #11 Comment Posted by ryan king on Apr 25, 02:26 PM

    Looks alot like AHAH [http://microformats.org/wiki/rest/ahah].

  12.   #12 Comment Posted by Fierce Unknown on Apr 26, 02:02 PM

    Great article!

    I do have a question: I have a map page setup for my wedding – using the yahoo flash api I created map markers for my city, and an additional map for the city the wedding will take place. Currently I link to the maps in iframes – I would like to use the AXAH method.

    When loading the page for the first time my city1 map is shown (built in javascript and displayed via flash) – when I request the other map the div is loaded correctly, but the javascript/flash map does not get created.

    is there a function to make the javascript run?

    am I asking this question correctly?

    cheers.

  13.   #13 Comment Posted by Johan on May 13, 10:23 AM

    Is it possible to request only the information say in a tag from another website – via the HTTP Request. If so, can you please provide an example. Lets say I would like to get hello world from a div with the id =headline

  14.   #14 Author Comment on May 14, 10:48 AM

    @johan – For the most part, no. HTTP request is limited to your own server (I believe). I think however there are some work arounds, but I have not looked into them. If it was possible then yes you (using the dom, xml or json) could access a text node in an element like you spoke of.

  15.   #15 Comment Posted by Anonymous on May 24, 02:54 PM

    To Dennis Bullock writing the first comment:

    why would you care if he had stolen the whole article word by word? if it gave you something right here right now then who cares who really came up with the idea in the first place?

  16.   #16 Comment Posted by Ray on May 30, 12:12 AM

    Internet Explorer 7, natively supports XMLHttpRequest() and has all other versions of this turned off by default, perhaps you could update your tutorial to relfect this instead of saying that all versions of IE don’t support it…

  17.   #17 Author Comment on Jun 13, 07:26 AM

    @Ray – Good idea, I’ll get around to this soon.

  18.   #18 Comment Posted by Samer Ali on Jun 30, 03:11 PM

    i think this is pretty good, i have already thought of using this i find coders complicating things more than it deserves, this is simple/clean/fast example, Thanks

  19.   #19 Comment Posted by Vsync on Jul 8, 07:01 AM

    Hey there! great article.
    one question though:

    i’m trying to call an HTML document containting hebrew characters, and it won’t show them. no mattar what i set in the AJAH.HTM (i use your example) at the charset..
    its just stays weired blocks.. why’s that ?

  20.   #20 Author Comment on Jul 8, 08:23 AM

    @Vsync – Well, if you wanted a different character set you would have to set it in the document that is pulling the AJAX content. If you wanted a different set for the AJAX content I believe you would have to use an iframe so that you could call an entirely new page.

  21.   #21 Comment Posted by Vsync on Jul 11, 10:00 AM

    Hello,

    well, i’ve tried to set every charset i’ve seen coded on the documents but nothing changed made it work.

    by the way, I’ve managed to make it work with Hebrew charset by useing the XML calling method and not HTML.. weired.

    anyway, yes, I thought it resembles an iframe (by loading files inside containers) but iframes aren’t so good for SEO anyway.

    thanks for the fast answer though! :)

  22.   #22 Comment Posted by Robert on Jul 11, 10:46 AM

    This works like a charm. Thanks for the detailed explanation of code!

  23.   #23 Comment Posted by Jeff Davis on Jul 13, 02:50 PM

    Working on a locked-down desktop for the moment and the example downloaded wasn’t working so I dumped readystate and status and because I’m accessing as a file, not a served web page, the status was 0 rather than 200. Changed the logic and off we go!
    Many thanks for this gentle intro, and a useful technique on its own… Axah!

  24.   #24 Comment Posted by anon on Aug 18, 02:17 AM

    too bad it doesn’t work on firefox =(

  25.   #25 Comment Posted by abbyAJAX on Sep 27, 06:17 AM

    I have a function which loads certain rows when the page is refreshed using AJAX. I am calling the fucntion in onComplete of Ajax.Request method.
    But it will not work correctly because the style.display is coming as undefined. That means my javascript function executes at wrong time before the rows are loaded correctly. Is there any way to call the function after making sure that all the rows are correctly loaded.

  26.   #26 Author Comment on Oct 2, 12:12 PM
  27.   #27 Comment Posted by Duk on Oct 17, 02:24 PM

    Good Ajax!

  28.   #28 Comment Posted by Daniele Florio on Nov 3, 01:24 AM

    Hi guys,

    I’d like to show you my new project about performing of AHAH original function. For more information please visit :

    http://www.gizax.it/ahahsection

    regards,

    D.Florio
    http://www.gizax.it
    Gizax Studios, Internet Accessibility

  29.   #29 Comment Posted by Geert Baven on Dec 3, 05:37 AM

    Hi Cody,
    Could you please check if there is something wrong with the files? when I download them I cannot get it to work, just keep getting error messages.

  30.   #30 Comment Posted by Chris on Jan 15, 07:21 PM

    I’m having the same problem as Geert.

    All files either copied form Source view or downloaded in Zip format don’t seem to be working.

    I’m on a Mac using FF 2.0.0.1

  31.   #31 Comment Posted by Daniel on Mar 26, 09:08 AM

    @Geert&Chris:
    Have you already tried to test the files on a web server (on your webspace or via a localhost service like XAMPP)? AJAX or AXAH use HTTP requests which only work with servers. When opening the AXAH.htm from a local file browser AJAX responses won’t work.

  32.   #32 Comment Posted by DJPaul on Jun 15, 04:27 AM

    Many thanks for this reminder

  33.   #33 Comment Posted by John Settino on Aug 9, 10:18 PM

    I’m trying to use this function to accept information from a prompt: An ID passed via the function call and a text variable set via the prompt(). The example I used can submit one variable to the url (?id=#) however, I also need to use a second, “&reason=x” however I cannot figure out how.

    I’m an ajax/javascript idiot and any help would be appreciated.

  34.   #34 Comment Posted by gazeteler on Oct 23, 05:39 AM

    This is kinda funny. I was reading this acticle and I thought…...I know I have read this before and then it came to me….Godbit! I had seen this on Godbit. At first I was thinking bad things about you and then after going over there I discovered you are one of the guys. Thought it was funny. You guys are great and I hope I can contribute some time. You know could I maybe interview you for posting on my site as I am a fellow designer.

  35.   #35 Comment Posted by fal on Oct 23, 05:40 AM

    Working on a locked-down desktop for the moment and the example downloaded wasn’t working so I dumped readystate and status and because I’m accessing as a file, not a served web page, the status was 0 rather than 200. Changed the logic and off we go!

  36.   #36 Comment Posted by youtube on Oct 23, 05:41 AM

    Yes, the two calls would just have to be in a single function/object that uses the getAXAH(); function.