Ajax Hacks: Tips & Tools for Creating Responsive Web Sites

Ensure that an email address used as a username is unique but do not submit anything else on the page.

The email-address validation performed in "Validate Email Syntax" [Hack #23] allows you to safely send the email address off to the server-side program, where it will be checked against an existing database to see if it has already been used. This hack does that checking.

Figure 3-2 in "Validate Email Syntax" [Hack #23] shows what the web page looks like when the user types an entry that breaks our validity check. If the user enters an address with valid syntax, that address is sent to the server component. Depending on whether it passes the server-side check, the user then sees a message conveying either that the specified username has already been taken or that they have provided a unique email address, and it has been saved (Figure 3-3). "But all email addresses are unique," you might declare. That's true, but web users often try to register more than once at the same sitewho remembers all the tedious details about registering at the countless web sites we typically use? If you try to register twice with the same email address, the application responds that your username is already taken.

Figure 3-3. Unique name passes muster

If the email address is just one element on a lengthy registration form, a non-Ajax web application will submit all the form values at once when a user registers, and often painstakingly reconstruct the page just to instruct the user to try again. This hack submits only the email address and does not evaluate or refresh other page elements.

How It Works

Here is the HTML code, which "Validate a Text Field or textarea for Blank Fields" [Hack #22] also uses:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <script type="text/javascript" src="/books/4/254/1/html/2/js/http_request.js"></script> <script type="text/javascript" src="/books/4/254/1/html/2/js/email.js"></script> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Enter email</title> </head> <body> <form action="javascript:void%200"> <div ></div> Enter email: <input type="text" name="email" size="25"><br /> <button type="submit" name="submit" value="Send">Send</button> </form> </body> </html>

The JavaScript in email.js sends the validated email address to the server, which checks an existing database of usernames and responds with a "1" if the address is already in use (details on email validation were provided in "Validate Email Syntax" [Hack #23]). The simple XML response output looks like <is_used>1</is_used>. Here is the code from the checkAddress( ) function, contained in http_request.js, that sends the validated email address:

if(eml.valid) { url="http://www.parkerriver.com/s/checker?email="+ encodeURIComponent(val); httpRequest("GET",url,true,handleResponse); }

The code uses XMLHttpRequest to send the email address to the server component. The httpRequest( ) function wraps the creation and initialization of the request object. httpRequest( ) takes as parameters:

  • The type of request, as in GET or POST

  • The URL or server web address

  • A Boolean indicating whether the request is asynchronous or not

  • The name of a function or a function literal that handles the server response

The Server Handshake

The server then returns some XML indicating whether it has found the username or not. Here's the code for handleResponse( ), which appears in email.js:

//event handler for XMLHttpRequest function handleResponse( ){ var usedTag, answer,xmlReturnVal; if(request.readyState == 4){ if(request.status == 200){ //implement Document object in DOM xmlReturnVal = request.responseXML; usedTag = xmlReturnVal.getElementsByTagName("is_used")[0]; //the data will be 0 or 1 answer= usedTag.childNodes[0].data; if(answer==true){ eMsg("This user name is not available. Kindly try again.", "red"); } else { eMsg("Your new user name has been saved.","blue"); } } else { alert("A problem occurred with communicating between the "+ "XMLHttpRequest object and the server program."); } }//end outer if }

handleResponse( ) gets the XML by accessing the responseXML property of XMLHttpRequest. The code calls the DOM Document method getEle-mentsByTagName( ), which returns a nodeList (just like an array) of nodes that have the specified tag name. The tag name is is_used, as in <is_used>0</is_used>. Since the return value is an array structure, the code gets the first and only array member using [0]:

xmlReturnVal.getElementsByTagName("is_used")[0];

The code then accesses the text contained by the is_used tag and generates a user message. "Validate Email Syntax" [Hack #23] shows the eMsg( ) code.

For Those Server Hackers...

The code for the server-side component, which is a Java servlet that mimics a database, is shown below. It uses a Map type, a kind of Hashtable object, to contain the stored usernames; however, a full-fledged production application would use middleware to connect with a database and check on usernames.

A production application would also use a server component to implement a second layer of email validation, before it interacted with any stored email addresses. The server would also implement security measures to prevent any tampering with or mining of the email database.

Here is the server-side code:

public class EmailChecker extends HttpServlet{ //pretend this is the database! private static List USERS; static{ USERS=Collections.synchronizedList(new ArrayList( )); USERS.add("bruceperry@gmail.com"); USERS.add("johnjsmith@gmail.com"); USERS.add("teddyroosevelt@gmail.com"); USERS.add("janejsmith@gmail.com"); } protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String email=null; email = httpServletRequest.getParameter("email"); //we make this an int, because JavaScript converts //a valid String such as "false" to true int bool = 0; if(email != null){ if(USERS.contains(email)){ bool=1; } else { USERS.add(email); } } else { //throw ServletException signaling a null or //absent parameter } sendXML(httpServletResponse,bool); } protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { doGet(httpServletRequest, httpServletResponse); } private void sendXML(HttpServletResponse response, int emailUsed) throws IOException { response.setContentType("text/xml; charset=UTF-8"); String content = "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>"+ "<is_used>"+emailUsed+"</is_used>"; response.getWriter( ).write(content); } }

The server component can also check the email address's validity, as mentioned in the Note above the code, using another component designed for this purpose.

Категории