Mar 30, 2011

Create an AJAX supported registration form with WhizBase

This tutorial will discuss fancy secure registration forms, with AJAX technology support. In this article I assume you already know HTML and some JS. I will write the code using WhizBase Server Pages, so you need to know some basics in WBSP (you might look at some of my other articles on WhizBase).

The Structure

I will first explain the structure of our registration form, as I am using AJAX, I will not have any refresh for our page, so I will have one main page with the HTML and JS code.
For the validation process I will use one WhizBase file, for submitting registration data I will use another WhizBase file.
To store the registration information I will need a DB, and for this demonstration I will use the simplest one, Microsoft Access DB.
Every registration process needs a confirmation process to reduce spam registrations. So I will need one WhizBase file for confirmation, for sending the email I will use two files (I will explain why later in this article).
Now let give names, I will create default.wbsp, validate.wbsp, submit.wbsp, mail.wbsp, blank.html and confirm.wbsp. I will create reg.mdb for DB.

Registration Elements

The registration form will contain a user name, first name, last name, email and password. All elements are required, so no element must be empty. The user name must be available, the password must be repeated to confirm the password and the email must be real.
<html>
<head>
<title>Registration Form</title>
<script type="text/javascript">
function loadXMLDoc(url,rezult)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET",url,false);
xmlhttp.send(null);
document.getElementById(rezult).innerHTML=xmlhttp.responseText;
}
function Validate()
{
loadXMLDoc('validate.wbsp?username='+document.getElementById("username").value+'&fname='+document.getElementById("fname").value+'&lname='+document.getElementById("lname").value+'&password='+document.getElementById("password").value+'&password2='+document.getElementById("password2").value+'&email='+document.getElementById("email").value,'msgs');
if(document.getElementById('msgs').innerHTML==""){
loadXMLDoc('submit.wbsp?wbf_username='+document.getElementById("username").value+'&wbf_fname='+document.getElementById("fname").value+'&wbf_lname='+document.getElementById("lname").value+'&wbf_password='+document.getElementById("password").value+'&wbf_email='+document.getElementById("email").value,'msgs');
}
}
</script>
</head>
<body>
<div id="msgs"></div>
<fieldset><legend>Enter your information in the form below.</legend><br />
Username:<br />
<input type="text" name="username" id="username" size="40" maxlength="60" /><br /><br />
First Name:<br/>
<input type="text" name="fname" id="fname" size="40" maxlength="60" /><br /><br />
Last Name:<br/>
<input type="text" name="lname" id="lname" size="40" maxlength="60"/><br /><br />
Password:<br />
<input type="password" name="password" id="password" size="40" maxlength="60"/><br /><br />
Confirm Your Password:<br />
<input type="password" name="password2" id="password2" size="40" maxlength="60"/><br /><br />
E-Mail:<br />
<input type="text" name="email" id="email" size="40" maxlength="60"/><br /><br /> </fieldset>
<div align="center">
<input type="button" value="Submit" onclick="Validate();" /></div>
</body>
</html>
Let me now explain the HTML and JS code. The HTML code have the basic elements of the registration, I have input text fields to insert data needed for the registration with two password fields (for the password, and a second for confirmation). Finally I have a submit button and a div for viewing system messages.
The JS code has two functions, the first is the AJAX JS function, the other is the validate function that I call when I submit the form.
You will notice I call AJAX for two reasons, one is for validating the data in the form, the second is for saving the data in the DB.

Validation process

I will create a file for validating form data and will name it as "validate.wbsp". In this script I need to validate data, if there is errors I must display an error message, if not, keep the output empty. The output will be returned by AJAX and displayed in the messages div.
[FormFields]
wb_basename=reg.mdb
wb_rcdset=profile
WB_Command=Q
wb_query=username="$wbv{username}"
wb_maxrec=1
[MsgAndLbl]
WBM_NoMatch=$wbsetv{msg|}
<!--WB_BeginTemplate-->$wbif["$wbp[rc]"=1|$wbsetv[msg|The username is not available, plase choose another!<br />]|]$wbif["$wbv[username]"=""|$wbsetv[msg|$wbgetv[msg]Please write your username!<br />]|]$wbif["$wbv[fname]"=""|$wbsetv[msg|$wbgetv[msg]Please write your first name!<br />]|]$wbif["$wbv[lname]"=""|$wbsetv[msg|$wbgetv[msg]Please write your first name!<br />]|]$wbsplit[$wbv[email]|email_array|@|F]$wbsplit[$wbgetv[email_array(1)]|domain|.|F]$wbif["$wbv[password]"=""|$wbsetv[msg|$wbgetv[msg]Please insert a password!<br />]|]$wbif["$wbv[password]"<>"$wbv[password2]"|$wbsetv[msg|$wbgetv[msg]Your passwords do not match!<br />]|]$wbif[($wbcstr[$wbv[email]|@]=1) and ($wblen[$wbgetv[email_array(0)]]>0) and ($wblen[$wbgetv[email_array(1)]]>0) and ($wblen[$wbgetv[domain(0)]]>0) and (($wblen[$wbgetv[domain(1)]]>1) and ($wblen[$wbgetv[domain(1)]]<5))||$wbsetv[msg|$wbgetv[msg]Please insert a valid email address<br />]]$wbgetv[msg]
WhizBase do not recognize lines, it's code is directly embeded in HTML, so any extra white space or break will show in the HTML, so I have removed all white spaces and breaks I do not need.
Let us go through the code step by step.
[FormFields]
wb_basename=reg.mdb
wb_rcdset=profile
WB_Command=Q
wb_query=username="$wbv{username}"
wb_maxrec=1
[MsgAndLbl]
WBM_NoMatch=$wbsetv{msg|}
<!--WB_BeginTemplate-->
Here I am connecting to my DB Access file with the record set (table) profile, making a Query command and giving a where clause option username="$wbv{username}", where $wbv{username} will show the parameter I sent by AJAX by get or post method. For WhizBase get and post are the same.
I am limiting the records with 1 maximum, because I just want to check if the username already exists in the DB. If there is no records I will set the msg variable empty, I will need this variable later in the code. WBM_NoMatch gives "No Matching records" message by default, I do not want that, so I am just setting a variable.
$wbif["$wbp[rc]"=1|$wbsetv[msg|The username is not available, please choose another!<br />]|]
If the query above returns data I will give an error message that the username is not available, and save the message in the msg variable. I'm using an IF statement and check if $wbp[rc] which returns the number of records are equal to one.
$wbif["$wbv[username]"=""|$wbsetv[msg|$wbgetv[msg]Please write your username!<br />]|]
In case the username is empty I give an error message to write the username. When I assign the message to the variable I must not forget the messages we have from before, so I use wbgetv in wbsetv to add the past ones also.
$wbif["$wbv[fname]"=""|$wbsetv[msg|$wbgetv[msg]Please write your first name!<br />]|]
$wbif["$wbv[lname]"=""|$wbsetv[msg|$wbgetv[msg]Please write your first name!<br />]|]
$wbif["$wbv[password]"=""|$wbsetv[msg|$wbgetv[msg]Please insert a password!<br />]|]
The same process as before I do for the first name, the last name and the password.
$wbif["$wbv[password]"<>"$wbv[password2]"|$wbsetv[msg|$wbgetv[msg]Your passwords do not match!<br />]|]
If the passwords do not match, it is also an error. WhizBase uses <> for not equal. If you put != it will provoke a syntax error.
$wbsplit[$wbv[email]|email_array|@|F]
$wbsplit[$wbgetv[email_array(1)]|domain|.|F]
$wbif[($wbcstr[$wbv[email]|@]=1) and ($wblen[$wbgetv[email_array(0)]]>0) and ($wblen[$wbgetv[email_array(1)]]>0) and ($wblen[$wbgetv[domain(0)]]>0) and (($wblen[$wbgetv[domain(1)]]>1) and ($wblen[$wbgetv[domain(1)]]<5))||$wbsetv[msg|$wbgetv[msg]Please insert a valid email address<br />]]
Checking the email if it is valid is a little more complicated process: I need to check if the email address has an @ sign, and if it has at least one character before and after the @ sign. I also check if the domain name part before the dot has at least one character, and if the TLD part is at least 2 characters but not more than four.
$wbgetv[msg]
Finally I display the error messages I have collected, if no error messages are provoked I will have an empty variable. This data is displayed by AJAX in my messages div.

The Database

Before I go with the submitting data process, I need to show you the DB I have created. It is one DB containing one table called profile. Profile contains seven fields. The id is an auto-incremental field. The confirm field is a number type field with zero default value. The rest fields (username, fname, lname, password, email) are text type fields. I am saving the DB as "reg.mdb" access file.

Submitting the data

The submitting section of the code doesn't just save data to the DB, it also calls the email file to send a confirmation request email.
Before I get to that, I pass the parameters in the URL using JS, a little bit different than before. I am use a wbf_ prefix for every parameter I want to add to the DB. WhizBase takes them automatically and filters them, then adds them in the location we specify.
[FormFields]
wb_basename=reg.mdb
wb_rcdset=profile
WB_Command=A
<!--WB_BeginTemplate-->$wbgeturl[mail.wbsp?id=$wbf[id]&email=$wbf[email]]You will recieve a confirmation email to finish the registration process.
This code will save the data in reg.mdb DB, in profile table using Add command. I will use wbgeturl function to call the email sending file, I am passing the id and the email of the last inserted data. By $wbf I can get the data inserted by this operation.
I return via AJAX the message "You will receive a confirmation email to finish the registration process.".
At this time I have data in the DB, but it is still not confirmed. I have created a confirm field in the DB which has by default a zero value.

Sending email

Sending an email in WhizBase is very easy, it supports HTML by default, anything I write in this file after the "<!--WB_BeginTemplate-->" code, will be shown in the email. So I must be careful what I write.
[FormFields]
WB_Command=P
WB_From=admin@yourdomain.com
WB_Redirect=blank.html
WB_Subject=Please confirm your registration
wb_mailserver=mail.yourdomain.com
WB_To=$wbv{email}
<!--WB_BeginTemplate-->Please click <a href="http://www.yourdomain.com/confirm.wbsp?wbf_id=$wbv[id]">here</a> to confirm your registration.
The command P is for sending custom email. I specify the email address I am sending from, as well as from which mail server, the recipient's email address, and the subject of the email. After the "<!--WB_BeginTemplate-->" code I write everything I want to show in the email, which in this case is a link to the confirmation page, with the id of the profile I saved.
I call this file with the wbgeturl function, which will show me the data returned from the file called. So I need to return nothing by redirecting the page I am calling to blank.html (which is a blank file). The redirect in WhizBase is made on the server side, so I do not get the message of the email, but the blank page.

Confirmation process

When the guest makes a registration he will receive my email for confirmation, the link to the confirmation must be clicked, which will call my file for confirmation.
[FormFields]
wb_basename=reg.mdb
wb_rcdset=profile
WB_Command=U
WB_UID=id
WB_FORCED=wbf_confirm=1
<!--WB_BeginTemplate-->Now you can login to the system!
The confirmation will update the DB, and put value 1 in the field confirm for the specified profile. Updating the DB is simple, I specify the DB name, the recordset (table) name, the U command for update, I specify which field is the unique identifier for this process. In our case it is ID. And I will force one parameter as it is sent with the URL call, it is wbf_confirm = 1.
Finally I tell the guest that he has become a user. In the next article I will show you how to make a Login in WhizBase code.
For more information email me at: NurAzije [at] Gmail [dot] com Or visit the WhizBase official site at www.whizbase.com

No comments: