Previous Page TOC Index Next Page Home


6

Creating Interactive Forms

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

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.

Properties of the form Object

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

target

String containing the name of window targeted by a form submission

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.

The action Property

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".

The elements Property

This property is covered in more depth later in the section about the elements[] array.

The encoding Property

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
The name Property

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".


Using named forms is especially useful in documents with multiple forms where the JavaScript scripts must work with all the forms in the document.

The target Property

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".


The TARGET attribute is particularly useful in the context of frames, which we discuss in Chapter 8, "Frames, Documents, and Windows."

Methods of the form Object

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>

Event Handlers for the form Object

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>

Working with Form Elements

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">)

textArea

A multiline text entry field (<TEXTAREA>default text</TEXTAREA>)

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.

The button Element

In standard HTML forms, only two buttons are available—submit and reset—because 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>

The checkbox Element

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)

click()

Emulates a click in the checkbox (method)

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

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

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

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)

click()

Emulates a click in the checkbox (method)

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>

Analysis

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.

End of Analysis

The reset Element

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.


A bug in the current version of Navigator results in odd behavior with the RESET button: When text fields are cleared by the RESET button, this isn't reflected into the corresponding element until the field is given focus.

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>

Analysis

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.

End of Analysis

The select Element

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 onChange—the same as for the text object.


In the current version of JavaScript (in Navigator 2.0), the onChange event handler is not invoked immediately after the user changes his selection. Rather, once the user leaves the selection list (that is, removes focus from the list), then the onChange event handler works.

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 Element

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.

The text Element

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)

select()

Emulates selecting text in 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>

In current versions of Navigator 2, the onChange event handler is not invoked as soon as the user types a change. Rather, it is invoked when focus leaves the field, and the text has changed.

The textarea Element

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.

Using Tables to Create a Calculator

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.


A more detailed discussion of HTML tables is available at Netscape's Web site at the URL http://home.netscape.com/assist/net_sites/tables.html.

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.

End of Analysis

The elements[] Array

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.

Building a Multiplication Table

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."

End of Analysis

The forms[] Array

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.

Prompting with Text Fields

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.

End of Analysis

Summary

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.

Commands and Extensions Review

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

string.length

JavaScript property

Integer value indicating the index of the last character in a string


The Math.floor() and string.substring() methods will be used in the exercises later in this chapter. More details about the use of these methods will be discussed at that time.

Q&A

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.


This capability is expected to be included in the next release of Netscape Navigator.

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.


Note: This capability is expected to be included in the next release of Netscape Navigator.

Exercises

  1. Which of these HTML tags are valid?

    a. <FORM METHOD=POST onClick="go();">

    b. <BODY onLOAD="go();">

    c. <INPUT TYPE=text onChange="go();">

    d. <INPUT TYPE=checkbox onChange="go();">

    e. <BODY onUnload="go();">

    f. <INPUT TYPE=text onClick="go();">

  2. Take the script from Listing 6.7 (the calculator program) and extend it to add the following:

    A positive/negative toggle button (that is, click on the button and the currently entered number changes sign).

    A decimal point button so that the user can enter floating point numbers.

    Check for errors as the user performs actions; specifically: check that the user is not trying to divide by zero and the user does not enter two decimal points (if the user divides by zero, display a warning, and don't perform the action; if the user enters a second decimal point, ignore it).

  3. Extend the functionality of Listing 6.9 to optionally check if entered information is in a specific numeric range and, if not, to warn the user.

Answers

  1. The following are valid: (c) and (e). Example (a) is not valid because onClick is not a valid event handler for the BODY tag; (b) is wrong because JavaScript is case sensitive and the correct form is onLoad; (d) is incorrect because checkboxes only have the onClick event handler; and (f) is incorrect because the onClick event handler is not available for text fields.

  2. In the following script, you can add three functions to implement the additional features:

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.

  1. In order to extend the functionality to include the optional range checking and alert, you need to add an additional function:


    function checkRange(field,low,high,message) {

    if (field.value != "") {
    if ((field.value < low) || (field.value > high)) {
    alert(message);
    field.value="";
    field.focus();
    }
    } else {
    checkField(field);
    }

    }

    This function first checks if the user has entered information. If she has, it checks the range; if the information is outside the range, the function alerts the user, clears the field, and returns focus to the field.

    If there is no data entered, the function calls checkField(), which displays the default value in the field.

Previous Page TOC Index Next Page Home