We've seen how JavaScript "scripts" can be embedded into HTML files. The following subsections explain how JavaScript event-handler functions are embedded in HTML files to allow web pages to interact with the user.
In the old days, computer programs often ran in "batch" mode. This meant that they read a batch of data in, did some computation on that data, and then wrote out the results. Later, with timesharing and text-based terminals, limited kinds of interactivity became possible--the program could ask the user for input, and the user could type in data; the computer could process the data and display the results on-screen.
Nowadays, however, with graphical displays and pointing devices like mouses, the situation is different--programs are generally "event driven," responding to mouse button clicks and keystrokes in a way that depends on the position of the mouse pointer. A web browser is just such a graphical environment, and so client-side JavaScript uses the event-driven programming model.
In order to implement an event-driven program, you must write event-handler functions that take the appropriate actions in response to the user's input. You must also register these event handlers with the system in some way (perhaps just by giving them standard names) so that the system can invoke them at the appropriate times.
Events do not just occur of their own accord. Generally, they are generated when the user interacts with something in the user interface. When the user interface is an HTML file, as is the case for client-side JavaScript programs, then that "something" will be a HTML object, such as a hypertext link, a button, a drop-down menu or an input field. Since events occur "on" particular objects, it follows that they must be handled "for" those particular objects. Therefore, the logical way to define an event handler is as part of the HTML object to which it responds.
In order to allow us to define JavaScript event handlers as part of HTML object definitions, JavaScript extends HTML by adding new attributes to various HTML tags that define objects. For example, to define an event handler that is invoked when the user clicks on a checkbox in a form, for example, you specify the handler code as an attribute of the HTML tag that defines the checkbox in the form:
<INPUT TYPE="checkbox" NAME="opts" VALUE="ignore-case" onClick="ignore_case = this.checked;" >
What's of interest to us here is the onClick attribute.[3] The string value of the onClick attribute may contain one or more JavaScript statements. If there is more than one statement, they must be separated from each other with semicolons.[4] When the specified event--in this case, a click--occurs on the checkbox the JavaScript code within the string will be executed.
[3] The mixed-case capitalization of onClick is a common convention for JavaScript event handlers defined in HTML files. HTML element and attribute names are case-insensitive, but writing "onClick" rather than "ONCLICK" sets off the handlers from standard HTML tags that are, by convention, shown in all capitals.
[4] The statements may not be separated by newlines: while an HTML attribute value normally may contain newlines, this doesn't work with JavaScript.
While you can include any number of JavaScript statements within an event-handler definition, a common technique, when more than one or two simple statements are required, is to define the body of an event handler as a function between <SCRIPT> and </SCRIPT> tags, and then to simply invoke this function from the event handler. This keeps most of your actual JavaScript code within scripts and reduces the need to mingle JavaScript and HTML.
Most form elements have one or more event handlers that you can define. Buttons, checkboxes, and radio buttons are among the elements that can specify an onClick handler. Text and Textarea elements can have onChange, onFocus, and onBlur event handlers that are invoked when the user changes the displayed value or when the user gives keyboard focus to, or takes away keyboard focus from, the element. In addition to these HTML form-related event handlers, there are also handlers invoked whenever the user moves the mouse over a hypertext link and whenever a web page is loaded into the browser or unloaded from the browser.
Table 10.1 lists the event handlers defined by all client-side JavaScript objects. The objects themselves will be introduced in some of the following chapters, but this table will, for now, illustrate what a diverse collection of event handlers is supported by JavaScript. Once you've learned about all of the client-side objects supported by JavaScript, this table should serve as a convenient event-handler reference. Note that this table lists event handlers supported by Navigator 3.0; not all those shown are supported by Navigator 2.0 or Internet Explorer 3.0.
Object | Supported Event Handlers | ||||
---|---|---|---|---|---|
Area | onClick()[1] | onMouseOut() | onMouseOver() | ||
Button | onBlur()[2] | onClick() | onFocus()[2] | ||
Checkbox | onBlur()[2] | onClick() | onFocus()[2] | ||
FileUpload | onBlur() | onChange() | onFocus() | ||
Form | onReset() | onSubmit() | |||
Frame | onLoad() | onUnload() | |||
Image | onAbort() | onError() | onLoad() | ||
Link | onClick() | onMouseOut() | onMouseOver() | ||
Radio | onBlur()[2] | onClick() | onFocus()[2] | ||
Reset | onBlur()[2] | onClick() | onFocus()[2] | ||
Select | onBlur()[2] | onChange() | onFocus()[2] | ||
Submit | onBlur()[2] | onClick() | onFocus()[2] | ||
Text | onBlur() | onChange() | onFocus() | ||
Textarea | onBlur() | onChange() | onFocus() | ||
Window | onBlur() | onError() | onFocus() | onLoad() | onUnload() |
Footnotes:
[1] |
Specifying an event handler as a string within an appropriate HTML tag defines a JavaScript function that is invoked by the browser when the appropriate event occurs. In fact, in Navigator 3.0, event-handler functions are stored as properties of the objects for which they are defined. Thus, if the checkbox defined in the example above was accessible in JavaScript as document.forms[0].opts[2], the event handler defined in the object's HTML tag would be available to JavaScript code as:
document.forms[0].opts[2].onclick
In Navigator 3.0, you can use event-handler properties in the ways you can use any method property. You can use it to invoke the event handler explicitly, to assign the event handler to some other variable or pass it to a function, and even to define or redefine an event handler by assigning an appropriate function to the event-handler property--thereby avoiding the need to define the event handler with a (sometimes long and awkward) string value of an HTML attribute.
In Internet Explorer, but not in Navigator, there is an alternative syntax for defining event handlers. It involves using new FOR and EVENT attributes to the <SCRIPT> tag to specify code that constitutes an event handler for a named object and a named event. Using this Internet Explorer technique, we could rewrite the checkbox example shown earlier like this:
<INPUT TYPE="checkbox" NAME="opts" VALUE="ignore-case"> <SCRIPT FOR="opts" EVENT="onClick"> ignore_case = this.checked; </SCRIPT>
There is a certain elegance to specifying event handlers in this way--it avoids the need to add new JavaScript-specific attributes to all the HTML objects. Nevertheless, since this technique is not supported by Navigator, I do not recommend its use.
There is another type of event, besides those generated through user interaction. These are events generated when specified periods of time have elapsed; they are known as timer events, or "timeouts." Timeouts are important to any JavaScript program that must perform an action on some regular schedule, even when the user is not actively interacting with the browser. Applications of timeouts include clocks and animation.
You use setTimeout() (a method of the Window object) to specify that a timeout should occur a specified number of milliseconds in the future. Timer events do not have predefined event handlers as other types of events do. Instead, the code to be executed when the specified time interval elapses is passed as a string argument to setTimeout(). For example, the following code arranges for a timer event to occur in 1 second (1000 milliseconds). When that timer event occurs, the function show_date_time() will be invoked.
// call the show_date_time() function 1 second from now setTimeout("show_date_time();", 1000);
When you register a timeout with code like that above, only one timer event will occur--i.e., the timer event will occur one second in the future; it will not repeat itself every second after that. When you do want a timer that repeats periodically, you simply include code in the "handler" that re-registers the timeout by calling setTimeout() again. This is a useful technique for animation and related tasks. It might be done like this:
function animate_status_line_annoyingly() { // Set the Window.status property here, // then arrange to be called later so we can do it again! setTimeout("animate_status_line_annoyingly()", 1000); }
In complex programs you may need to use more than one timeout. This is no problem; JavaScript can keep track of any number of pending timer events. After you have registered a timeout with setTimeout(), but before the timer event has actually occurred, you can cancel the timeout with the clearTimeout() method. See the reference section of this book for complete detains on Window.setTimeout() and Window.clearTimeout().