Josh Gough

<November 2008>
SuMoTuWeThFrSa
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456


Navigation

Subscriptions

Post Categories



Monday, November 21, 2005 - Posts

AJAX Backend Agnostic State and County Dependent Listboxes
AJAX is the big idea these days. A little bit of AJAX sprinkled into web development tool box can definitely help you clean up some things. While there are dozens of new frameworks arising for going full-speed ahead into AJAX, some of us just want to add some usability to existing web sites. Here is a simple working prototype for a backend agnostic way to create a listbox of states and a listbox of counties such that when the user changes the state, the counties for that state are loaded in the county listbox.

I know this is not new stuff. People have been doing it for years, but maybe not with Ajax.
  • Some people pop open new windows.
  • Some people load content in hidden frames.
  • Some people just load the entire list into the browser when the page loads for the first time.
  • Still others are content to post the entire page back to the server and cause much pain and sufferring for users when they must complete all required fields before they can even select a county of residence or work.
But, now that we all love Ajax, let's look a dead simple example of doing this with XmlHttpRequest. Here are the tools we'll make use of:
WARNING: The FOLLOWING CODE IS SO SIMPLE YOU MAY BE BLINDED

Step 1: Create a dry as bones HTML UI Page

Name the page getCounties.html and fill it with this code. Make sure you download the xmlhttprequest.js file from Andrew's site.

<html>
    <head>
        <title>Test Ajax Callbacks</title>
        <script type="text/javascript" src="xmlhttprequest.js"></script>
        <script type="text/javascript" src="populateCounties.js"></script>
    </head>
    <body>
        <form name="locations">
            <p>
                <b>States:</b> <br />
                <select name="states" size="5" style="width: 300px;" onchange="getCounties(this)">
                    <option value="12">Florida</option>
                    <option value="13">Georgia</option>
                </select>
            </p>
            <p>
                <b>Counties:</b> <br />
                <select name="counties" id="selCounties" size="5" style="width: 300px;">
                    <option value="-1">Please Select a State to See Counties ... </option>
                </select>
            </p>
        </form>
    </body>
</html>

Step 2: Create a Backend Data Provider in ASP 3.0

In real life, you'd probably be calling a datasbase to generate the return values. In this sample, we'll just use stubs that load predefined lists. I don't even know if these correspond to FIPS codes or not, but in real life, you'd make sure they do.

Name this page getCounties.asp and fill it with this code:

<%
' Stub page that returns dummy county values for an ajax callback

Dim state_id, payload

state_id = Request.QueryString("sid")
payload = "{}"

If Not state_id = "" Then
    Select Case state_id
        Case "13"
            payload = "{1:'APPLING', 2:'COBB', 3:'DE KALB'}"
        Case "12"
            payload = "{1:'A COUNTY', 2:'B COUNTY', 3:'C COUNTY'}"
    End Select
End If

Response.Write payload
%>

Step 3: Create Front-End JavaScript Code to Handle the Events and Make the Callback to getCounties.asp

Finally, we'll create the front-end JavaScript code needed to manipulate the HTML SELECT object. Name this file populateCounties.js and put this code in it:

function getCounties(objSel)
{
    idx = objSel.selectedIndex;

    if (idx != null)
    {
        var val = objSel.options[idx].value;
        var req = new XMLHttpRequest();
        if (req)
        {
            req.onreadystatechange = function()
            {
                if (req.readyState == 4 && (req.status == 200 || req.status == 304))
                {
                    // Create an object from the returned literal code:
                    var objCounties = {};
                    try
                    {
                        eval("objCounties = " + req.responseText);
                    }
                    catch (ex)
                    {
                    }
                    populateCountiesList(objCounties);
                }
            };
            var requestStr = 'getcounties.asp?sid=' + val;
            req.open('GET', requestStr);
            req.send(null);
        }
    }

}

function populateCountiesList(objCounties)
{
    var counties = document.getElementById("selCounties");
    var len = counties.options.length;
    for (var i=0; i < len; i++)
    {
        counties.remove(0);
    }

    // Add the dummy value for people who don't want to choose a county
    counties.options[0] = new Option("Please Select a State to See Counties ... ", "-1");

    // add elements from the object
    var countyId;
    for (countyId in objCounties)
    {
        counties.options[counties.options.length] =
        new Option(objCounties[countyId], countyId);
    }
}

Step 4: You Can Test it by Loading it From My Site

To make it easier for you to see in action, I put the code on my site: http://apps.ultravioletconsulting.com/projects/AjaxStateAndCounty/getCounties.html

Later, I will put an entire solution with all states and counties.

Recap: Explanation of the Code

  1. The HTML is just a simple HTML UI that we are all familiar with.
  2. The getCounties.asp page accepts a state id and then returns a payload that contains a string of text the is actually valid JavaScript code. The line {1:'APPLING', 2:'COBB', 3:'DE KALB'} represents a JavaScript literal object. You can read more about literal notation in the ECMA-262 documentation or at the link to the JSON site above. All this means is that this is basically a hash-table, for Perl and Java folks, or a Dictionary, for VB folks.
  3. Inside of populateCounties.js, we finally find a GOOD use for the notorious eval() function. You remember when people used to use eval to do image rollovers? So do I. I'd rather not remember it though. It gave JavaScript a bad name, and it never deserved that. But, in our case, this is a perfect use for eval, because we really want to execute the string and bring its contents into the scope of the executing block. After that, we pass it to the populateCountiesList and perform some more standard, dry-as-bones HTML and JavaScript that we're all familiar with
So there it is. That's Ajax. You can replace getCounties.asp with whatever your backend of choice is. Just remember to build a literal JavaScript object as the payload, and then it's just plain-old HTML and JavaScript DOM manipulation from that point forward.

posted Monday, November 21, 2005 8:57 PM by JoshuaGough with 341 Comments




Powered by Dot Net Junkies, by Telligent Systems