From SwinBrain

This is a How To article designed to give step-by-step instructions. Search SwinBrain and the external links if you require more detailed information about this topic.


Asynchronous JavaScript and XML

In relation to web development, AJAX stands for Asynchronous JavaScript and XML ... although the 'X' should probably be for XMLHttpRequest.

There is a very good explanation of AJAX on Wikipedia.

Instead of repeating what's been written there, I'll show a small tutorial for AJAX. This is based on a tutorial by Bill Bercik, but adds some actual XML parsing, and uses Australian post codes (downloadable from the Australia Post web site.) If you want to see what we're going to build, have a look at this site.

Setting the Scene

The heart and soul of AJAX is "asynchronous". This allows us to communicate with the server without having to refresh the entire page, thus breaking our dependance on the traditional HTTP Request/Response paradigm.

This demo will show a trivial application that allows the user to type in their Australian post code and have the forms other fields (Suburb and State) automatically populated with the correct values without the user having to submit the form, and without the page having to be refreshed.

NOTE: This demo makes no attempt to be browser independent. It was developed under Firefox 1.0.7, and has not been tested on any other browsers (except Firefox 1.5, Beta 2). While I could make it browser independent, this would add more code, obfuscating the point I'm trying to demonstrate.

The HTML Form

  1. <form method="get" action="index.php" onsubmit="return false;" id="theForm">
  2. <label>Postcode<input type="text" id="postcode" onblur="updateCityState(this);"/></label>
  3. <label>Suburb<select id="suburb"></select></label>
  4. <label>State<input type="text" readonly="readonly" id="state" size="3"/></label>
  5. </form>
  6. </body>

That's it. They don't come much simpler than that. The forms action (on line 2), refers back to itself. This hasn't been implemented yet, but is intended to be part of a fallback in case Javascript isn't enabled.

One important feature is the onblur event in the postcode input field on line 3. This is what invokes the AJAX magic.

The only other thing of interest here is the empty select tag on line 4. This will get populated by the AJAX stuff, as will the state input field. Why have a select field? In Australia, a single postcode may be shared by several suburbs, so we may get a number of results which the user can select from, as you can see in the following XML...

The Data as XML

The X in AJAX stands for XML, so here it is. This is generated by a simple query ("select * from pcodes where pcode=3121", in this case) run in the PHP file, and returned to the page as XML (see below for the PHP code).

  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <addresses>
  3. <address>
  4. <postcode>3121</postcode>
  5. <location>BURNLEY</location>
  6. <state>VIC</state>
  7. </address>
  8. <address>
  9. <postcode>3121</postcode>
  10. <location>CREMORNE</location>
  11. <state>VIC</state>
  12. </address>
  13. <address>
  14. <postcode>3121</postcode>
  15. <location>RICHMOND</location>
  16. <state>VIC</state>
  17. </address>
  18. </addresses>

This XML shows a postcode (3121) that matches three suburbs. All three location will need to be populated into the select fields options. I would have used the 3122 post code where Swinburne is located, but there's only one match, so it's a poor example :(

The JavaScript

This Client-side JavaScript code has two basic purposes that relate to the functions wrriten

  • updateCityState() is the function that gets the specific (limited) data that we want and places it in an XML document. This also "hooks" the XML document (xmlDoc) onload event to call the populate() function.
  • populate() takes the data from the XML document (which is ready with the limited data needed) and presents it to the HTML form (via the document object model).

  1. <script type="text/javascript">
  3. var xmlDoc;
  5. function updateCityState(elementToRead)
  6. {
  7. if (document.implementation && document.implementation.createDocument)
  8. {
  9. xmlDoc = document.implementation.createDocument("", "", null);
  10. xmlDoc.onload = populate;
  11. }
  12. else
  13. {
  14. alert('Your browser can\'t handle this script');
  15. return;
  16. }
  17. xmlDoc.load("getSuburbState.php?param=" + elementToRead.value);
  18. }
  20. function populate()
  21. {
  22. var adresses = xmlDoc.getElementsByTagName('address');
  23. //set suburb stuff
  24. var subObj = document.getElementById("suburb") ;
  25. subObj.length = 0;
  26. subObj.length = adresses.length;
  27. for(i=0; i<adresses.length; i++)
  28. {
  29. subObj.options[i].text =
  30. adresses[i].getElementsByTagName('location')[0].firstChild.nodeValue;
  31. document.getElementById("state").value =
  32. adresses[i].getElementsByTagName('state')[0].firstChild.nodeValue;
  33. }
  34. }
  38. </script>


  1. <?php
  2. if(isset($_GET['param']))
  3. {
  4. header('Content-type: text/xml');
  5. $pcode = mysql_escape_string($_GET['param']);
  6. $query = "select * from pcodes where pcode = '$pcode'";
  7. $con = mysql_connect('localhost', 'user_name', 'password');
  8. if($con===false) die('failed to open db');
  9. if(false === mysql_select_db('db_name', $con)) die('failed to select db');
  10. $results = mysql_query($query, $con);
  11. mysql_close($con);
  12. echo('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n");
  13. echo("<addresses>\n");
  14. while($row = mysql_fetch_array($results, MYSQL_ASSOC))
  15. {
  16. echo("\t<address>\n");
  17. echo("\t\t<postcode>" . $row['pcode'] . "</postcode>\n");
  18. echo("\t\t<location>" . $row['place'] . "</location>\n");
  19. echo("\t\t<state>" . $row['state'] . "</state>\n");
  20. echo("\t</address>\n");
  21. }
  22. echo("</addresses>\n");
  23. }
  24. ?>