Working with forms is the cornerstone of many of the JavaScript programs currently available on the World Wide Web. From simple spreadsheets to conversion calculators and color-pickers, many scripts use forms and their associated properties, methods,
and event handlers to produce sophisticated interactive programs.
In order to effectively use forms in JavaScript, it is necessary to understand the form object and its properties and methods and to have a firm command of the events generated by different form elements.
In this chapter, you will learn this by covering the following topics:
The form object is one of the most heavily used objects in JavaScript scripts written for Navigator 2. Using the form object, as a programmer, you have at your disposal information about the elements
in a form and their values and can alter many of these values as needed.
A separate instance of the form object is created for each form in a document. As you learn later in the section about the forms[] array, forms all have a numeric index. They can also be referred to
by name.
Table 6.1 outlines the properties available with the form object.
Property |
Description |
action |
String containing the value of the ACTION attribute of the FORM tag |
elements |
Array containing an entry for each element in the form (such as checkboxes, text fields and selection lists) |
encoding |
String containing the MIME type used for encoding the form contents sent to the server. Reflects the ENCTYPE attribute of the FORM tag. |
name |
String containing the value of the NAME attribute of the FORM tag |
|
|
As you learn later in the section on the elements[] array, each of the elements of the form is itself an object with associated properties and methods. Elements can be referred to by name, as well as through their numeric index in the elements[] array.
With this property, you can ascertain the action specified in the form definition. For instance, in a form defined with the following:
<FORM METHOD=POST ACTION="/cgi-bin/test.pl">
the action property has a value of "/cgi-bin/test.pl".
This property is covered in more depth later in the section about the elements[] array.
The encoding property reflects the MIME type which is used to encode the data submitted from a form to the server. In practical terms, this means that the property reflects the ENCTYPE attribute of the FORM tag, and you can set the encoding of a form by changing the value of this property.
This is useful when you want to upload a file to be processed by a CGI script on the server. More details about form-based file upload is available in the Internet Engineering Task Force's Request for Comments document number 1867 at the
following site:
http://www.ics.uci.edu/pub/ietf/html/rfc1867.txt
This property provides the programmer with the name specified in the form definition. In a form defined with the tag:
<FORM METHOD=POST ACTION="/cgi-bin/test.pl" NAME="thisform">
the name property has a value of "thisform".
The target property is similar to the action and name properties and makes the content of the TARGET attribute
available to the programmer. In the FORM definition
<FORM METHOD=POST ACTION="/cgi-bin/test.pl" NAME="thisform" TARGET="thatframe">
the target property has a value of "thatframe".
There is only one method available with the form object: submit(). As mentioned in Chapter 5, "Events in
JavaScript," this method emulates a click on the submit button of a form without invoking the onSubmit event handler.
For instance, in the following script, the form has no submit button and can be submitted when the user enters the correct value in the text field. The onSubmit event handler, which returns false, ensures that the form is not submitted if the user hits
return in the text entry field.
<HTML> <HEAD> <TITLE>submit() Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function checkValue(form) { if (form.answer.value == "100") form.submit(); else form.answer.value = ""; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST ACTION="/cgi-bin/correct.pl" onSubmit="return false;"> What is 10 * 10? <INPUT TYPE="text" NAME="answer" onChange="checkValue(this.form);"> </FORM> </BODY> </HTML>
Just as it has only one method, the form object has only a single event handler associated with it: onSubmit. This event handler is invoked when the user submits a form. For instance, in the following script, when the user submits the form, she is thanked for doing so.
<HTML> <HEAD> <TITLE>onSubmit Example</TITLE> </HEAD> <BODY> <FORM METHOD=POST ACTION="/cgi-bin/test.pl" onSubmit="alert('Thanks for taking the test.');"> What is 10 * 10? <INPUT TYPE="text" NAME="answer"> <BR> <INPUT TYPE="submit"> </FORM> </BODY> </HTML>
Forms are made up of a variety of elements which enable users to provide information. Traditionally, the content (or value) of these elements is passed to programs on the server through an interface known as the Common Gateway Interface, or CGI for short.
Using JavaScript, though, you can write scripts into your HTML documents to work with form elements and their values. You already saw a basic example of this in Chapter 5, in Listing 5.3 where you produced an extremely simple calculator that calculated
the value of a JavaScript expression and displayed the result.
In this section, you will take a look at each type of form element in detail and see what properties and methods and event handlers are available for each.
Table 6.2 outlines the elements that make up forms. Each element has a corresponding object.
Form Element |
Description |
button |
A new element which provides a button other than a submit or reset button (<INPUT TYPE="button">) |
checkbox |
A checkbox (<INPUT TYPE="checkbox">) |
hidden |
A hidden field (<INPUT TYPE="hidden">) |
password |
A password text field in which each keystroke appears as an asterisk (*) (<INPUT TYPE="password">) |
radio |
A radio button (<INPUT TYPE="radio">) |
reset |
A reset button (<INPUT TYPE="reset">) |
select |
A selection list (<SELECT><OPTION>option1</OPTION><OPTIONoption2</OPTION></SELECT>) |
submit |
A submit button (<INPUT TYPE="submit">) |
text |
A text field (<INPUT TYPE="text">) |
|
|
Each of these elements can be named and referred to by name in a JavaScript script. Each also has properties and methods associated with it.
In standard HTML forms, only two buttons are availablesubmit and resetbecause the data contained in a form must be sent to some URL (usually a CGI-BIN script) for processing or
storage.
A button element is specified using the INPUT tag:
<INPUT TYPE="button" NAME="name" VALUE="buttonName">
In the above INPUT tag, a button named name is created. The VALUE attribute contains the text that the Navigator browser displays in the
button.
The button element has two properties: name (as specified in the INPUT tag) and value, which is also specified in the INPUT tag.
There is a single event handler for the button element: onClick. Associated with this is a single method: click().
The addition of the button element enables JavaScript programmers to write JavaScript code to be executed for additional buttons in a script.
For instance, in Listing 5.3, instead of using the onChange element, you could alter the script as shown in Listing 6.1, to evaluate the supplied expression when a button is pressed.
Input
<HTML> <HEAD>
<TITLE>button Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function calculate(form) { form.results.value = eval(form.entry.value); } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> Enter a JavaScript mathematical expression: <INPUT TYPE="text" NAME="entry" VALUE=""> <BR> The result of this expression is: <INPUT TYPE=text NAME="results" onFocus="this.blur();"> <BR> <INPUT TYPE="button" VALUE="Calculate" onClick="calculate(this.form);"> </FORM> </BODY> </HTML>
Checkboxes are toggle switches in an HTML form. They are used to select or deselect information. Checkboxes have more properties and methods available than buttons do, as outlined in Table 6.3.
Method or Property |
Description |
checked |
Indicates the current status of the checkbox element (property) |
defaultChecked |
Indicates the default status of the element (property) |
name |
Indicates the name of the element as specified in the INPUT tag (property) |
value |
Indicates the current value of the element as specified in the INPUT tag (property) |
|
|
As you might expect, there is a single event handler for checkboxes: onClick.
For example, you can use checkboxes to produce an alternative to the double and square exercise (Exercise 3) from Chapter 5. Instead of three fields, you can have an entry text field, a checkbox to indicate squaring (doubling will be the default action)
and a results text field.
The resulting script would look like Listing 6.2.
Input
<HTML> <HEAD> <TITLE>checkbox Example</TITLE> <SCRIPT> <!-- HIDE FROM OTHER BROWSERS function calculate(form,callingField) { if (callingField == "result") { if (form.square.checked) { form.entry.value = Math.sqrt(form.result.value); } else { form.entry.value = form.result.value / 2; } } else { if (form.square.checked) { form.result.value = form.entry.value * form.entry.value; } else { form.result.value = form.entry.value * 2; } } } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> Value: <INPUT TYPE="text" NAME="entry" VALUE=0 onChange="calculate(this.form,this.name);"> <BR> Action (default double): <INPUT TYPE=checkbox NAME=square onClick="calculate(this.form,this.name);"> Square <BR> Result: <INPUT TYPE="text" NAME="result" VALUE=0 onChange="calculate(this.form,this.name);"> </FORM> </BODY> </HTML>
Analysis
In this script, you see an example of how to use the onClick event handler as well as how the checked property is a boolean value which can be used as the condition for an if ... else statement.
You have added a checkbox named square to the form. If the checkbox is checked, the program will square the value. If it isn't, then the default action will be to double the value. The onClick event handler in the checkbox definition (<INPUT
TYPE=checkbox NAME=square onClick="calculate(this.form,this.name);">) ensures that when the user changes the desired action, the form recalculates (as well as if the user changes the value of the entry field).
In order to take advantage of the checkbox, you have also changed the calculate() function, as shown here:
function calculate(form,callingField) { if (callingField == "result") { if (form.square.checked) { form.entry.value = Math.sqrt(form.result.value); } else { form.entry.value = form.result.value / 2; } } else { if (form.square.checked) { form.result.value = form.entry.value * form.entry.value; } else { form.result.value = form.entry.value * 2; } } }
In this function, you use the boolean property checked to determine the correct action. If form.square.checked is true, then you should be squaring; if the value is false, you should be doubling the value in the entry field.
End of Analysis
The hidden element is unique among all the form elements in that it is not displayed by the a Web browser. Hidden fields can be used to store values that need to be
sent to the server along with a form submission but shouldn't be displayed in the page.
They can also be used in JavaScript to store values used throughout a script and for calculations within a form.
The hidden object has only two properties associated with it: name and value, both of which are string values like other objects. There are no methods or event handlers for the hidden object.
The password element is a unique type of text entry field in that any keystrokes are displayed as an asterisk (*). this makes the
password element ideal for accepting input of confidential information such as account passwords or bank account personal identification numbers (PINs).
The password object has three properties similar to text fields: defaultValue, name, and value. Unlike the previous two elements, the password fields include more
methods (focus(), blur(), and select()) and the corresponding event handlers: onFocus, onBlur, and onSelect.
We will discuss these methods and event handlers in more detail in the section on the text element.
The radio element is similar to toggle checkboxes, except that several radio buttons are combined into a group and only a single button can be selected at any given
time. For instance, the following lines produce a group of three radio buttons named test, similar to those in Figure 6.1.
<INPUT TYPE="radio" NAME="test" VALUE="1" CHECKED>1<BR> <INPUT TYPE="radio" NAME="test" VALUE="2">2<BR> <INPUT TYPE="radio" NAME="test" VALUE="3">3<BR>
The group of radio buttons is formed by using a consistent name in all the INPUT tags.
Figure 6.1. With a group of radio buttons, only one element can be selected at any given time.
The radio element is accessible in JavaScript through the radio object which has several properties for checking the current status of a radio button group. Table 6.4 outlines the properties and methods available with the radio object.
Method or Property |
Description |
checked |
Indicates the current status of the radio element (property) |
defaultChecked |
Indicates the default status of the element (property) |
index |
Indicates the index of the currently selected radio button in the group |
length |
Indicates the number of radio buttons in a group |
name |
Indicates the name of the element as specified in the INPUT tag (property) |
value |
Indicates the current value of the element as specified in the INPUT tag (property) |
|
|
As with checkboxes, the single event handler, onClick, is available for radio buttons.
The index and length properties haven't appeared in any of the form elements we have looked at so far in this chapter. Because a radio button group contains multiple elements, the radio object maintains an array of the radio buttons with indexes
starting at zero. In the example of a radio button group named "test" above, if the group were part of a form named "testform", we could reference the second radio button as testform.test[1], and we could check the current status of the
button with testform.test[1].checked.
To illustrate usage of the radio object, you can rewrite Listing 6.2 used to demonstrate checkboxes, using radio buttons instead.
Input
<HTML> <HEAD> <TITLE>checkbox Example</TITLE> <SCRIPT> <!-- HIDE FROM OTHER BROWSERS function calculate(form,callingField) { if (callingField == "result") { if (form.action[1].checked) { form.entry.value = Math.sqrt(form.result.value); } else { form.entry.value = form.result.value / 2; } } else { if (form.action[1].checked) { form.result.value = form.entry.value * form.entry.value; } else { form.result.value = form.entry.value * 2; } } } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> Value: <INPUT TYPE="text" NAME="entry" VALUE=0 onChange="calculate(this.form,this.name);"> <BR> Action:<BR> <INPUT TYPE="radio" NAME="action" VALUE="twice" onClick="calculate(this.form,this.name);"> Double<BR> <INPUT TYPE="radio" NAME="action" VALUE="square" onClick="calculate(this.form,this.name);"> Square <BR> Result: <INPUT TYPE=text NAME="result" VALUE=0 onChange="calculate(this.form,this.name);"> </FORM> </BODY> </HTML>
In this example, the changes from the checkbox version are subtle. Instead of one checkbox, you now have a pair of radio buttons with different values: double and square.
You know that the individual radio buttons are accessible through an array so that the double button is action[0] and the square button is action[1]. In this way, you only need to change the references in the calculate() function from
form.square.checked to form.action[1].checked.
Using the reset object in JavaScript, it is possible to react to clicks on the reset button. Like the button
object, the reset object has two properties (name and value) and one method
(click()). The onClick event handler is also available.
Although most programmers do not find a need to use the onClick event handler for reset buttons or need to check the value of the button, the reset object can be used to clear the form to some value other than the default.
Listing 6.4. demonstrates how the RESET button can be used to clear a form to different values than the default.
Input
<HTML> <HEAD> <TITLE>reset Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function clearForm(form) { form.value1.value = "Form"; form.value2.value = "Cleared"; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> <INPUT TYPE="text" NAME="value1"><BR> <INPUT TYPE="text" NAME="value2"><BR> <INPUT TYPE="reset" VALUE="Clear Form" onClick="clearForm(this.form);"> </FORM> </BODY> </HTML>
This script is fairly simple. You have created a form with two text fields and a reset button. The reset button has an onClick event handler which calls clearForm() when the button is clicked.
The clearForm() function takes the form object as an argument and proceeds to place two new values in the two text fields of the form.
Selection lists in HTML forms appear as drop down menus or scrollable lists of selectable items. Lists are
built using two tags: SELECT and OPTION. For instance, the following code snippet
<SELECT NAME="test"> <OPTION SELECTED>1 <OPTION>2 <OPTION>3 </SELECT>
creates a three-item drop-down menu with the choices 1, 2, and 3. Using the SIZE attribute you can create a scrollable list with the number of elements visible at one time indicated by the value of the SIZE attribute. To turn your drop-down menu into a
scrollable menu with two visible items you could use the following:
<SELECT NAME="test" SIZE=2> <OPTION SELECTED>1 <OPTION>2 <OPTION>3 </SELECT>
In both of these examples, the user can make only one choice. Using the MULTIPLE attribute, you can enable the user to select more than one choice in a scrollable selection list:
<SELECT NAME="test" SIZE=2 MULTIPLE> <OPTION SELECTED>1 <OPTION>2 <OPTION>3 </SELECT>
Selection lists are accessible in JavaScript through the select object. This object bears some similarity to both the buttons you have seen, as well as with radio buttons.
As with radio buttons, the list of options is maintained as an array with indexes starting at zero. In this case, the array is a property of the select object called options.
Both the selection option, as well as individual option elements have properties. In addition to the options array, the select object has the selectedIndex property which contains the index number of the currently selected option.
Each option in a selection list also has several properties. defaultSelected indicates if the option is selected by default in the OPTION tag. The index property contains the index value of the current option in the options array. Again, as you might
expect, selected indicates the current status of the option, text contains the value of the text displayed in the menu for the specific option, and value contains any value indicated in the OPTION tag.
The select object has no available methods. The select object has three event handlers which don't correspond to the available event emulating method. These are
onBlur, onFocus, and onChangethe same as for the text object.
For example, if you have the following selection list:
<SELECT NAME="example" onFocus="react();"> <OPTION SELECTED VALUE="Number One">1 <OPTION VALUE="The Second">2 <OPTION VALUE="Three is It">3 </SELECT>
then when the list is first displayed, you would have access to the following information:
example.options[1].value = "The Second" example.options[2].text = "3" example.selectedIndex = 0 example.options[0].defaultSelected = true example.options[1].selected = false
If the user then clicks on the menu and selects the second option, the onFocus event handler would execute (the react() function would be called) and then the values of these same properties would be as follows:
example.options[1].value = "The Second" example.options[2].text = "3" example.selectedIndex = 1 example.options[0].defaultSelected = true example.options[1].selected = true
The submit button is another special-purpose button like the reset button. This button submits the current information from each field of
the form to the URL specified in the ACTION attribute of the FORM tag using the METHOD indicated in the FORM tag.
Like with the button object and the reset object, you have name and value properties available to you, along with a click() method and an onClick event handler.
text elements are among the most common entry fields used in HTML forms. Similar to the password field you looked at earlier, text fields enable a single line of text entry, but unlike the
password element, the text is displayed as normal type rather than as asterisks.
The text object has three properties: defaultValue, name and value. Three methods emulate user events: focus(), blur(), and select()
(which selects the text in the entry field). Four event handlers are available: onBlur, onFocus, onChange, and onSelect (for when the user selects some of the text in the field).
Table 6.5 outlines the properties and methods for the text element.
Method or Property |
Description |
defaultValue |
Indicates the default value of the element as specified in INPUT tag (property) |
name |
Indicates the name of the element as specified in the INPUT tag (property) |
value |
Indicates the current value of the element (property) |
focus() |
Emulates giving focus to the text field (method) |
blur() |
Emulates removing focus from the text field (method) |
|
|
It is important to note that the content of a text field can be changed by assigning values to the value property. Thus, in the following example, whatever text is entered in the first field is echoed in the second field,
and any text entered in the second field is echoed in the first field. By itself, this has little value, but the ability to use data from a text field and to dynamically update and change data in a text field is a powerful feature of JavaScript.
Input
<HTML> <HEAD> <TITLE>text Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function echo(form,currentField) { if (currentField == "first") form.second.value = form.first.value; else form.first.value = form.second.value; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM> <INPUT TYPE=text NAME="first" onChange="echo(this.form,this.name);"> <INPUT TYPE=text NAME="second" onChange="echo(this.form,this.name);"> </FORM> </BODY> </HTML>
The TEXTAREA tag provides a custom size multiple-line text entry field defined by a container. The example in this code
<TEXTAREA NAME="fieldName" ROWS=10 COLS=25> Default Text Here </TEXTAREA>
creates a text entry field of 10 rows with 25 characters on each line. The text Default Text Here would appear in the field when it is first displayed.
Like the text element, JavaScript provides you with the defaultValue, name and value properties, the focus(), blur(), and select() methods and the onBlur, onFocus, onChange, and onSelect event handlers.
Now that we have taken a detailed look at the form object, its elements, properties, and methods, you are ready to use this information to build a somewhat more
complicated script.
In this example, you will build a simple mathematical calculator using forms. That is, each number and the four mathematical functions (addition, subtraction, multiplication, and division) will each be a button. You will also have two other buttons: one
to clear the running total and the other to clear the current entry.
In order to make your calculator appear more organized, you will make use of HTML tables. For those without experience using tables, tables are contained in the TABLE container tag and consist of rows contained in the TR tag and column elements
contained in the TD tag. In addition, the COLSPAN attribute causes a cell to cover two columns. Similarly, ROWSPAN makes a cell two rows deep.
For instance, the HTML code in Listing 6.6 produces a simple table.
Input
<TABLE BORDER=1> <TR> <TD COLSPAN=2>This is a table</TD> </TR> <TR> <TD>One</TD> <TD>Two</TD> </TR> <TR> <TD>Three</TD> <TD>Four</TD> </TR> </TABLE>
Output
The output from Listing 6.6 looks like the one in Figure 6.2.
Figure 6.2. HTML tables contain rows and columns of cells
End of Output
Using tables, then, you are ready to work on developing your calculator.
In terms of behavior, your calculator should work the way a simple electronic calculator does: When a user enters a number, it is immediately displayed to the right of previously entered digits. Mathematical functions are executed in the order entered
(no precedence here), and the effects of operations are cumulative until the clear button is pressed. Listing 6.7 is the source code for this calculator.
Input
Listing 6.7. Creating a calculator with tables.
<HTML> <HEAD> <TITLE>Example 6.1</TITLE> <SCRIPT> <!-- HIDE FROM OTHER BROWSERS var total = 0; var lastOperation = "+"; var newnumber = true; function enterNumber(digit) { var form = digit.form; if (newnumber) { clearNumber(form); newnumber = false; } form.display.value = form.display.value + digit.name; } function clear(form) { total = 0; lastOperation = "+"; form.display.value = ""; } function clearNumber(form) { form.display.value = ""; } function calculate(operation) { var form = operation.form; var expression = total + lastOperation + form.display.value; lastOperation = operation.value; total = eval(expression); form.display.value = total; newnumber = true; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM> <TABLE BORDER=1> <TR> <TD COLSPAN=4> <INPUT TYPE=text NAME=display VALUE="" onFocus="this.blur();"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="7" VALUE=" 7 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="8" VALUE=" 8 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="9" VALUE=" 9 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="+" VALUE=" + " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="4" VALUE=" 4 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="5" VALUE=" 5 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="6" VALUE=" 6 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="-" VALUE=" - " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="1" VALUE=" 1 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="2" VALUE=" 2 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="3" VALUE=" 3 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="*" VALUE=" * " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="0" VALUE=" 0 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="C" VALUE=" C " onClick="clear(this.form);"> </TD> <TD> <INPUT TYPE=button NAME="CE" VALUE="CE" onClick="clearNumber(this.form);"> </TD> <TD> <INPUT TYPE=button NAME="/" VALUE=" / " onClick="calculate(this);"> </TD> </TR> </TABLE> </FORM> </BODY> </HTML>
Output
This script produces results like those in Figure 6.3.
Figure 6.3. Tables make the calculator look appealing, and JavaScript makes it work.
End of Output
Analysis
Several interesting techniques are used in this script. Let's take a look at selected parts of the script sequentially from the start.
var total = 0; var lastOperation = "+"; var newnumber = true;
Here you declare the global variables you need to keep track of information. The total variable contains the current running total of the user's calculations. This is the same as the last displayed value before the user began entering new a new number.
lastOperation is used to keep track of the operation last entered by the user to be performed on the running total and the newly entered number. newnumber is used to keep track of when user input should be treated as a new number or part of the currently
displayed number.
The initial values of these variables require some explanation. Obviously, total starts with a zero value. However, as you will see later in the calculate() function, you need a lastOperation value to perform on every number entered. By assigning the
value "+" to lastOperation, the first number entered by the user will be added to the initial total of zero.
function enterNumber(digit) { var form = digit.form; if (newnumber) { clearNumber(form); newnumber = false; } form.display.value = form.display.value + digit; }
You pass the currently clicked button object to enterNumber() as the argument digit. The line var form = digit.form; provides you with reference to the form containing the current button in much the same way as when you pass this.form to a function.
Because each new digit is added to the right side of the number you can treat the digits as strings concatenate.
function calulate(operation) { var form = operation.form; var expression = total + lastOperation + form.display.value; lastOperation = operation.value; total = eval(expression); form.display.value = total; newnumber = true; }
The calculate() function is where the real work of the calculator script is done. The function is invoked when the user clicks on one of the operator buttons. When this happens, the line var expression = total + lastOperation + form.display.value;
builds an expression in the form of a string.
You then use the eval() function to evaluate the expression you have just built. This value becomes the new value of total, is displayed in the text field, and the operation the user has just clicked is assigned to lastOperation.
One component of this calculator which is lacking is an equal = button. To implement it would require changing the logic of the calculate() function.
As mentioned in the section on the properties of the form object, all the elements in a form can also be referenced by the elements[] array. For instance, you could create the following form:
<FORM METHOD=POST NAME=testform> <INPUT TYPE="text" NAME="one"> <INPUT TYPE="text" NAME="two"> <INPUT TYPE="text" NAME="three"> </FORM>
You can refer to the three elements as document.testform.elements[0], document.testform.elements[1], and document.testform.elements[2] in addition to the obvious document.testform.one, document.testform.two, document.testform.three.
This can be useful in situations where the sequential relationship of form elements is more important than their names.
In this example, you will take advantage of the elements[] array to build a simple dynamic multiplication table. The form will have 11 elements, the user fills in the first field to specify which
multiplication table to calculate, and the rest of the fields provide the one to ten multiplication table for that number.
Input
<HTML> <HEAD> <TITLE>Example 6.2</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function calculate(form) { var num=1; var number=form.number.value; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; form.elements[num].value = number * num++; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> Number: <INPUT TYPE=text NAME="number" VALUE=1 onChange="calculate(this.form);"><BR> x 1: <INPUT TYPE=text NAME="1" VALUE=1 onFocus="blur();"><BR> x 2: <INPUT TYPE=text NAME="2" VALUE=2 onFocus="blur();"><BR> x 3: <INPUT TYPE=text NAME="3" VALUE=3 onFocus="blur();"><BR> x 4: <INPUT TYPE=text NAME="4" VALUE=4 onFocus="blur();"><BR> x 5: <INPUT TYPE=text NAME="5" VALUE=5 onFocus="blur();"><BR> x 6: <INPUT TYPE=text NAME="6" VALUE=6 onFocus="blur();"><BR> x 7: <INPUT TYPE=text NAME="7" VALUE=7 onFocus="blur();"><BR> x 8: <INPUT TYPE=text NAME="8" VALUE=8 onFocus="blur();"><BR> x 9: <INPUT TYPE=text NAME="9" VALUE=9 onFocus="blur();"><BR> x 10: <INPUT TYPE=text NAME="10" VALUE=10 onFocus="this.blur();"><BR> <ITEM TYPE=button NAME="calculcate" VALUE="Calculate"onClick="calculate(this.form);"> </FORM> </BODY> </HTML>
Output
Listing 6.8 produces results similar to those in Figure 6.4.
Figure 6.4. Using the elements[] array, you can reference each field in order.
End of Output
Analysis
Notice in this script that you can refer to form elements by number. Because the elements[] array starts with an index of zero, you have made the first element (index zero) the entry field and start the multiplication table with element two (which has
an index value of one).
In the function calculate(), you use the variable num as a counter which starts at one. You use the following command 10 times to build the multiplication table:
form.elements[num].value = number * num++;
What this line tells you to do is assign the value of number * num to the current element and then increase num by one. This provides an excellent example of how to use the unary increment operator (++) to return the value of an expression and then
increase it by one.
Typically, you would not write the calculate function the way you have here. Instead, you would use a for loop:
function calculate(form) { var number=form.number.value; for(num = 1; num <= 10; num++) { form.elements[num].value = number * num; } }
for loops are covered in Chapter 7, "Loops."
While event handlers are generally designed to work with individual forms or fields, at times, it is useful to be able to reference forms in relationship to other forms on a page.
This is where the document.forms[] array comes into play. It would be possible to have multiple identical forms on the same page and have information in a single field match in all three forms. This could be more easily achieved using the
document.forms[] array than with form names. In this script, you have two text entry fields in separate forms. Using the forms[] array, you keep the value of the fields in each form the same when the user changes a value in one form.
<HTML> <HEAD> <TITLE>forms[] Example</TITLE> </HEAD> <BODY> <FORM METHOD=POST> <INPUT TYPE=text onChange="document.forms[1].elements[0].value = this.value;"> </FORM> <FORM METHOD=POST> <INPUT TYPE=text onChange="document.forms[0].elements[0].value = this.value;"> </FORM> </BODY> </HTML>
In addition to referring to forms numerically in the forms[] array, they can also be refereed to by name. Using the NAME attribute of the FORM tag, you can assign a name to a form:
<FORM METHOD=POST NAME="name">
Then, this form can be referred to as document.forms["name"] or as document.name.
Now you are going to put together some of the skills you have learned in this chapter in a different type of interactive form.
Usually, text entry forms consist of field names followed by fields. What you want to do is produce forms where the field name (that is, the prompt for the field) is the initial value of the field. This should look like the example in Figure 6.5.
Figure 6.5. Prompt information as a field's default value looks less cluttered on Landegg Academy's home page.
If the user clicks in an unchanged field, the field clears and the user enters information. If he moves the focus out of the field and hasn't entered any information, the original content reappears.
At the same time, if the user clicks in a field that contains data entered by the user, the field is not cleared.
This can be done by developing a general-purpose set of functions such as those in Listing 6.9.
Input
<HTML> <HEAD> <TITLE>Listing 6.9</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- HIDE FROM OTHER BROWSERS function clearField(field) { // Check if field contains the default value if (field.value == field.defaultValue) { // It does, so clear the field field.value = ""; } } function checkField(field) { // Check if user has entered information in the field if (field.value == "") { // User has not entered anything field.value = field.defaultValue; } } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST> <INPUT TYPE=text NAME="name" VALUE="Name" onFocus="clearField(this);" onBlur="checkField(this);"> <BR> <INPUT TYPE=text NAME="email" VALUE="E-mail Address" onFocus="clearField(this);" onBlur="checkField(this);"> <BR> <INPUT TYPE=text NAME="phone" VALUE="Phone Number" onFocus="clearField(this);" onBlur="checkField(this);"> </FORM> </BODY> </HTML>
Output
This script produces a form with three text entry fields that looks like Figure 6.6. If a user clicks in the "E-mail" field, the result is similar to Figure 6.7.
Figure 6.6. A form with prompt information as the default value for each field.
Figure 6.7. The clearField() function clears the content of a field if needed.
End of Output
Analysis
In Listing 6.9, you highlight the use of the defaultValue property. Using this you are able to build two simple functions, clearField() and checkField(), to handle all the work.
clearField() is called when the user places focus in a field. By comparing the current value of the field with the default value, the function decides if it should clear the field before the user
starts entering information.
Similarly, checkField() is called when the focus leaves a field. If the content of the field is blank then the default value is reassigned to the field.
In this chapter, you have taken the major step from simple scripts to complex, interactive Web page development using JavaScript.
By working with form elements and event handlers, you can write scripts that enable sophisticated user interaction. For instance, you can develop simple spreadsheets, complex calculators, and can perform error checking before sending forms to a server
for processing by CGI scripts.
Event handlers are specified HTML tags. Event handlers take as their values JavaScript code, usually in the form of a function call.
In order to step beyond the bounds of the simple sort of processes you have been scripting up to this point, in Chapter 7, you will take a detailed look at loops which provide you with increased control over the flow of a program.
Command/Extension |
Type |
Description |
blur() |
JavaScript method |
Emulates removing focus from a form element |
form.action |
JavaScript property |
String containing the value of the ACTION attribute of the FORM tag |
form.elements |
JavaScript property |
Array containing an entry for each element in the form (such as checkboxes, text fields, and selection lists) |
form.encoding |
JavaScript property |
String containing the MIME type used when submitting form data to the server |
form.name |
JavaScript property |
String containing the value of the NAME attribute of the FORM tag |
form.target |
JavaScript property |
String containing the name of window targeted by a form submission |
form.submit() |
JavaScript method |
Emulates the submission of an HTML form |
onSubmit |
Event Handler |
Event handler for the submission of an HTML form |
button |
HTML attribute |
Type attribute for HTML buttons (<INPUT TYPE=button>) |
checkbox |
HTML attribute |
Type attribute for checkbox toggle switches (<INPUT TYPE=checkbox>) |
password |
HTML attribute |
Type attribute for password text entry fields (<INPUT TYPE=password>) |
radio |
HTML attribute |
Type attribute for radio button toggle switches in forms (<INPUT TYPE=radio>) |
reset |
HTML attribute |
Type attribute for reset buttons (<INPUT TYPE=reset>) |
SELECT |
HTML tag |
Container tag for selection lists |
OPTION |
HTML tag |
Indicates options in a selection list (<SELECT><OPTION>Option 1<OPTION>Option 2</SELECT>) |
submit |
HTML attribute |
Type attribute for submit buttons (<INPUT TYPE=submit>) |
text |
HTML attribute |
Type attribute for text fields in forms (<INPUT TYPE=text>) |
TEXTAREA |
HTML tag |
Container tag for multi-line text entry field (<TEXTAREA>default text</TEXTAREA>) |
name |
JavaScript property |
String containing the name of an HTML element (button, checkbox, password, radio button, reset, submit, text, text area) |
value |
JavaScript property |
String containing the current value of an HTML element (button, checkbox, password, radio button, reset, selection list, submit, text, text area) |
click() |
JavaScript method |
Emulates clicking on a form element (button, checkbox, radio button, reset, selection list, submit) |
onClick |
JavaScript property |
Event handler for a click event (button, checkbox, radio button, reset, submit) |
checked |
JavaScript property |
Boolean value indicating if a choice is checked (checkbox, radio button) |
defaultChecked |
JavaScript property |
Boolean value indicating if a choice is checked by default (checkbox, radio button) |
defaultvalue |
JavaScript property |
String containing the default value of an HTML element (password, text, text area) |
focus() |
JavaScript method |
Emulates giving focus to an element (password, text, text area) |
blur() |
JavaScript method |
Emulates removing focus from an element (password, text, text area) |
select() |
JavaScript method |
Emulates selecting text in a field (password, text, text area) |
onFocus |
Event handler |
Event handler for a focus event (password, selection list, text, text area) |
onBlur |
Event handler |
Event handler for a blur event (password, selection list, text, text area) |
onChange |
Event handler |
Event handler for when the value of a field changes (password, selection list, text, text area) |
onSelect |
Event handler |
Event handler for when the user selects text in a field (password, text, text area) |
index |
JavaScript property |
Integer indicating the current choice from a group of choices (radio button, selection list) |
length |
JavaScript property |
Integer indicating the number of choices in a group of choices (radio button) |
defaultSelected |
JavaScript property |
Boolean value indicating if a choice is selected by default (selection list) |
options |
JavaScript property |
Array of options in a selection list |
text |
JavaScript property |
Text displayed for a menu item in a selection list |
TABLE |
HTML tag |
Container tag for HTML tables |
TR |
HTML tag |
Container tag for rows of an HTML table |
TD |
HTML tag |
Container tag for cells of an HTML table |
COLSPAN |
HTML attribute |
Attribute of the TD tag to indicate if a cell spans multiple columns |
ROWSPAN |
HTML attribute |
Attribute of the TD tag to indicate if a cell spans multiple rows |
BORDER |
HTML attribute |
Attribute of the TABLE tag to indicate the width of the borders in a table |
document.forms[] |
JavaScript property |
Array of form objects with an entry for each form in a document |
string.subtring() |
JavaScript method |
Returns a portion of the string based on being passed the indexes of the first and last character as arguments |
Math.floor() |
JavaScript method |
Returns the next integer value less than the argument |
|
|
|
Q: Can I dynamically change the text in a button or on a drop-
down SELECT list by assigning values to properties such as
button.value?
A: No. Once a page has been rendered, its appearance (outside
text fields and a few other exceptions) cannot be altered at
all.
Q: Is it possible to have an event handler, maybe onChange,
invoked with each keystroke as a user enters data in a text
field?
A: No; the onChange event handler only is invoked when focus
leaves the field. Currently, there is no way to trap and react
to individual keystrokes.
Input
<HTML> <HEAD> <TITLE>Exercise 6.2</TITLE> <SCRIPT> <!-- HIDE FROM OTHER BROWSERS var total = 0; var lastOperation = "+"; var newnumber = true; function enterNumber(digit) { var form = digit.form; if (newnumber) { clearNumber(form); newnumber = false; } form.display.value = form.display.value + digit.name; } function clear(form) { total = 0; lastOperation = "+"; form.display.value = 0; } function clearNumber(form) { form.display.value = 0; } function calculate(operation) { var form = operation.form; if (checkErrors(form)) { var expression = total + lastOperation + form.display.value; lastOperation = operation.value; total = eval(expression); form.display.value = total; newnumber = true; } else { alert("You cannot divide by zero!"); form.display.value = ""; } } function changeSign(form) { var num = eval(form.display.value); form.display.value = -num; if (newnumber) total = -num; } function decimalPoint(form) { if (Math.floor(form.display.value) == form.display.value) { form.display.value += "."; } } function checkErrors(form) { noErrors = true; if ((lastOperation == "/") && (form.display.value == 0)) noErrors = false; return noErrors; } // STOP HIDING FROM OTHER BROWSERS --> </SCRIPT> </HEAD> <BODY> <FORM> <TABLE BORDER = 1> <TR> <TD COLSPAN=4> <INPUT TYPE=text NAME=display VALUE="0" > </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="7" VALUE=" 7 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="8" VALUE=" 8 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="9" VALUE=" 9 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="+" VALUE=" + " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="4" VALUE=" 4 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="5" VALUE=" 5 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="6" VALUE=" 6 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="-" VALUE=" - " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="1" VALUE=" 1 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="2" VALUE=" 2 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="3" VALUE=" 3 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="*" VALUE=" * " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="0" VALUE=" 0 " onClick="enterNumber(this);"> </TD> <TD> <INPUT TYPE=button NAME="C" VALUE=" C " onClick="clear(this.form);"> </TD> <TD> <INPUT TYPE=button NAME="CE" VALUE="CE" onClick="clearNumber(this.form);"> </TD> <TD> <INPUT TYPE=button NAME="/" VALUE=" / " onClick="calculate(this);"> </TD> </TR> <TR> <TD> <INPUT TYPE=button NAME="sign" VALUE="+/-" onClick="changeSign(this.form);"> </TD> <TD> </TD> <TD> <INPUT TYPE=button NAME="decimal" VALUE=" . " onClick="decimalPoint(this.form);"> </TD> <TD> </TD> </TR> </TABLE> </FORM> </BODY> </HTML>
Output
This script produces a calculator that looks like the one in Figure 6.8.
Figure 6.8. Two buttons and three functions added to the calculator.
End of Output
Analysis
There are several points worth noting in this new version of the calculator program. First, you make use of the unary negation operation (-) in the changeSign() function.
In the decimalPoint() function, you check if the number is currently a floating point value by using the Math.floor() method. Only an integer evaluates to itself using Math.floor() and only integers lack a decimal point (in this particular case). It is
important to note that this method isn't foolproof. A user could still enter two decimal points in a row.
You can handle this by using the substring() method of the string object to check if the last character of the display field is already a decimal point. The substring() method takes two arguments as follows:
stringname.substring(firstCharacter,lastCharacter)
where firstCharacter and lastCharacter are the numeric offset of the desired characters from the start of a string. The numeric offset is calculated based on the first character being number zero. So, if you have a variable called
testString with the value "JavaScript", then testString.substring(1,4) returns a value of "avaS".
Of course, in this example, you don't know the numeric offset of the last character in form.display.value. You can find this out by using the string.length property. Now you can test if the last character is a decimal point using the expression:
(form.display.value.substring(form.display.value.length,form.display.value.length) == ".")
Then, the decimalPoint() function would look like this:
function decimalPoint(form) { var lastChar = form.display.value.length; var display = form.display.value; if ((Math.floor(form.display.value) == form.display.value) || (display.substring(lastChar,lastChar) == ".")) { form.display.value += "."; } }
The last function you added to your script is checkErrors(). In this script you simply check if the last operation is divide and the current value is zero, and then you alert the user and disallow the operation.