All Categories :
ActiveX
Chapter 6
Checking Form Data
CONTENTS
Almost every Web site, especially those run by commercial or semi-commercial
organizations, solicits information from the user. Whether it's
a simple request for further information or the user places a
complex order, the information that you as webmaster receive is
by and large unchecked, and you therefore rely upon the user to
enter the details correctly.
The usual remedy to this is to write a server-side CGI script,
which is not too onerous a task. However, the user must wait for
the information to travel to the server, the script to run, and
a new Web page to appear in the browser before he finds out whether
his information is within the limits. If the information isn't
valid, he re-enters the offending section and waits again. This
current method of data verification obviously wastes time and
bandwidth and assumes that you have access to the server's CGI-BIN
or CGI-LOCAL directories and that you have the resources
to create a server-side script in languages such as Perl or PHP/FI.
When you add client-side data verification, you can perform all
this verification at the browser. The user is immediately aware-even
as he is typing-of whether the data is acceptable. You cannot
stop the mischievous netizens who insist on filling out forms
using e-mail addresses such as me@imnottelling.com, but
at least you can do something to reduce the amount of totally
unusable information.
This chapter concentrates on the data-verification methods you
can add to a current HTML form without using ActiveX controls.
Part of Chapter 16, "Real-Life Examples II," shows you
how to build an interactive form with ActiveX controls and the
HTML layout control.
The main object of the exercise is to stop poorly formatted data
or data that doesn't fit your criteria from reaching the server.
This means that you have to perform some type of validation on
the data before it is submitted. The form object has an OnSubmit
event that is fired either when the user clicks the Submit button
or when the script calls the form object's submit method-ideal
for handling the validation process.
Prior to submission, while the user is entering data, you can
use several methods to alert the user to a problem with his input.
The HTML text box has an OnChange event that fires when
the focus moves away from the text box only if the text is different
from the last time the event fired. For example, you can enter,
This is some text, into an empty HTML text box, and the
OnChange event fires when you move to the next text box
or control. Return to the text box, delete the word text,
retype it, and move away. Because the text is unchanged, the OnChange
event doesn't fire-quite logical really!
Note |
The ActiveX text box Change() event does not work in this way. The Change() event is fired with every keystroke, and placing validation code in the Change() event handler can drive a user to distraction if it is not implemented thoughtfully.
|
Using the OnChange event, you can test for data acceptability
and caution the user if the test fails. Of course, this method
on its own doesn't really solve your problem because the user
can simply choose to click OK on the Alert box and then ignore
its warning-which means you still receive bad data at the server.
There is no substitute for preventing poor data from being submitted.
However, ongoing verification during the entry phase used in conjunction
with a final verification helps both you and the users.
Listing 6.1 shows the source code for the example you use in this
chapter; Figure 6.1 shows the Web page when it's run in the browser.
It contains five HTML text boxes. The first is an optional field
that contains no verification. Two fields require a numerical
entry, one requires a date, and one asks for the user's e-mail
address. As the user enters data and moves to the next field,
the data is verified, and if the script finds a problem, it alerts
the user. The verification takes place in a series of functions
that can be called from any of the fields, which allows for speedy
maintenance should you need to add further verifiable fields to
the form. Finally, the user clicks the submit button, which is
a normal button. The data is reverified, and if it's found to
be correct, the form data is submitted to the server.
Figure 6.1 : The sample form in the browser.
Listing 6.1. The sample source code for validate.htm.
<HTML>
<HEAD>
<TITLE>Data Validation</TITLE>
1:<SCRIPT LANGUAGE="vbscript">
2:Function ValidateNumber(ByVal TheNumber, ByVal FieldName)
3: If Not IsNumeric(TheNumber) Then
4: x = MsgBox("Invalid Numeric Entry",16,FieldName)
5: ValidateNumber = False
6: Else
7: ValidateNumber = True
8: End If
9:End Function
10:Function ValidateDate(ByVal TheDate, ByVal FieldName)
11: If Not IsDate(TheDate) Then
12: x = MsgBox("Invalid Date",16,FieldName)
13: ValidateDate = False
14: Else
15: ValidateDate = True
16: End If
17:End Function
18:Function IsEMail(ByVal TheEMail, ByVal FieldName)
19: If InStr(TheEMail, "@") > 2 Then
20: If Len(TheEMail) - InStr(TheEMail, "@") > 6 Then
21: If InStr(InStr(TheEMail, "@"),TheEMail,".") > 0 Then
22: If Len(TheEMail) - InStr(InStr(TheEMail, "@"),TheEMail,".") => 2 Then
23: ValidateEMail = True
24: Else
25: ValidateEMail = False
26: End If
27: Else
28: ValidateEMail = False
29: End If
30: Else
31: ValidateEMail = False
32: End If
33: Else
34: ValidateEMail = False
35: End If
36: If ValidateEMail = True Then
37: IsEMail = True
38: Else
39: x = MsgBox("Invalid Entry",16,FieldName)
40: IsEMail = False
41:End If
42:End Function
43:Sub txtQty_OnChange
44: x = ValidateNumber(Document.Form1.txtQty.Value, "Quantity")
45:End Sub
46:Sub txtSize_OnChange
47: x = ValidateNumber(Document.Form1.txtSize.Value, "Size")
48:End Sub
49:Sub txtDate_OnChange
50: x = ValidateDate(Document.Form1.txtDate.Value, "Date")
51:End Sub
52:Sub txtEmail_OnChange
53: x = IsEMail(Document.Form1.txtEmail.Value, "EMail")
54:End Sub
55:Sub cmdButton1_OnClick
56: If ValidateNumber(Document.Form1.txtQty.Value, "Quantity") And _
57: ValidateDate(Document.Form1.txtDate.Value, "Date") And _
58: ValidateNumber(Document.Form1.txtSize.Value, "Size") And _
59: IsEMail(Document.Form1.txtEmail.Value, "EMail") Then
60: Document.Form1.Submit
61: Else
62: Exit Sub
63: End If
64:End Sub
65:</SCRIPT>
</HEAD>
<BODY BGCOLOR="white">
<FORM NAME="Form1" ACTION="http://www.vbscripts.com/test/formtest.phtml"
METHOD=POST>
<PRE>
Your Name <INPUT TYPE="text" NAME="txtUserName">
Quantity <INPUT TYPE="text" NAME="txtQty">
Size in Metres <INPUT TYPE="text" NAME="txtSize">
Date <INPUT TYPE="text" NAME="txtDate">
Your EMail <INPUT TYPE="text" NAME="txtEmail">
<INPUT TYPE="Button" NAME="cmdButton1" VALUE="Submit Now">
</PRE>
</FORM>
</BODY>
</HTML>
The form itself is a straightforward HTML form; no surprises here.
The form's action is set to a PHP/FI-scripted HTML page, which
simply displays the data entered in the form. The HTML for the
form is shown in the following code block:
<FORM NAME="Form1" ACTION="http://www.vbscripts.com/test/formtest.phtml"
METHOD=POST>
<PRE>
Your Name <INPUT TYPE="text" NAME="txtUserName">
Quantity <INPUT TYPE="text" NAME="txtQty">
Size in Metres <INPUT TYPE="text" NAME="txtSize">
Date <INPUT TYPE="text" NAME="txtDate">
Your EMail <INPUT TYPE="text" NAME="txtEmail">
<INPUT TYPE="Button" NAME="cmdButton1" VALUE="Submit Now">
</PRE>
</FORM>
Each of the verifications is held in a separate function. Functions
in VBScript are procedures that return a value to the code that
called them. The following code is the function that validates
the numerical data:
2:Function ValidateNumber(ByVal TheNumber, ByVal FieldName)
3: If Not IsNumeric(TheNumber) Then
4: x = MsgBox("Invalid Numeric Entry",16,FieldName)
5: ValidateNumber = False
6: Else
7: ValidateNumber = True
8: End If
9:End Function
The function prototype in line 2 requires that two values are
passed into the function: first, TheNumber, which is
the value to be validated, and second, FieldName, which
is the name of the field being validated.
The keyword ByVal instructs the scripting engine to pass
only the value of these variables into the function. For more
detail on functions and procedures, see Chapter 9 "Making
Your Program Flow."
Line 3, where the actual verification takes place, introduces
you to a new concept, negation.
Suppose x equals 10. The statement If x = 10 Then returns
True, and the lines following the If... statement
execute. However, reversing the condition is known as negation;
if x is not equal
to 10, the code lines between the If and End If
execute if you write the statement as If Not x = 10 Then.
To learn more about If...Then conditional statements,
see Chapter 9.
Determining whether a series of characters is numeric isn't an
easy task if you consider the logic that must be performed. However,
VBScript's built-in checking functions include IsNumeric.
If the entered string can be converted to a number, the function
returns True; if it cannot be converted, the function
returns False. Remember that all data coming from an
HTML form is string data; for instance, the number 400 appears
to the program as "400".
Lines 4 and 5 execute only if the data entered into the field
cannot be converted into a number (such as non-numeric characters).
Line 4 displays a message box to the user informing him or her
that the entry is invalid; the message box uses an OK button and
a Stop icon. The user then has the option to return to the field
and retype the entry. Line 5 sets the function's own return value
to False.
Line 6 is part of the If...Then...Else conditional statement.
Line 7, which executes only if the IsNumeric function
returns True, sets the function's own return value to
True.
Lines 8 and 9 finish the If...Then statement and end
the function, passing execution back to the code that called the
function and returning a value of either True or False.
The function for validating the date in this example is very similar
to the numerical validation function:
10:Function ValidateDate(ByVal TheDate, ByVal FieldName)
11: If Not IsDate(TheDate) Then
12: x = MsgBox("Invalid Date",16,FieldName)
13: ValidateDate = False
14: Else
15: ValidateDate = True
16: End If
17:End Function
The function prototype in line 10 requires that two values are
passed into the function: first, TheDate, which is the
date entered by the user to be validated, and second, FieldName.
Line 11 is where the date verification takes place. To learn more
about If...Then conditional statements, see Chapter 9.
The IsDate function, which is built into the VBScript
engine, saves you from writing a huge script to cover all possible
combinations that are valid dates-12-Jun-96, 12-June-1996,
12-6-96, 12/06/96, 06/12/96, and so
on. The IsDate function operates on the user's date setting
in the International section of his Windows system. What is a
valid date in one country might be invalid in another. Suppose
a user in Sweden types the date 96.06.12, which is a
valid date format in Sweden, because his Windows system is set
to Swedish date formats. IsDate correctly returns True.
However, this presents a problem when you send the data to the
server.
Instead of writing a mammoth server-side script to handle every
possible date format in the world, you can restrict the date to
a certain format and display it to the user-for example, mm-dd-yy.
You can then create a script that checks for this rather rigid
date format.
Chapter 8 "Adding Date and Time Functions," shows a
more flexible alternative that breaks the user's date input into
month, day, and year and rearranges it to your desired format.
Lines 12 and 13 execute only if the data entered into the field
is not a valid date. Line 14 is part of the If...Then...Else
conditional statement. Line 15, which executes only if the IsDate
function returns True, sets the function's own return
value to True.
Lines 16 and 17 finish the If...Then statement and end
the function, passing execution back to the code that called the
function and returning a value of either True or False.
Verifying string data can become somewhat complicated because
you must decide what the string pattern should look like and hard
code that pattern into the script, as the following code shows:
18:Function IsEMail(ByVal TheEMail, ByVal FieldName)
19: If InStr(TheEMail, "@") > 2 Then
20: If Len(TheEMail) - InStr(TheEMail, "@") > 6 Then
21: If InStr(InStr(TheEMail, "@"),TheEMail,".") > 0 Then
22: If Len(TheEMail) - InStr(InStr(TheEMail, "@"),TheEMail,".") => 2
Then
23: ValidateEMail = True
24: Else
25: ValidateEMail = False
26: End If
27: Else
28: ValidateEMail = False
29: End If
30: Else
31: ValidateEMail = False
32: End If
33: Else
34: ValidateEMail = False
35: End If
36: If ValidateEMail = True Then
37: IsEMail = True
38: Else
39: x = MsgBox("Invalid Entry",16,FieldName)
40: IsEMail = False
41:End If
42:End Function
The pattern of an e-mail address at minimum should be ***@***.***,
where * is alphanumeric. Lines 19 to 22 check for this
minimum pattern.
Line 19 uses the InStr function to find the @
character somewhere in the string. InStr returns the
position of the character if found or 0 if it is not
found within the search string. The criteria you set for the first
part of the pattern is that the @ character must appear
at least three characters in from the left. As a result, the InStr
function in line 19 must return at least 3 for the first
part of the pattern to be true.
If the first part succeeds, the second part of the pattern dictates
that there must be a minimum of seven characters after the @
symbol. Line 20 tests this condition by subtracting the position
of the @ symbol from the length of the overall string,
which is found with the Len function.
20: If Len(TheEMail) - InStr(TheEMail, "@") > 6 Then
In the minimum pattern, the length of the string is 11 characters,
and the @ symbol resides at position 4; therefore, the
minimum number of characters to the right of the @ is
7. Line 20 tests for any amount greater than 6.
The next stage is a little more complex. Line 21 determines whether
a . (period) appears somewhere after the @ symbol.
Notice that the InStr function appears twice in line
21:
21: If InStr(InStr(TheEMail, "@"),TheEMail,".") > 0 Then
The full syntax of InStr is
InStr(Start,String1,String2)
In Line 21, you use the position of the @ symbol to determine
where InStr should start its search for the .
symbol. If it does find a . symbol somewhere after the
@ symbol, the function returns the position of the character,
and you can proceed to the final part of the pattern, which is
determining whether the . symbol appears at least two
characters in from the right. As you know, the e-mail address
could be a .com, .edu, .com.bh, .co.uk,
and so on.
22: If Len(TheEMail) - InStr(InStr(TheEMail, "@"),TheEMail,".") => 2
Then
Line 22 uses the position of the @, the position of the
., and the overall length of the string to determine
how many characters appear after the . symbol. Two or
more characters at the end makes the pattern complete and fits
our definition of the minimum e-mail address. Of course, as I
said earlier, this doesn't stop someone from entering aaa@aaa.aaa.
If the validation of the e-mail address fails at any stage, the
variable ValidateEmail is set to False. Finally,
the script makes a check of the variable, and if all is well,
the function's own return value is set to True. If the
data is invalid, the return value is set to False, and
a warning message is displayed to the user.
Where were all these functions called? What set them going? When
the user enters a new or changed value in one of the text boxes
and then moves away from that text box, an OnChange event
fires. The following segment shows the event handlers for each
of the text boxes, not including the first text box, which is
not validated:
43:Sub txtQty_OnChange
44: x = ValidateNumber(Document.Form1.txtQty.Value, "Quantity")
45:End Sub
46:Sub txtSize_OnChange
47: x = ValidateNumber(Document.Form1.txtSize.Value, "Size")
48:End Sub
49:Sub txtDate_OnChange
50: x = ValidateDate(Document.Form1.txtDate.Value, "Date")
51:End Sub
52:Sub txtEmail_OnChange
53: x = IsEMail(Document.Form1.txtEmail.Value, "EMail")
54:End Sub
I put these event handlers out on their own so that you can read
them easily, but it is legal to write the event handler within
the HTML definition of the text box in
this way:
<INPUT LANGUAGE="vbscript" TYPE=text ONCHANGE=" x = call
ValidateNumber(Document.Form1.txtSize.value,"Size")"
NAME="txtSize">
In fact, if you create these event handlers within the ActiveX
Control Pad, that is exactly the automatic code that the Control
Pad creates.
As mentioned in the introduction to the chapter, the main goal
of data validation is to reduce the amount of poor data or to
eliminate it altogether. What the example accomplishes so far
is really a cosmetic exercise in informing the user of the invalidity
of his data entry, hoping that this spurs him into action to change
the entry. However, the script doesn't guarantee this. The ultimate
precaution is to hide the data submission behind a wall of validation.
Only after all the validation checks that you specify are completed
successfully is the data submitted to the server, as you can see
from the following code:
55:Sub cmdButton1_OnClick
56: If ValidateNumber(Document.Form1.txtQty.Value, "Quantity") And _
57: ValidateDate(Document.Form1.txtDate.Value, "Date") And _
58: ValidateNumber(Document.Form1.txtSize.Value, "Size") And _
59: IsEMail(Document.Form1.txtEmail.Value, "EMail") Then
60: Document.Form1.Submit
61: Else
62: Exit Sub
63: End If
64:End Sub
Lines 56 through 59 are actually the same line, joined together
at runtime with the special underscore character. All checks must
return True for the overall statement to be True.
One of the nice things about this method of checking is that each
check is carried out regardless of the result of the last. The
user receives a prompt for all fields that fail the test.
Note |
Because you use functions to perform the validation, you can call them from many different places within your script, rather than rewrite the same code over and over.
|
When the data is in order, line 60 calls the form's submit method
and the data is on its way.
The ActiveX and VBScript documentation refers to using the OnSubmit
event to perform data validation in such a way that prevents form
submission if the validation fails. However, the documentation
does not describe the very odd way in which the OnSubmit
event must be implemented.
OnSubmit is an event and, as such, the code attached
to that event should be within an event handler. But the OnSubmit
event must be used as though it is a function. Here's how you
declare the prototype for the OnSubmit "event."
Function myForm_OnSubmit()
This is done so that OnSubmit can return a value. OnSubmit
returns True if the form data is validated, in which
case the form data is submitted; it returns False if
the form data fails validation, in which case the form data is
not submitted.
Within the OnSubmit event handler/function, you can include
calls to all your validation routines, as this amendment to the
previous example shows:
55:Function Form1_OnSubmit
56: If ValidateNumber(Document.Form1.txtQty.Value, "Quantity") And _
57: ValidateDate(Document.Form1.txtDate.Value, "Date") And _
58: ValidateNumber(Document.Form1.txtSize.Value, "Size") And _
59: IsEMail(Document.Form1.txtEmail.Value, "EMail") Then
60: Form1_OnSubmit = True
61: Else
62: Form1_OnSubmit = False
63: End If
64:End Sub
To use this code with the previous example, you would also have
to change the button control type to Submit.
In this chapter, you saw that client-side data verification is
economical in terms of time and bandwidth. You can use several
methods to ensure that data is formatted correctly and to alert
users to any problems with their data along the way. Here's a
brief summary:
- Use the OnBlur or OnChange events to determine
when a user has finished working on one field and moved onto another
field-your signal to check the data.
- Forcing the cursor back to the field can cause an infinite
loop.
- Check for a valid numeric value using IsNumeric.
- Check for a valid date value using IsDate.
- If you have to check a string for a particular pattern, decide
what the rules of that pattern are and how you are going to check
for those rules before you start programming.
- Always make the submission of data to the server conditional
upon successful data validation.
You have just learned how to interactively and programatically
validate data and then submit that data to the server. To brush
up on your skills to create even more complex validation routines,
look at the following chapters:
- Chapter 7 "Manipulating Strings," discusses formatting
and breaking down strings.
- For more information about date and time functions, see Chapter
8, "Adding Date and Time Functions."
- When you use If...Then conditional statements, consult
Chapter 9 "Making Your Program Flow."
Q: | If I put my validation routines on the client side, isn't it possible for someone to see what could be sensitive information?
|
A: | Yes, and for this reason, you should be careful what you place in a client-side validation routine. For example, don't write a script that says something like if myform.password.value <> "letmein" then.... If you do, you've just blown it!
|