Although HTML pages can be difficult to develop, they are usually very simple to use. The number of things you can do with an HTML page is quite limited. For the most part, you simply look at it-read its text, admire its graphics, and, perhaps, listen to the sounds it can play. For many, the Web experience consists of visiting a series of pages without interacting with them. The only interaction occurs when the user selects a link or clicks an imagemap.
HTML forms have gradually changed that model to increase the level of interaction. A form can have a variety of ways of accepting input, including text fields, buttons, check boxes, and multiple choice selections. In this way, HTML forms are a lot like paper forms. The user fills in the form, perhaps to purchase some item, and then submits the form. This submission process also mimics real life. It is difficult to tell whether the form has been properly filled in, and the time taken for processing the form is often quite lengthy. In the case of HTML, this processing delay occurs because the contents of the form must be sent across the network to some URL, processed there, and then returned to the user. Even the slightest error causes the form to be rejected, so that the form entry must be repeated.
One of the primary goals of JScript is to localize most of this process and perform the form validation within the user's browser. It won't be possible actually to submit an order locally, but it will be possible to make sure that the form is properly filled out locally, and thereby avoid forcing the user to redo the form. JScript realizes this goal through event handlers. Event handlers are JScript statements (usually functions) that are called whenever something happens. JScript functions can be called when a form is submitted, or they can be called whenever the user does anything to the form. If your form requires that a certain field correspond to a number between 2 and 10, for example, you can write a JScript function that will validate that field when the user changes it, and complain if the value is out of range.
This chapter describes event handling in JScript. We discuss all the events that can be handled, as well as the contexts in which these events may arise. In addition, you learn how JScript can be included within Web pages, and how JScript functions are connected with different components of that page.
To understand JScript's event-handling model, you must first think about the set of things that can actually happen on a Web page. Although there are many different things you can do with the browser, most of these have nothing to do with Web navigation. When you save a page as text, print a page, or edit your favorites list, you are not actually navigating the Web. In these cases, you are using some of the graphical capabilities of the browser, which are independent of the Web.
To understand which browser actions correspond to JScript events and which do not, it is important to distinguish those actions that actually cause (or might cause) some change in the Web page being displayed. From the user's standpoint, the number of such actions is actually quite limited. In fact, there are really only two types of top-level actions: The user can navigate, or the user can interact with an element of an HTML form. Navigation means to change from one Web page to another, or perhaps to open a completely new page in a new window. Interaction with the contents of an HTML form means activating one of the elements in that form (clicking a button) or changing one or more of the elements in such a form that can be changed (editing a text field).
In the navigation category, you can distinguish the following actions:
In most of these cases, the current page will be unloaded, which means it will no longer be visible in any browser window. In several of these cases, a new page will be loaded, which means its contents will be displayed in a browser window, perhaps a new one created specifically to display this particular page. Anyone who has used the World Wide Web realizes that selecting a hypertext link may not successfully take you to another. The machine to which that link points may be down or simply inaccessible. The link may even be dead, meaning that it does not point to a valid destination. Selecting an inaccessible or dead link may unload the current page without loading a new page. Internet Explorer typically displays a blank page or posts an error message. You may or may not be left on the current page, depending on the type of error. A sample error alert from IE is shown in Figure 3.1.
These events, loading and unloading a page, are the two document-level events that can be handled by JScript. This means that it is possible to write JScript code, contained within the HTML definition of a page, that will be executed whenever that page is loaded. You can also have code that is executed whenever that page is unloaded. It is important to realize that loading and unloading are two separate, unrelated events. For example, when you attempt to activate a link that leads to a nonexistent or blank page, the current page is unloaded, but nothing is loaded in its place. In order to return to the last valid Web page, you must use one of the navigation controls. For example, if you select Back in Internet Explorer, the last page you visited is reloaded.
There are two additional events that are vaguely related to navigation. These events are the following:
When you move the mouse over a hypertext link, a mouseOver event is generated. This event is not associated with clicking the link; it is associated with being poised to click it. This event can be used to give the user feedback, such as changing the color of the link or flashing it. The final event is the mouseMove event. This event is a Microsoft-specific extension of the mouseOver event. It also occurs when you move the mouse over a hypertext link. The difference is that this event can be used to provide more information about the event, such as the current position of the mouse.
We have now discussed the events that arise if you are using the browser to navigate the Web. Of course, you can also interact with your browser through the elements of an HTML form. Every form element that permits input is associated with one or more JScript events. We can broadly characterize the possible components of an HTML form as follows (Chapter 6 "Interactive HTML Objects," has a section on "Review of HTML Forms"):
The first three components are standard parts of HTML. The final
component, an embedded object created using the OBJECT
tag, is a more recent addition that allows the Web page designer
to embed a variety of active elements into an HTML page. For the
moment, we will concentrate on the first three items on this list.
See Chapter 12, "Scripting and ActiveX," for more information on embedded objects and the ActiveX technology, p. 341. |
Button Elements in Forms. Buttons come in five varieties, as follows:
Simple buttons are defined using the HTML <INPUT
TYPE="button">. Check boxes define options,
which are either off (not checked) or on (checked). These are
created using an <INPUT TYPE="checkbox">
directive. Option buttons use the <INPUT
TYPE="radio"> directive, and permit the
user to select exactly one of a set of choices. Submit buttons
and reset buttons are very special. Submit buttons, created by
<INPUT TYPE="submit">,
are used to end input operations on a form. When the Submit button
is pressed, the contents of the form are packaged and sent to
the URL target specified in the ACTION
attribute of the <FORM>
definition. Reset buttons bring the form back to its initial state,
wiping out any input the user has performed; they are specified
as <INPUT TYPE="reset">.
Figure 3.2 shows a simple HTML form with all five button types;
it was generated by the HTML file ALLBUT.HTM.
Tip |
Hidden fields on HTML forms do not generate JScript events. |
Figure 3.2 : All five types of HTML buttons have corresponding JScript events.
The one thing the five types of buttons have in common is that you click the button to achieve its effect. Because this is an extremely common action, the JScript event model defines click as one of its HTML form events. This event is generated by each of the five button types. In addition, when a form is actually submitted, a submit event is generated. The submit event is really owned by the form being submitted, and not the Submit button that causes it.
Text Elements in Forms. There are three types of text items possible within an HTML form, as follows:
Single-line text fields are created with an <INPUT TYPE="text"> directive. Any text you type in a text field is displayed as you type it. This behavior is known as echoing the input. Single-line text fields that are created using <INPUT TYPE="password"> do not echo their input. Multiline text fields are created with the TEXTAREA tag, and are usually called textareas. An HTML form showing all three types of text elements is shown in Figure 3.3, created from the file ALLTXT.HTM. Interacting with text is more complex than interacting with a button. There are more things you can do with text. You can click in the text field, enter text, edit text, select text, and decide you are finished with the text and move on.
Figure 3.3 : HTML text elements generate several different JScript events.
What are the events JScript generates in response to these various
actions? JScript uses a text manipulation model that will be familiar
to anyone who has ever used a windowing system. It defines four
events that are associated with text fields and textareas, but
not passwords fields-change,
select, focus,
and blur. The first two should
be self-explanatory. The change
event is generated whenever any text is changed, and the select
event is generated whenever text is selected. Selecting text is
more than simply clicking in the editable text field or textarea.
It means actually highlighting a portion of the text with the
mouse or arrow keys.
Note |
Password fields do not generate JScript events. This was a conscious design decision to prevent malicious script code from diverting password text. |
The events focus and blur are a little more involved. A text field or textarea is said to have focus when it is currently accepting input typed at the keyboard. Clicking anywhere inside a text item is certain to give it focus, and simply moving the mouse over the text field may do so, as well. blur is the opposite of focus. blur occurs when the text item no longer has focus. This may happen because some other item now has the focus, or because the focus has simply been lost. You will notice that if you position the mouse over a graphic (other than an imagemap), you can type until your fingers are sore, but nothing happens. This is a case where nothing has focus.
Selection Elements in Forms. Selection lists are defined
by the SELECT tag; their
options are enumerated using the OPTION
tag. They operate almost the same as text items; they are capable
of generating focus, blur,
and change events. Paradoxically,
selection lists do not generate select
events. You might well wonder why four event types are needed
for text and three for lists. This is clarified later in this
chapter. Figure 3.4 summarizes the events understood by JScript
and the HTML elements that generate them.
The topic of text events is covered in much greater detail in Chapter 6 "Interactive HTML Objects," particularly in the section on "Manipulating Text Fields," p. 163. |
Figure 3.4 : JScript events model different types of user interaction with a Web page.
Anything not mentioned in the previous two sections should be considered an action, not a JScript event. Scrolling a window, reading newsgroups, or answering mail are certainly actions, but they are not events. Using the Back, Forward, or Home buttons on Internet Explorer's toolbar are not really JScript events, but they ultimately result in JScript events being delivered to the current page, because they unload the current document. Creating an entry in the favorites list (hotlist) is not even remotely related to JScript events, because it does not affect the current page at all. How does one distinguish actions that might possibly be events from those that are not? The rule is that if an action affects or changes the current page, it is associated with one or more JScript events.
It might be argued that scrolling or resizing a window affects the current page, and should therefore result in some kind of event. Those of you who have programmed any kind of windowing system know these are often called visibility, or window damage, events. JScript takes a more literal definition of a page. No matter how much or how little of a Web page is visible, it is still the same page. Even if you read only the cartoons in The New Yorker, the articles are still there, unchanged.
So far, we have talked about JScript as a language, and we have talked a bit about HTML, but we have not talked about how JScript is used in HTML. Event handlers are the glue that link HTML elements with JScript code, but how is it done? This section addresses this question. The answer has two parts: how JScript is included or referenced in a Web page, and how event handlers are attached to HTML items.
In the most general sense, every Web page is constructed from HTML statements that divide the page into two parts: the <HEAD> and the <BODY>. The HTML directives within the context of the <HEAD> give information about the page, while those in the <BODY> make up the page itself. In most simple HTML documents, the <HEAD> usually contains only the <TITLE>. It can also contain a BASE tag which specifies a pathname that should be used to resolve relative HREFs within the document, and one or more LINK tags, which indicate the relationship of this document to one or more other documents, such as the browser's home page.
The HEAD section of an HTML document can also be used to contain the JScript code for your event handlers. While it is not absolutely necessary for all JScript code to go with the <HEAD>...</HEAD> delimiters, it is an excellent idea because it ensures that all JScript code has been defined before any of the <BODY> of the document is seen. In particular, if the document has a handler for the load event, and that event was triggered before the event handler code had been read, an error would result because the event-handler function would be undefined.
Syntax of the SCRIPT Tag. JScript code is introduced with the SCRIPT tag. Everything between this tag and the closing /SCRIPT tag is assumed to be some kind of client-side script code such as JScript. The syntax for the SCRIPT tag is:
<SCRIPT LANGUAGE="LangName" [SRC="URL"]>
The element LangName gives the language that is used in the subsequent script code; this should be JavaScript. Internet Explorer will also accept JScript and VBScript (for scripts written in the Visual Basic Scripting language). For maximum portability, you should specify your script language as JavaScript. This will give it a fighting chance of running on other browsers that support some version of JavaScript such as Netscape Navigator.
If the SRC attribute is specified, it should reference an URL containing code in the script language. For JScript, this should be a valid URL for a file containing the JScript code. The file name should have the suffix .JS. If the SRC attribute is given, then the <SCRIPT> can be immediately terminated by a </SCRIPT> directive. A <SCRIPT> block that loads JScript code from a file named CLICK.JS in a directory jscode relative to the document base would look like this:
<SCRIPT LANGUAGE="JavaScript" SRC="jscode/click.js"> </SCRIPT>
If the SRC attribute is not
given, it is expected that all the code between <SCRIPT>
and </SCRIPT> is the
script source itself. In the glorious future, when the overwhelming
majority of browsers understand the SCRIPT
tag, or at least benignly ignore it, the JScript source may be
given literally. Until then, it is recommended that source included
between <SCRIPT> and
</SCRIPT> be enclosed
within the HTML comment delimiters <!--
and -->. A simple example
showing a single JScript function is shown in Listing 3.1.
Caution |
Use the C-style comments // and /* */ inside JScript code. Never use HTML comments inside JScript. |
Listing 3.1 A JScript <SCRIPT> with a Single Function
<SCRIPT LANGUAGE="JScript"> <!-- function dontclickme() { // an ominous button click handler alert("I told you not to click me"); return( false ); } <!-- end script --> </SCRIPT>
Use of HTML Comments. The function in Listing 3.1 does not do much; it merely uses the alert() function to pop up a warning dialog box with its argument as the message. Presumably, this function is the click event handler for a button you don't want the user to press. The important thing to notice about this simple example is the paradoxical but important use of HTML comments. The entire script body is enclosed with a comment, and the comment close --> is also paired with a second, seemingly redundant, comment start <!-- on the last line. At present, you should structure your script according to the following rules:
It is also possible to terminate the script code with a line like
//Æ,
but the preceding method suggested is a bit more general. You
should use this magic incantation not because it makes sense,
but because it works. Note that JScript code referenced through
an SRC URL should also follow
these rules, as if it had literally been included in the <SCRIPT>
block. Note also that you may have both a JScript SRC
URL and literal JScript between <SCRIPT>
and </SCRIPT>. In this
case, the URL referenced by the SRC attribute is read and processed
before the literal JScript.
Caution |
HTML comments are one of the least conforming areas of HTML. Most browsers deviate a little from the HTML standards, and some deviate a lot. The preceding comment rules may change in the future, and may be implemented differently on different browsers. |
Processing <SCRIPT> Code. There are two important aspects to JScript code defined by or within a SCRIPT block. The first important principle is that this JScript code is not executed-it is merely read and checked for syntax errors. When the browser sees the code shown in Listing 3.1, it does not execute the dontclickme() function, it merely recognizes that this function is a JScript function, and saves the definition of that function for later use. This is precisely the opposite behavior of normal HTML. When you say <HR> in an HTML document, you get a horizontal rule. You don't get it immediately, but you do get it when the browser has finished laying out the page (assuming that there are no HTML errors, of course).
This is the way that most interpreted languages work, however. If you create a Sub in BASIC, a defun in LISP, or a proc in TCL, it is not executed when it is read. Instead, the interpreter parses it, which means that it scans through the function looking for obvious syntax errors, such as unbalanced parentheses, and records the function's definition for later use. The function is used only when it is called. In JScript, functions are most often called by events.
Binding in JScript. Another critically important aspect of JScript is that it carries out dynamic binding. Binding refers to the way in which names of things, such as variable names, function names, and object names, are associated with the things themselves. If you call the function dontclickme from Listing 3.1 by saying dontclickme(), you are not actually referring to the function itself; you are referring to the name of the function. "The Song of the Volga Boatmen" is really the name of that song; it is not the song itself. If you want the sheet music, you go to your favorite music store and ask for it by name; most people do not go in and begin singing, "Eh-eh uxhnyot "
There are two general approaches to binding: static binding and dynamic binding. Many languages, particularly compiled languages such as C, C++, and Java, often insist on static binding. This means they require that they be able to find all named references when a program is compiled. (Of course, with the advent of dynamically loaded libraries, this rule was relaxed a bit.) JScript uses the more liberal form, dynamic binding. JScript attempts to resolve names only when they are used.
Dynamic binding has several consequences. In the first place,
if the function dontclickme()
is never called, then it can contain all but the most hideous
syntax errors and they will never be found. If dontclickme
is the event handler for a button, and no one ever presses the
button, its problems are never exposed. Even if dontclickme()
is absolutely perfect, but the event handler is erroneously declared
to be a function named noclickme(),
this mismatch will not be detected until someone finally chooses
to press the button. JScript will only then try to find a function
named noclickme(). It will
fail, and an error will result. Dynamic binding is often called
runtime binding or late binding, because the binding
process takes place only when the JScript interpreter attempts
to run the code.
Tip |
Always check meticulously to ensure that the function, object, and variable names used in HTML match those in the JScript code. |
Dynamic binding has its advantages and disadvantages. Dynamic binding is used by many interpreters because it simplifies the language, and makes it very easy to add in new functions. Since there is no brooding and melancholy compiler to satisfy, it is possible to build up a complex JScript application incrementally. Even if you really need an event handler for every possible event, you can start out with one or two handlers, make them work, and then gradually add more complexity.
The disadvantage of dynamic binding should be clear from the previous discussion. There is very little error-checking. When the JScript interpreter is reading all the code in the SRC URL, or processing the code between <SCRIPT> and </SCRIPT>, it is performing some checking but it is by no means performing an exhaustive analysis of the code. Errors, particularly mismatched names, are not found until the erroneous code is executed. To see a more complete example of this, look at the HTML page defined in Listing 3.2.
Listing 3.2 ex32.htm-An Illustration of Dynamic Binding
<HTML> <HEAD> <TITLE>A Potentially Dangerous JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-- function dontclickme() { // button click handler alert("I told you not to click me"); } <!-- end script --> </SCRIPT> </HEAD> <BODY> <FORM METHOD="POST" ACTION="mailto:me@myhost.com"> <INPUT TYPE="button" NAME="mycheck" VALUE="HA!" onClick="dontclickme()"> </FORM> </BODY> </HTML>
If you copy this code, found in EX32.HTM in the directory for Chapter 3on the CD-ROM, into a local file, change the e-mail address in the form's ACTION to your own e-mail address, and then read that file into your browser, everything will be fine. Notice that the click event handler for the button is declared using the HTML attribute onClick="dontclickme()", which tells JScript that when this button is pressed, the function dontclickme should be called. (The exact syntax for declaring event handlers is discussed in the next section.) If you now click that button, you should see something like Figure 3.5.
Figure 3.5 : Clicking an HTML button invokes a JScript event handler that displays an alert.
So far so good. The name of the event handler in the HTML statement that created the button matches the name of a JScript function in the SCRIPT block. Now try the following experiment. Change the handler declaration from:
onClick="dontclickme()"
to
onClick="noclickme()"
and then read that file into your browser. You will notice that the initial appearance of the HTML page is exactly as before. No errors have been reported. If you attempt to click the button labeled HA!, your browser reports an error, and the alert dialog box shown in Figure 3.5 does not appear. This is dynamic binding at work. JScript did not know that the function named noclickme does not correspond to any currently defined function until the user action forced it to try to find one. Technically, the function name noclickme is said to be unbound.
It might seem that dynamic binding is a great potential source
of error without providing many benefits as compensation. As you
will see when we discuss objects in Chapter 4 "JScript Objects,"
objects may be defined and even modified on-the-fly. Dynamic binding
allows you to refer to things that do not yet exist, but that
will exist when the event handler that uses them is actually called.
Dynamic binding, like the loose typing provided by JScript's var,
is a two-edged sword. It must be used with care, but is very powerful.
See the "Defining Your Own Objects: The new Statement" section of Chapter 4 "JScript Objects," for more information on creating and modifying JScript objects, p. 87. |
Let's summarize these two critical points about JScript parsing and execution, because they will dominate our thinking for several chapters to come:
JScript names are resolved when they are executed, not when they are parsed.
The previous section demonstrated that JScript functions are executed only in response to events. We also know that events themselves occur only when some interaction with or change to the current HTML page occurs. There must be a way in which we can link events to JScript functions in HTML. In fact, we have already seen one such example of this in Listing 3.2. The mechanism is known as the event-handler declaration.
Event-handler declarations look exactly like ordinary HTML attributes. Each attribute name begins with the word on and is followed by the event name, so that onClick is the attribute that would be used to declare an event handler for the click event. The full declaration of an event handler looks like this:
onEvent="jscriptcode"
Attribute names are not case-sensitive, following the usual HTML convention. It is good practice, however, to use the coding style shown in the preceding line of code, with on in lowercase and the event name with an initial capital. This helps to distinguish it from other attributes, which are often fully capitalized.
The value of the attribute is a set of JScript code. The code may be included literally (known as inline JScript) or it may reference a JScript function. We can completely remove the dontclickme() function of Listing 3.2 and write the button statement as:
<INPUT TYPE="button" NAME="mycheck" VALUE="HA!" onClick="javascript:alert('I told you not to click me');">
This has two disadvantages. First, it tends to lead to very long
HTML statements. There is very little you can accomplish in only
a few characters. If you have hundreds of characters between the
opening (<) and the closing
(>) of an HTML statement,
it will almost certainly be very hard to read, and, if it is too
long, may cause your browser to choke. It is also not modular.
As you add event handlers for different HTML elements, you may
well find that there is a lot of common code. Each of the button
handlers might use a variation of the same code. Such common code
should always be encapsulated in a JScript function, rather than
being repeated in several places.
Tip |
Declare all event handlers as JScript functions. Avoid inline JScript code. |
One thing to notice about this example is the fact that the value of the onClick attribute is a quoted string. This follows standard HTML convention. Therefore, to include a string within the value of the attribute, we must alternate '' quotes with "" quotes. This follows the JScript standard for strings, as we learned in the "Implicit Data Types in JScript" section of Chapter 2 "JScript: The Language." If you modify the dontclickme function to accept a string argument, you must carefully use quotes when passing in literal strings. Listing 3.3 shows a modified version of dontclickme, called donteventme, and the HTML event-handler declarations that reference it. It can be found in the file ex33.htm on the CD-ROM.
Listing 3.3 ex33.htm-A JScript Function Can Be Shared by Several Event Handlers
<HTML> <HEAD> <TITLE>An Uncooperative JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-- function donteventme( str ) { // generic diffident handler alert("I told you not to " + str + " me"); } <!-- end script --> </SCRIPT> </HEAD> <BODY> <FORM METHOD="post" ACTION="mailto:me@myhost.com"> <BR>No<INPUT TYPE="checkbox" NAME="mycheck" VALUE="HA!" onClick="donteventme('click')"> <SELECT NAME="mysel" onChange="donteventme('change')"> <OPTION SELECTED>Nope</OPTION> <OPTION>Not Me</OPTION> <OPTION>No Way</OPTION> </SELECT> </FORM> </BODY> </HTML>
In this example, the function donteventme is called whenever the check box is checked or any selection is made on the selection list. The alert function within the donteventme constructs an uncooperative message based on the function's string argument str. Although this example accomplishes no useful work, it is a perfect template for a JScript page. In general, a JScript page has the following three components:
You now know how to declare event handlers in general. The next
section shows exactly which handlers can be associated with specific
HTML tags, and gives various examples of how these event handlers
are used.
Caution |
If you use the HTML IMG directive without assigning values to its WIDTH and HEIGHT attributes, event handling may be compromised. This limitation exists in Internet Explorer and Netscape Navigator. Make certain that you always include these attributes if you are using images together with JScript. |
JScript events occur at three levels-at the level of the entire Web document, at the level of an individual <FORM> within the document, and at the level of an element of a <FORM> within that document. At the same time, any particular element at any of these three levels may result in more than one event. For example, you have already seen that text items can generate up to four different events, depending on how they are manipulated. In this section, we examine each level and see which handlers are appropriate for the HTML elements within that level. As you might suspect, most of the action is at the lowest level, within HTML forms.
The HTML BODY tag is the container that holds the descriptive content of an HTML page. Just as the material in the HEAD section is about the page, the material between <BODY> and </BODY> is the page. The BODY tag can contain two event-handler declarations using the onLoad and onUnload attributes. A JScript page might have a BODY declaration that looks like this:
<BODY onLoad="loadfunc()" onUnload="unloadfunc()">
The onLoad="loadfunc()" attribute declares a JScript handler that will handle the load event. The load event is generated after the entire contents of the page, namely the HTML between <BODY> and </BODY>, have been read, but before they have been displayed. The onLoad event handler is an excellent place to perform any one-time initialization. It can also be used to display a splash screen containing company, product, or copyright information. It can even launch a security dialog box that permits only authorized users, with an appropriate password or key, to completely load the page.
The onUnload="unloadfunc()" attribute declares an event handler that is invoked whenever the page is unloaded. This happens when the user executes any action that brings up a new page in the same browser window. An unload event does not occur if a new page is opened in a new window. Even if a new page is not successfully loaded, the current page may still be unloaded, and the unloadfunc is called in that case. An onUnload event handler can be used to ensure that there are no loose ends, and to perform any cleanup necessary. For example, if the user has filled out a form, but has failed to press the Submit button, the onUnload handler should inform the user of that fact. It could even submit the form itself, based on the user's response. Note that both the onLoad and onUnload handlers are optional.
There are two final document-level event handlers, although they
are not associated with the BODY
tag. Any HTML link can declare an event handler for the mouseOver
or mouseMove events, which
both occur when the user places the mouse over the HREF
of that link. This can be used to achieve a visual effect or to
perform some special processing before the user actually tries
to access the link. Listing 3.4 shows a slightly fanciful example.
This code can be found in the file ex34.htm on the CD-ROM.
Caution |
In the current implementation of JScript, links have event handlers, but anchors do not. This means that you must catch navigation events by attaching event handlers to links. If any of your links point to anchors in the same document, the event must be handled at the link, not at the anchor. |
Listing 3.4 ex34.htm-Using the mouseOver Event to Mediate Access
<HTML> <HEAD> <TITLE>A Nationalist JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-- function warnthem( lnk ) { // mouseOver event handler var theirhost = lnk.hostname; // 2; get hostname of link var domain = "", lastdot = 0, len = 0; len = theirhost.length; // 4; string length of hostname lastdot = theirhost.lastIndexOf("."); // 5; find last dot domain = theirhost.substring(lastdot+1, len); // 6; last part of hostname if ( domain == "zz" ) { // 7; warn about country "zz" alert("Country zz only has 1200 baud modems"); } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> Check out the new links to <A HREF="http://home.std.zz" onMouseOver="warnthem(this)">Zzland</A> and its neighbor <A HREF="http://home.xyzzy.xy" onMouseOver="warnthem(this)">XYville</A> <HR> </BODY> </HTML>
This HTML creates a page with two elements-links to the fictitious
home pages of the countries Zzland
and XYville, and sets up
a mouseOver event handler
for those links. Note that the event handler function warnthem
is called with an argument this:
The special keyword this
is used to refer to the current JScript object. When the warnthem
function is called, its parameter lnk
is filled in with the object that represents the link over which
the mouse just moved.
The this keyword and other object-oriented concepts are discussed in Chapter 4 "Jscript Objects," in the section, "Defining Your Own Objects: The new Statement," p. 85. |
Statement 2 extracts the hostname part of that object, which in this example could be either home.std.zz or home.xyzzy.xy, depending on where the mouse is located. The next three statements use some of the string object functions (see "String Content Methods," in Chapter 4 "Jscript Objects") to tear off the last part of this fully qualified hostname, namely zz or xy, and save it in the variable domain. This variable is then tested against zz in statement 7. If the test passes, an alert is put up to warn the user that the connection to the zz home page will take longer due to slow modems. Links can also have click event handlers, so this code can be modified not only to warn the user, but also to abort the connection, if necessary. The result of placing the mouse over the Zzland link is shown in Figure 3.6.
Figure 3.6 : JScript event handlers can be used with any hypertext links.
The mouseMove event is almost identical to the mouseOver event. The only difference between the two is that the event handler for a mouseMove event is called with four arguments: the current state of the SHIFT key, which buttons are currently pressed, and the x and y coordinates of the mouse. Unfortunately, this event cannot be easily used with the type of HTML elements we have described so far. Its usage will be more fully discussed in Chapter 13, "More About ActiveX."
The FORM tag is used to begin the definition of an HTML form. It includes attributes from the METHOD to be used in submitting the form and the ACTION to be taken, and may also include a single type of event handler attribute, the onSubmit attribute. The syntax for a FORM tag is the following:
<FORM NAME="formname" ... onSubmit="return submithandler()">
Tip |
Put event handler attributes last on the attribute list of an HTML tag. This makes them easy to find and modify during debugging. |
The onSubmit handler is invoked
when the form's contents are about to be submitted. This is a
top-level action that applies to the entire form. It is also possible
to specify an onClick action
on the Submit button in a form, as you shall see in the section,
"Button Click Events." The natural use for an onSubmit
handler is to validate the contents of a form. The submission
proceeds if the contents are valid, and is canceled if they are
not.
Caution |
In order to use a submit handler to cancel a submission, it is essential to use the word "return" before the submit handler's name, as shown earlier. If the "return" is omitted, the submit handler will be called, but the form will always be submitted. |
Listing 3.5 (file ex35.htm on the CD-ROM) shows a very simple form with a single element, an editable text field. The value of the field is supposed to be a number between 1 and 9. The submit handler function checkit is called when the form is submitted. It validates the user-entered quantity and acts accordingly.
Listing 3.5 ex35.htm-Form Content Can Be Validated Using an onSubmit Handler
<HTML> <HEAD> <TITLE>A Simple Form Validation Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- function checkit() { // submit validation function var strval = document.myform.mytext.value; // 2; input text value var intval = parseInt(strval); // 3; convert to integer if ( 0 < intval && intval < 10 ) { // 4; input ok return( true ); // 5; allow submit } else { // 6; input bad - tell user alert("Input value " + strval + " is out of range"); return( false ); // 8; forbid submit } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> <FORM NAME="myform" METHOD="post" ACTION="mailto:me@myhost.com" onSubmit="return checkit()"> <P>Enter a number between 1 and 9: <INPUT TYPE="text" NAME="mytext" VALUE="1" SIZE="10"></P> <BR><INPUT TYPE="submit"> </FORM> <HR> </BODY> </HTML>
It is worthwhile to examine this example in some detail, as it exposes a number of points that are more thoroughly discussed later in this chapter. Let us consider the HTML in the <BODY> first. The FORM statement creates a form named myform with our usual fictitious mailto destination. It also contains an onSubmit attribute that specifies checkit() as the JScript function to call when the form is about to be submitted. Like all of our previous event handlers, this one takes no arguments. You will see very shortly that it is not only possible to pass in arguments, but it can also be very beneficial. For a document this simple, however, it is not necessary.
The first INPUT tag establishes an editable text field named mytext, which can hold up to 10 characters, and that will be initialized to the string "1". The second INPUT tag puts a Submit button just below the input text field. Neither of these INPUT statements has any handler attributes, although they could. What happens next?
If the user types in any text, or does anything except press the
Submit button, then nothing special happens. This example does
not process any events other than the
submit event, so changes
in the text field or navigation actions do not result in any JScript
code being executed. If the user does press the Submit button,
then the myform form tries
to submit itself. This triggers the submit
action, which results in its event handler, checkit(),
being called.
The checkit function does
two somewhat obscure things. In statement 2, it sets the local
variable strval equal to
the value of document.myform.mytext.value.
We know from the "Functions and Objects" section of
Chapter 2 "Jscript: The Language," that the right side
of this expression must be an object reference-in fact, a reference
to an object within an object within an object. It is reasonable
and correct to assume that the myform
subobject corresponds to the HTML form named myform
within the current document, and that the mytext
subobject corresponds to the HTML editable text field named mytext
inside myform. This windy
construct transfers the value of that text field into the local
variable strval. In statement
3, an attempt is made to convert this string to an integer using
the built-in function parseInt.
The putative integer is stored in intval.
See the sections, "HTML Objects" and "Built-In Functions" in Chapter 4 "JScript Objects," for more information on how to manipulate HTML fields. |
In statement 4, our validation test is performed. If the string in the text field did represent an integer between 1 and 9, inclusive, this if test passes and the checkit function returns true in statement 5. This is a message from JScript to the browser that the submission may complete.
If the text field was out of range, the else pathway in statement 6 is taken. Note that parseInt returns 0 if its argument cannot be parsed as an integer. This means that if the user entered "five" in the text field rather than "5", the value of intval will be 0, and the else clause will be taken. Statement 7 puts up an alert dialog box telling the user that the value was out of range. It contains the string representation of the value. This is useful, since the alert dialog box may be inadvertently positioned over the text input field. Finally, statement 8 returns false, indicating that the submit operation should not complete. The outcome of entering a value that is out of bounds is shown in Figure 3.7.
Figure 3.7 : JScript submit handlers are often used to validate form input.
It should be stressed that if the event handler had been declared as onSubmit="checkit()" the function checkit() would still be called whenever the Submit button was pressed, but no validation would take place. The form would always be submitted in this case, even if the input value is out of range. In this case, the return code from the checkit() function is ignored. The version that we used in Listing 3.5, onSubmit="return checkit()", ensures that the submission is canceled if checkit() returns false.
In this particular case, it is important to give the mytext
text field an initial value of 1. This ensures that if the user
clicks the Submit button without altering that text field, it
will have an acceptable value, and the form will be submitted.
In many cases, just the opposite is true. The whole point of a
catalog order form is to persuade the user to enter critical information,
such as his or her name and e-mail address. In this case, it's
a good idea to initialize the text field with a deliberately invalid
value, so that if the user hits Submit without typing anything,
the form is not submitted. Chapter 6 "Interactive HTML Objects,"
and Chapter 16, "Creative User Interaction," provide
several more sophisticated examples of customized user interaction
using JScript.
Note |
Always give the user meaningful feedback on inappropriate input or other error conditions. Indicate why and where the error occurred, not just that an error occurred. Be brief, but specific. |
Almost all form elements may have one or more event handlers. The type of event handlers permitted on a given element depends on the type of element itself. You have already seen the linkage between events and HTML entities in Figure 3.4. Broadly speaking, buttons can generate click events, and text and select items can generate focus, blur, select, and change events. The one potentially confusing aspect of this organization of events is that selection lists cannot generate the select event. This is because they have no editable text. We will not consider all possible events in this chapter, only a pithy subset.
There are two important exceptions to the rule that all form elements can have handlers. The first exception applies to hidden items, those with <INPUT TYPE="hidden">. Since they cannot be seen, they cannot be changed by the user, and therefore cannot generate events. The second exception applies to individual OPTION elements within a SELECT selection list. The SELECT tag itself may have attributes declaring focus, blur, and change handlers, but the OPTIONs may not generate their own events. Any acquisition or loss of focus and any change in the item(s) that have been selected apply to the whole list, not to an individual element.
Button Click Events. All button types within an HTML form can have click event handlers by adding an onClick attribute to their <INPUT> declaration. Simple buttons with a TYPE attribute of "button", "reset", or "submit" merely signal that they have been pressed. (Recall that the act of submitting a form may also be caught using an onSubmit handler attached to the <FORM> declaration.) Check boxes and option buttons also have values. Check boxes and individual option buttons can be asked whether they are on or off. A group of option buttons can also be asked for the unique index of the button currently checked.
One very common problem in HTML forms design is the issue of conflicting options. Users are often presented with a variety of different choices, which may even be spread out over more than one HTML form. Some combinations of choices may be invalid or dubious. Unfortunately, in standard HTML, there is no way to perform input validation of this kind without actually submitting the form and asking the ACTION URL whether that particular combination is acceptable.
JScript event handlers are ideal for this kind of validation. As you will learn in Chapter 4 every HTML form element is also a JScript object. You have already seen some examples of this in Listings 3.4 and 3.5. Listing 3.6 shows two option buttons working together with a check box using a JScript onClick event handler. The code for this listing can be found in file ex36.htm on the CD-ROM. The initial appearance of this form is shown in Figure 3.8.
Listing 3.6 ex36.htm-Values of Different Form Elements Can Be Accessed in JScript
<HTML> <HEAD> <TITLE>Two Choices Work as One</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- function insok() { // make sure payment & ins choices are compatible var isgold = document.myform.payment[1].checked; // 2; gold checked var isins = document.myform.insurance.checked; // 3; insurance selected? var ok = null; // 5; if paying in gold without insurance then.. if ( isgold == true && isins != true ) { ok = confirm("Do you want insurance?"); // 6; ask for insurance if ( ok == true ) { // 7; yes, get insurance document.myform.insurance.checked = true; // 8; check it } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> <FORM NAME="myform" METHOD="POST" ACTION="mailto:me@myhost.com"> <STRONG>Payment Options</STRONG><BR> <HR> <INPUT TYPE="radio" NAME="payment" VALUE="1" CHECKED onClick="insok()"> Personal Check <INPUT TYPE="radio" NAME="payment" VALUE="2" onClick="insok()"> Gold Bullion <HR> <INPUT TYPE="checkbox" NAME="insurance" VALUE="Ins"> Insurance? </FORM> <HR> </BODY> </HTML>
The <BODY> of this page sets up a two-choice option button named payment, and a check box named insurance. The first button is selected, and the check box starts off unchecked. The option button group has the function insok as its click event handler. Whenever either of the buttons is clicked, the insok function is called.
In statements 2 and 3, insok fetches the current value of the second option button named payment. Note that payment actually denotes the entire group of buttons, not any single option button, so that you must use the array reference payment[1] in order to refer to the second button (0-based indexing is used). That value is stored in the Boolean variable isgold. The variable insok gets the state of the insurance check box, which is also true if it is checked and false if it is not. A compatibility test is now performed in statement 5. If the option button group indicates payment in gold bullion, but the insurance button is not checked, then a confirmation dialog box is put up using the confirm() function in statement 6.
Figure 3.8 : JScript onClick handlers can be used to exclude invalid user input.
The confirmation dialog box has OK and Cancel buttons. If the
user presses OK, the function returns true;
otherwise it returns false.
The return value is tested in statement 7. If it was true,
then the user does want insurance, and the method function value
of the checked property of the myform.insurance
object is set to true. Without
worrying too much about what methods and properties really mean
just yet, it is easy to infer that this assignment statement has
the same effect as a click of the insurance button. That check
box is now checked.
Troubleshooting |
I modified the code shown in Listing 3.6. I added another group of option buttons to collect information about the user's income level, with its own event handler doinc(). I would like to force the insok()
function to be called from the new event handler. Inside doinc(), I have a statement:
myform.insurance.click(); This click() function is supposed to cause the insurance check box to be checked, but the handler is never called. Why? JScript has many functions such as click() that emulate user actions. These emulated actions do not generate events, however, so the corresponding event handler functions are never called. There is nothing mystical about the event handler function insok()-it is an ordinary JScript function that happens to be linked to an HTML event. If you want to call insok() in your doinc() event handler, just do the following: insok(); |
Text Edit and Selection Events. HTML text <INPUT> fields with a TYPE attribute of "text" may declare event handlers for any combination of the four text events: focus, blur, change, and select. Multiline text input items created with a TEXTAREA tag may also have these handlers. Selection lists created with <SELECT> can generate all these events except select.
The focus event is generated when the text item gets the input focus, usually as a result of a mouse click. Tabbing through form fields also moves the input focus. The blur event is generated when an item that had focus loses it. The change event is generated whenever something changes. In a text item, this results when any new text is entered or existing text deleted. In a selection list, it happens whenever a new selection is made, even in a list that permits MULTIPLE selections. The select event is generated when the user selects some text, usually by click-and-drag or double-click operations with the mouse. The select event is almost always accompanied by a visual cue, usually by the selected text becoming highlighted or changing color.
These events can be used to obtain very fine control over the content of text or selection list items. The most common application is to use the change or blur events to ensure that a text field has an appropriate value. If you ask the user to enter his or her birthdate, for example, and provide separate fields for the month, day, and year, you will almost certainly want to make sure that the value of the day field is a number between 1 and 31. You might even go to greater lengths, and limit the day field's value based on the value of the month field. In any case, you want to avoid erroneous input such as "bleen." Text events can also be used to coordinate the values coming from multiple form elements, as we saw in Listing 3.6.
Listing 3.7 (file ex37.htm on the CD-ROM) shows a linguistic application of the blur event for a TEXTAREA. The user is inspired to enter a sentence without a single instance of the letter e. If the user tries and fails, he is chided for his lack of creativity. Note that the blur event handler is called only if the user clicks outside the textarea, because blur is generated only when focus is lost. Parts II and IV of this book provide many more detailed examples of all the JScript events.
Listing 3.7 ex37.htm-An Example of JScript's Text Events
<HTML> <HEAD> <TITLE>A Literary Exercise</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- function hasE() { // complain if there is an e var thestr = document.myform.mytarea.value; // 2; get textarea value var uthestr = thestr.toLowerCase(); // 3; convert to lowercase if ( uthestr == "" ) { // 4; no entry return; // 5; just return } if ( uthestr.indexOf("e") >= 0 ) { // 7; found an 'e' alert("Alors! You've got an E in there!"); // 8; failed } else { if ( uthestr.length <= 20 ) { alert("Nice try, but too brief"); // 11; too short } else { alert("Congratulations!"); // 13; succeeded } } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <P>The novel <I>A Void</I> does not contain a single "e".<BR> Can you create a sentence without one?</P> <HR> <FORM NAME="myform" METHOD="POST" ACTION="mailto:me@myhost.com"> <TEXTAREA NAME="mytarea" ROWS="5" COLUMNS="80" onBlur="hasE()"> </TEXTAREA> </FORM> <HR> </BODY> </HTML>
The modus operandi of this example should be becoming familiar to you now. If the user types or clicks in the textarea, nothing happens. When he or she leaves the textarea and clicks elsewhere, a blur event is generated and the handler function hasE is invoked. This function gets the contents of the textarea into a local variable named thestr (in statement 2) and then uses one of the string functions to convert it to lowercase (statement 3). This saves a little time, as the function won't have to test for the presence of both e and E. The new lowercase string uthestr is tested against the empty string in statement 4. If there is no text, the function returns without complaint.
If there is some text, but it has an e, the user is reprimanded in statement 8. If there is no e, but the text has less than 20 characters, the user is encouraged to try a more ambitious work in statement 11. If the text is long enough and has no e, the user is praised in statement 13. Of course, there is nothing preventing the user from entering gibberish such as zzzzzzzzzzzzzzzzzzzzzzzzz and being congratulated anyway. Much more sophisticated checking would be necessary to ensure that the input was actually a sentence.