R E C E N T     E N T R I E S

POSTED: Wednesday, July 29, 2009

AJAX Field Validation

I had the opportunity to respond to a forum question last week,  "I have a form that when you submit it, it checks a field compared to a database, and if it does not match I want to redirect them back to to ASP page with the field in red indicating that it was invalid, what is the best way I can do this?"

 This is one of those situations where AJAX might be the best technique. AJAX is really a group of techniques on the client-side used to retrieve data from a server asynchronously (in the background) without reloading the page.  Data is usually retrieved using the XMLHttpRequest object.  Suprisingly, despite the acronym "AJAX", the use of JavaScript and XML is not actually required and the server requests need not be asynchronous.

In this example we are going to compare the text in a form input (text box) to fields in a database. The form sends a request to a database every time there is a "KeyUP".  Using AJAX, the form sends the information via a query string  and "queries" the database without reloading the page.  When a match is found, the text response changes from this:

<font color='#FF0000'>INCORRECT PASSWORD</font> 

to this:

<font color='#339933'>BINGO! CORRECT PASSWORD!</font> 

Here is the example - code follows below:

The code is straight-forward.  There is the "work-horse" page that is named ajax_username.asp and holds the database copnnection object and SQL statement. The Access database (in this example) is named "database.mdb" and the table is named "tblUsers" with a column (field) named "xusername".

<%
Set xusername = Request.QueryString("xusername")
Set DBConn = Nothing
Set DBConn = Server.CreateObject("ADODB.Connection")
DBconn.CommandTimeout = 0
ConnectStr = "provider=microsoft.jet.oledb.4.0; " & "data source=" & Server.MapPath("database.mdb") 
DBConn.Open ConnectStr
SQL = "SELECT [xusername] FROM [tblUsers] WHERE xusername='" & xusername & "' "
Set chk_xusername = Server.CreateObject("ADODB.Recordset")
chk_xusername.Open SQL, DBconn, 3, 3
If chk_xusername.EOF = False then
response.write ("<font color='#339933'>BINGO! CORRECT PASSWORD!</font>")
Else
response.write ("<font color='#FF0000'>INCORRECT PASSWORD</font>")
End if
chk_xusername.close
set chk_xusername = nothing
DBconn.close
set DBconn = nothing
%>

Here is the code for the public page that has the input form (save it as test.asp).  The page looks longer than it really is because we have included our CSS styles that may be moved to a separate sheet later.  They include the styles for the Form and the Fieldset as well as our standard "CSS Reset".

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax Test</title>
<script language="javascript">
function OnChangedUsername()
{
if(document.form1.newuserid.value == "")
{
document.form1.btnCheckAvailability.disabled = true;
}
else
{
document.form1.btnCheckAvailability.disabled = false;
}
}
function createRequestObject() {
var ReqObj;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
ReqObj = new ActiveXObject("Microsoft.XMLHTTP");
}else{
ReqObj = new XMLHttpRequest();
}
return ReqObj;
}
var http = createRequestObject();
function sndReq() {
http.open('get', 'ajax_username.asp?xusername='+document.form1.newuserid.value);
http.onreadystatechange = handleResponse;
http.send(null);
}
function handleResponse() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("xusername_chk").innerHTML = update[0];
}
}
}
</script>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
<!--
/* Begin  RESETS css */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
background: none;
}

/* remember to define focus styles! */
:focus {
outline: 0;
}

body {
line-height: 1;
color: black;
background: white;
}

ol, ul {
list-style: none;
}

/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: separate;
border-spacing: 0;
}

caption, th, td {
  text-align: left;
font-weight: normal;
}

blockquote:before, blockquote:after,
q:before, q:after {
content: "";
}

blockquote, q {
quotes: "" "";
}

textarea {
margin: 0; padding: 0;
}

/* End  RESETS css */
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 100%;
line-height: 1.5em;
background: #FFF;
margin: 0; /* it's good practice to zero the margin and padding of the body element to account for differing browser defaults */
padding: 0;
text-align: center; /* this centers the container in IE 5* browsers. The text is then set to the left aligned default in the #container selector */
color: #000000;
}
#container {
width: 780px;  /* using 20px less than a full 800px width allows for browser chrome and avoids a horizontal scroll bar */
background: #FFFFFF;
margin: 0 auto; /* the auto margins (in conjunction with a width) center the page */
/*border: 1px solid #000000;*/
text-align: left; /* this overrides the text-align: center on the body element. */
color:#000;
}

#container p {
        font-size: 90%;
text-align: left; /* this overrides the text-align: center on the body element. */
color:#333;

#container strong {
font-weight:bold;
}

#container #form1
{
width:400px;
}
#container #form1 fieldset
{
display: block;
background-color: #ffffff;
border:#CCC 1px solid;
font-size: 90%;
padding: 0px 0px 0px 10px; /* clockwise top-right-bottom-left */
color:#000;
width:400px;
}
#container #form1 fieldset label
{
margin: 0px 0px 10px 0px;
font-size: 90%;
font-weight: normal;
}
#container #form1 fieldset legend
{
margin-bottom: 1em;
padding:0px 5px 0px 5px;
}

#container #form1 fieldset legend p
{
font-size: 120%;
font-weight: normal;
color: #000080;
background-color: #ffffff;
}
#container #form1 fieldset .submit {
border: 1px inset #006;
background: #ccf;
margin: 15px 0px 5px 20px; /* clockwise top-right-bottom-left */
color:#000;
}

#container #form1 fieldset input {
margin: 0px 0px 10px 0px; /* clockwise top-right-bottom-left */

}
#container #form1 fieldset .submit:hover {
border: 1px inset #f00;
background: #eef;
cursor:pointer;
color:#000;
}
-->
</style>
</head>
<body>
<div id="container">
<form method="post" action="javascript:void(0);" name="form1" id="form1">
<fieldset>
<legend><p>AJAX PASSWORD EXAMPLE</p></legend>
<input type="newuserid" name="newuserid" id="newuserid" size="20" onKeyUp="sndReq();" />
<label for="newuserid">Type Password</label><br />
<input id="btnCheckAvailability" type="button" disabled="disabled" value="Password Check" onClick="sndReq();">
<label for="btnCheckAvailability"></label><br />
<div ID="xusername_chk"></div>
</fieldset>
</form>
</div>
</body>
</html>
 

Comments

1. Michael - great script, thanks for the post. However, when I type one letter, it tells me incorrect password (without doing a keyup, if I understand that correctly) Are there any security concerns with this? It also seems that it could be brute forced easier. I like it though.
by Scott+Race
2. Hi Scott!
The query is being sent to the database using httprequest after each keyup: onKeyUp="sndReq();".
For a form validation you could easily change this to a send request "onSubmit" instead...it is as secure as any other form post at that point...the example I wrote is just a fun and simple way to show AJAX functionality.
by Mike

3. Definitely slick, I can see how it could have many uses...thanks again.
by Scott+Race
4. What's really, really nice here is that you have shown how to do Ajax routines with an extremely small amount of easily understandable code. Broken down nicely into a couple of simple functions - a far cry from other examples I've seen. Great!
by Buddy




Name
URL
Email
Email address is not published
Remember Me
Comments

CAPTCHA
Write the characters in the image above