Here is a something cool you can add to your web site. You have a registration form that asks for a username. In order to save the user time and a trip to the server, you want to see if the username exists as they type it in. Let's look at how Spry could handle this.

First, let me build a simple form:

<form id="userform" action="null.html" method="post"> <h2>Register</h2> <table width="600" border="0"> <tr valign="top"> <td align="right" width="200">username (min 4 characters)</td> <td width="400"><input type="text" id="username" name="username" onKeyUp="checkUsername()"> <span id="resultblock" class="error"></span></td> </tr> <tr> <td align="right">password</td> <td><input type="password" name="password"></td> </tr> <tr> <td align="right">confirm password</td> <td><input type="password2" name="password2"></td> </tr> <tr> <td> </td> <td><input type="button" value="Fake Submit"></td> </tr> </table> </form>

The only thing you want to pay attention to here are these two lines:

<input type="text" id="username" name="username" onKeyUp="checkUsername()"> <span id="resultblock" class="error"></span>

What I've done here is used a bit of JavaScript to execute when the form field is changed. (And I know onKeyUp has a few issues. Can folks recommend a more well rounded approach?) As the user types, it will call my function, checkUsername():

function checkUsername() { var uvalue = document.getElementById("username").value; if(uvalue.length < 4) { status(''); return; } Spry.Utils.loadURL("GET","userchecker.cfm?username="+encodeURIComponent(uvalue), false, usercheck);

}

In this code I grab the value of the form field. If the size is less than 4, I clear my result message and leave the function (the status function will be described in a bit). If we have enough characters, I then use loadURL, from the Spry.Utils package, to call a server side file. (Here is my earlier entry on loadURL.) I fire off the event and wait for the result. (At the end I'll talk about how to modify it to not wait.) Lastly, a function named usercheck will be called with the result. Let's take a look at that function:

function usercheck(request) { var result = request.xhRequest.responseText;

if(result == 0) status("Username not available!"); else status(''); }

When the result returns from the request, I have an object that contains information returned in the result. In this case, my server side script will return either a 1 or a 0. 0 is the flag for the username not being available, so I use my status function to write that result. Here is the status function in case you are curious:

function status(str) { var resultblock = document.getElementById("resultblock"); resultblock.innerHTML = str; }

As you can see, it is just using a bit of DHTML to update the span block next to my form field. Last but not least, here is the ColdFusion code running behind the scenes. Obviously it is not hooked up to anything real:

<cfsetting showdebugoutput=false>

<cfparam name="url.username" default="bob">

<cfset takennames="victor,jack,ashley,gloria,nikki">

<cfif listFindNoCase(takennames, url.username)> <cfset available = 0> <cfelse> <cfset available = 1> </cfif>

<cfoutput>#available#</cfoutput>

You can test this out here, and be sure to view source on the HTML page for a more complete view.

So I mentioned earlier that if I made my request not wait (asynch), then I'd have to modify things a bit. Because the user could keep on typing, I would need to return both the result and the username in my server side code. I'd then need to check and see if the username in the form field was still the same. I'll post a followup showing an asynch version later on.

Edited on August 26: Rob Brooks-Bilson raises some very good points about the security of this. Please be sure you read the comments below.