NOTE: The client-side scripting language we use here is best known as Java-Script. However, in June 1998, the European Computer Manufacturers Association (ECMA) agreed to be responsible for the standard implementations of the scripting language by Microsoft, Netscape, and Sun. Accordingly, the real name of the language is now ECMA-Script, based on the standard ECMA-262. The most recent version of ECMA-262 is the third edition, dated December 1999.
WARNING: In a web database application, client-side validation should implement the same or less validation than a server-side script.
Client-side validation is optional but has benefits, including faster response to the user than server-side validation, a reduction in web-server load, and a reduction in network traffic. Moreover, client-side validation can be implemented as interactive validation, not only as post-validation, as on the server side. However, validation in the client tier is unreliable: the user can bypass the validation through design, error, or configuration. For that reason, client-side validation is a tool that should be used only to improve speed, reduce load, and add features, and never to replace server-side validation.
This example is designed to check if a userName field contains whitespace and, if so, to show a dialog box containing an error message to the user. The dialog box is shown in Figure 7-1.
Figure 7-1. The dialog box produced when whitespace is entered in the userName field
The function call is part of the <form> element:
<form onSubmit="return(containsblanks(this.userName));" method="post" action="test.php">
When the submission event occurs—the user presses the Submit button—the onSubmit action handler is triggered. In this case, the function containsblanks( ) is called with one parameter, this.userName. The object this refers to the <form> itself and the expression this.userName refers to the input widget within the <form>. The function call itself is wrapped in a return( ) expression. The overall result of executing containsblanks( ) is that if the function returns false, the <form> isn't submitted to the server; if the function returns true, the HTTP request proceeds as usual.
A sophisticated and general-purpose data entry function for post-validation and batch error reporting is shown in Example 7-2. Only part of the script is shown; the remainder of the script includes the same PHP code to retrieve data and the HTML to display the customer <form> as in Example 6-7 in Chapter 6.
In the example, the <form> tag contains a long script for the onSubmit event that is called when the user clicks the Submit button. The code creates and sets properties for each data entry widget. As all widgets are mandatory, a description property is created and set (e.g., this.email.description = 'Email'). This description is later displayed in an error dialog box if data isn't entered. For widgets that are optional—there are none in this example, but the full customer <form> in Chapter 10 has them—an optional = true property can be set.
For widgets that require specific validation, a property that describes the data type is set. For example, the email widget has a property of this.email.email = true to ensure that validation appropriate to an email field is performed. After setting all properties for all fields, the verify( ) function is called with the <form> (this refers to the <form>) object as a parameter; the <form> object includes all widgets and their properties.
For compactness, we don't describe in detail how the verify( ) function works. However, it has the following features:
The verify( ) function isn't comprehensive and certainly doesn't do all the validation proposed for the winestore customer <form>. However, in most cases, the customer <form> can't be submitted without a good chance of it passing the server-side validation checks.
This approach has the advantage of reducing network traffic if the user has a web browser cache, because a copy of the script can be reused in multiple HTML pages.
220.127.116.11. Case study: A password <form> validation function
Figure 7-3. A dialog box produced by the script in Example 7-3
The function thesame( ) checks if the current widget contains data. If it does, the data in the widget is compared to the data in the other password widget. If the data in the widgets is different, an error message is shown to the user. It's necessary to test whether both widgets actually contain data in interactive validation; without this check, the function annoyingly displays an error before the user has the opportunity to enter data into both widgets.
There are several other events that are commonly trapped and handled in validation:
18.104.22.168. Rollover presentation with mouseOver events
Example 7-4 shows a basic implementation of the common rollover feature used in many web applications.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd"> <html> <head> <title>MouseOver Example</title> </head> <body bgcolor="#ffffff"> <a href="add_to_cart.php" onMouseOut="cart.src='cart_off.jpg'" onMouseOver="cart.src='cart_on.jpg'"> <img src="cart_off.jpg" border=0 name="cart" alt="cart picture"></a> </body> </html>
When the page is first loaded, an image of a shopping cart in plain gray off-mode is shown; the image is used in the front page of the winestore. As usual, the image is loaded with the HTML fragment:
<img src="cart_off.jpg" border=0 name="cart">
The only difference to the usual approach of loading images is that the <img> tag has a name attribute, in this case name="cart".
The event handler changes the value of the src attribute of the <img> tag with the name="cart". The result is that a new image is loaded to replace the off-mode image with an on-mode image. In this case, a shopping cart with a blue foreground is shown.
This restores the original gray off-mode image. The impression to the user is that the cart element is highlighted as the user focuses on the element; the same technique is used to highlight menu options and to produce pop-up and pull-down menus.
When the user changes the quantity of wine he intends to purchase, an onChange event is generated. This change event is handled by the update( ) function, which modifies the value attribute of the total widget, showing the new total cost to the user. The new value shown to the user is calculated by multiplying together the quantity.value and the unit.value. Of course, as in all web database applications, the values and mathematics should be rechecked at the server when the <form> is submitted to the server.
22.214.171.124. Interacting with the web browser
Having said that, adding features that are helpful is desirable. Example 7-6 shows four examples of handlers for buttons that use methods or functions defined for the browser window object. The function window.close( ) closes the focused window, window.print( ) shows the print dialog window, windows.history.go(-1) goes back one page, and window.open( ) opens a new browser window.
The page rendered in a Netscape browser is shown in Figure 7-4.
Figure 7-4. Controlling the browser behavior through buttons
Only window.open( ) has any complexity. The first parameter is the URL to request in the new window, the second is a title, and the third is a set of properties the new window has. Without the list of properties that are included, the default new window has no Location box, no toolbars, no scrollbars, and can't be resized: it's an evil console!
126.96.36.199. Which browser is the user using?
Example 7-7. Which browser is the user using?
Figure 7-5. Detecting the browser application details using the script in Example 7-7
Copyright © 2003 O'Reilly & Associates. All rights reserved.