11. JavaScript: Events

OBJECTIVES

In this chapter you’ll learn:

• The concepts of events, event handlers and event bubbling.

• To create and register event handlers that respond to mouse and keyboard events.

• To use the event object to get information about an event.

• To recognize and respond to common events, including onload, onmousemove, onmouseover, onmouseout, onfocus, onblur, onsubmit and onreset.

The wisest prophets make sure of the event first.
—Horace Walpole

Do you think I can listen all day to such stuff?
—Lewis Carroll

The user should feel in control of the computer; not the other way around. This is achieved in applications that embody three qualities: responsiveness, permissiveness, and consistency.
Inside Macintosh, Volume 1
Apple Computer, Inc., 1985

We are responsible for actions performed in response to circumstances for which we are not responsible.
—Allan Massie

11.1 Introduction

We’ve seen that XHTML pages can be controlled via scripting, and we’ve already used a few events to trigger scripts, such as the onclick and onsubmit events. This chapter goes into more detail on JavaScript events, which allow scripts to respond to user interactions and modify the page accordingly. Events allow scripts to respond to a user who is moving the mouse, entering form data or pressing keys. Events and event handling help make web applications more responsive, dynamic and interactive.

In this chapter, we discuss how to set up functions to react when an event fires (occurs). We give examples of event handling for nine common events, including mouse events and form-processing events. A the end of the chapter, we provide a table of the events covered in this chapter and other useful events.

11.2 Registering Event Handlers

Functions that handle events are called event handlers. Assigning an event handler to an event on a DOM node is called registering an event handler. Previously, we have registered event handlers using the inline model, treating events as attributes of XHTML elements (e.g., <p onclick = "myfunction()">). Another model, known as the traditional model, for registering event handlers is demonstrated alongside the inline model in Fig. 11.1.

Fig. 11.1 | Event registration models. (Part 1 of 3.)

Image

Fig. 11.1 | Event registration models. (Part 2 of 3.)

Image

Fig. 11.1 | Event registration models. (Part 3 of 3.)

Image

In the earliest event-capable browsers, the inline model was the only way to handle events. Later, Netscape developed the traditional model and Internet Explorer adopted it. Since then, both Netscape and Microsoft have developed separate (incompatible) advanced event models with more functionality than either the inline or the traditional model. Netscape’s advanced model was adapted by the W3C to create a DOM Events Specification. Most browsers support the W3C model, but Internet Explorer 7 does not. This means that to create cross-browser websites, we are mostly limited to the traditional and inline event models. While the advanced models provide more convenience and functionality, most of the features can be implemented with the traditional model.

Line 35 assigns "handleEvent()" to the onclick attribute of the div in lines 35–36. This is the inline model for event registration we’ve seen in previous examples. The div in line 39 is assigned an event handler using the traditional model. When the body element (lines 33–40) loads, the registerHandler function is called.

Function registerHandler (lines 25–29) uses JavaScript to register the function handleEvent as the event handler for the onclick event of the div with the id "traditional". Line 27 gets the div, and line 28 assigns the function handleEvent to the div’s onclick property.

Notice that in line 28, we do not put handleEvent in quotes or include parentheses at the end of the function name, as we do in the inline model in line 35. In the inline model, the value of the XHTML attribute is a JavaScript statement to execute when the event occurs. The value of the onclick property of a DOM node is not an executable statement, but the name of a function to be called when the event occurs. Recall that JavaScript functions can be treated as data (i.e., passed into methods, assigned to variables, etc.).

Image

Common Programming Error 11.1

Putting quotes around the function name when registering it using the inline model would assign a string to the onclick property of the node—a string cannot be called.

Image

Common Programming Error 11.2

Putting parentheses after the function name when registering it using the inline model would call the function immediately and assign its return value to the onclick property.

Once the event handler is registered in line 28, the div in line 39 has the same behavior as the div in lines 35–36, because handleEvent (lines 19–22) is set to handle the onclick event for both divs. When either div is clicked, an alert will display "The event was successfully handled."

The traditional model allows us to register event handlers in JavaScript code. This has important implications for what we can do with JavaScript events. For example, traditional event-handler registration allows us to assign event handlers to many elements quickly and easily using repetition statements, instead of adding an inline event handler to each XHTML element. In the remaining examples in this chapter, we use both the inline and traditional registration models depending on which is more convenient.

11.3 Event onload

The onload event fires whenever an element finishes loading successfully (i.e., all its children are loaded). Frequently, this event is used in the body element to initiate a script after the page loads in the client’s browser. Figure 11.2 uses the onload event for this purpose. The script called by the onload event updates a timer that indicates how many seconds have elapsed since the document was loaded.

Fig. 11.2 | Demonstrating the onload event. (Part 1 of 2.)

Image

Fig. 11.2 | Demonstrating the onload event. (Part 2 of 2.)

Image

Our use of the onload event occurs in line 30. After the body section loads, the browser triggers the onload event. This calls function startTimer (lines 15–19), which in turn uses method window.setInterval to specify that function updateTime (lines 22–26) should be called every 1000 milliseconds. The updateTime function increments variable seconds and updates the counter on the page.

Note that we could not have created this program without the onload event, because elements in the XHTML page cannot be accessed until the page has loaded. If a script in the head attempts to get a DOM node for an XHTML element in the body, getElementById returns null because the body has not yet loaded. Other uses of the onload event include opening a pop-up window once a page has loaded and triggering a script when an image or Java applet loads.

Image

Common Programming Error 11.3

Trying to get an element in a page before the page has loaded is a common error. Avoid this by putting your script in a function using the onload event to call the function.

11.4 Event onmousemove, the event Object and this

This section introduces the onmousemove event, which fires repeatedly whenever the user moves the mouse over the web page. We also discuss the event object and the keyword this, which permit more advanced event-handling capabilities. Figure 11.3 uses onmousemove and this to create a simple drawing program that allows the user to draw inside a box in red or blue by holding down the Shift or Ctrl keys.

Fig. 11.3 | Simple drawing program. (Part 1 of 3.)

Image

Fig. 11.3 | Simple drawing program. (Part 2 of 3.)

Image

Fig. 11.3 | Simple drawing program. (Part 3 of 3.)

Image

The XHTML body has a table with a tbody containing one row that gives the user instructions on how to use the program. The body’s onload attribute (line 61) calls function createCanvas, which initializes the program by filling in the table.

The createCanvas function (lines 23–41) fills in the table with a grid of cells. The CSS rule in lines 14–15 sets the width and height of every td element to 4px. Line 11 dictates that the table is 400px wide. Line 13 uses the border-collapse CSS property to eliminate space between the table cells.

Line 25 defines variable side, which determines the number of cells in each row and the number of rows created by the nested for statements in lines 28–40. We set side to 100 in order to fill the table with 10,000 4px cells. Line 26 stores the tbody element so that we can append rows to it as they are generated.

Image

Common Programming Error 11.4

Although you can omit the tbody element in an XHTML table, without it you cannot append tr elements as children of a table using JavaScript. While Firefox treats appended rows as members of the table body, Internet Explorer will not render any table cells that are dynamically added to a table outside a thead, tbody or tfoot element.

The nested for statements in lines 28–40 fill the table with a 100 × 100 grid of cells. The outer loop creates each table row, while the inner loop creates each cell. The inner loop uses the createElement method to create a table cell, assigns function process-MouseMove as the event handler for the cell’s onmousemove event and appends the cell as a child of the row. The onmousemove event of an element fires whenever the user moves the mouse over that element.

At this point, the program is initialized and simply calls processMouseMove whenever the mouse moves over any table cell. The function processMouseMove (lines 44–57) colors the cell the mouse moves over, depending on the key that is pressed when the event occurs. Lines 44–48 get the event object, which stores information about the event that called the event-handling function.

Internet Explorer and Firefox do not implement the same event models, so we need to account for some differences in how the event object can be handled and used. Firefox and other W3C-compliant browsers (e.g., Safari, Opera) pass the event object as an argument to the event-handling function. Internet Explorer, on the other hand, stores the event object in the event property of the window object. To get the event object regardless of the browser, we use a two-step process. Function processMouseMove takes the parameter e in line 44 to get the event object from Firefox. Then, if e is undefined (i.e., if the client is Internet Explorer), we assign the object in window.event to e in line 48.

In addition to providing different ways to access the event object, Firefox and Internet Explorer also implement different functionality in the event object itself. However, there are several event properties that both browsers implement with the same name, and some that both browsers implement with different names. In this book, we use properties that are implemented in both event models, or we write our code to use the correct property depending on the browser—all of our code runs properly in IE7 and Firefox 2 (and higher).

Once e contains the event object, we can use it to get information about the event. Lines 51–56 do the actual drawing. The event object’s ctrlKey property contains a boolean which reflects whether the Ctrl key was pressed during the event. If ctrlKey is true, line 52 executes, changing the color of a table cell.

To determine which table cell to color, we introduce the this keyword. The meaning of this depends on its context. In an event-handling function, this refers to the DOM object on which the event occurred. Our function uses this to refer to the table cell over which the mouse moved. The this keyword allows us to use one event handler to apply a change to one of many DOM elements, depending on which one received the event.

Lines 51–52 change the background color of this table cell to blue if the Ctrl key is pressed during the event. Similarly, lines 55–56 color the cell red if the Shift key is pressed. To determine this, we use the shiftKey property of the event object. This simple function allows the user to draw inside the table on the page in red and blue.

This example demonstrated the ctrlKey and shiftKey properties of the event object. Figure 11.4 lists some important cross-browser properties of the event object.

Fig. 11.4 | Some event object properties. (Part 1 of 2.)

Image

Fig. 11.4 | Some event object properties. (Part 2 of 2.)

Image

This section introduced the event onmousemove and the keyword this. We also discussed more advanced event handling using the event object to get information about the event. The next section continues our introduction of events with the onmouseover and onmouseout events.

11.5 Rollovers with onmouseover and onmouseout

Two more events fired by mouse movements are onmouseover and onmouseout. When the mouse cursor moves into an element, an onmouseover event occurs for that element. When the cursor leaves the element, an onmouseout event occurs. Figure 11.5 uses these events to achieve a rollover effect that updates text when the mouse cursor moves over it. We also introduce a technique for creating rollover images.

Fig. 11.5 | Events onmouseover and onmouseout. (Part 1 of 4.)

Image

Fig. 11.5 | Events onmouseover and onmouseout. (Part 2 of 4.)

Image

Fig. 11.5 | Events onmouseover and onmouseout. (Part 3 of 4.)

Image

Fig. 11.5 | Events onmouseover and onmouseout. (Part 4 of 4.)

Image

To create a rollover effect for the image in the heading, lines 20–23 create two new JavaScript Image objects—image1 and image2. Image image2 displays when the mouse hovers over the image. Image image1 displays when the mouse is outside the image. The script sets the src properties of each Image in lines 21 and 23, respectively. Creating Image objects preloads the images (i.e., loads the images in advance), so the browser does not need to download the rollover image the first time the script displays the image. If the image is large or the connection is slow, downloading would cause a noticeable delay in the image update.

Image

Performance Tip 11.1

Preloading images used in rollover effects prevents a delay the first time an image is displayed.

Functions mouseOver and mouseOut are set to process the onmouseover and onmouseout events, respectively, in lines 74–75. Both functions begin (lines 25–28 and 45–48) by getting the event object and using function getTarget to find the element that received the action. Because of browser event model differences, we need getTarget (defined in lines 66–72) to return the DOM node targeted by the action. In Internet Explorer, this node is stored in the event object’s srcElement property. In Firefox, it is stored in the event object’s target property. Lines 68–71 return the node using the correct property to hide the browser differences from the rest of our program. We must use function getTarget instead of this because we do not define an event handler for each specific element in the document. In this case, using this would return the entire document. In both mouseOver and mouseOut, we assign the return value of getTarget to variable target (lines 30 and 50).

Lines 33–37 in the mouseOver function handle the onmouseover event for the heading image by setting its src attribute (target.src) to the src property of the appropriate Image object (image2.src). The same task occurs with image1 in the mouseOut function (lines 53–57).

The script handles the onmouseover event for the table cells in lines 41–42. This code tests whether an id is specified, which is true only for our hex code table cells and the heading image in this example. If the element receiving the action has an id, the code changes the color of the element to match the color name stored in the id. As you can see in the code for the table (lines 86–111), each td element containing a color code has an id attribute set to one of the 16 basic XHTML colors. Lines 61–62 handle the onmouseout event by changing the text in the table cell the mouse cursor just left to match the color that it represents.

11.6 Form Processing with onfocus and onblur

The onfocus and onblur events are particularly useful when dealing with form elements that allow user input (Fig. 11.6). The onfocus event fires when an element gains focus (i.e., when the user clicks a form field or uses the Tab key to move between form elements), and onblur fires when an element loses focus, which occurs when another control gains the focus. In lines 31–32, the script changes the text inside the div below the form (line 58) based on the messageNum passed to function helpText (lines 29–33). Each of the elements of the form, such as the name input in lines 40–41, passes a different value to the helpText function when it gains focus (and its onfocus event fires). These values are used as indices for helpArray, which is declared and initialized in lines 17–27 and stores help messages. When elements lose focus, they all pass the value 6 to helpText to clear the tip div (note that the empty string "" is stored in the last element of the array).

Fig. 11.6 | Demonstrating the onfocus and onblur events. (Part 1 of 2.)

Image

Fig. 11.6 | Demonstrating the onfocus and onblur events. (Part 2 of 2.)

Image

11.7 Form Processing with onsubmit and onreset

Two more useful events for processing forms are onsubmit and onreset. These events fire when a form is submitted or reset, respectively (Fig. 11.7). Function registerEvents (lines 35–46) registers the event handlers for the form after the body has loaded.

Fig. 11.7 | Demonstrating the onsubmit and onreset events. (Part 1 of 2.)

Image

Fig. 11.7 | Demonstrating the onsubmit and onreset events. (Part 2 of 2.)

Image

Lines 37–40 and 42–45 introduce several new concepts. Line 37 gets the form element ("myForm", lines 51–70), then lines 37–40 assign an anonymous function to its onsubmit property. An anonymous function is defined with no name—it is created in nearly the same way as any other function, but with no identifier after the keyword function. This notation is useful when creating a function for the sole purpose of assigning it to an event handler. We never call the function ourselves, so we don’t need to give it a name, and it’s more concise to create the function and register it as an event handler at the same time.

The anonymous function (lines 37–40) assigned to the onsubmit property of myForm executes in response to the user submitting the form (i.e., clicking the Submit button or pressing the Enter key). Line 39 introduces the confirm method of the window object. As with alert, we do not need to prefix the call with the object name window and the dot (.) operator. The confirm dialog asks the users a question, presenting them with an OK button and a Cancel button. If the user clicks OK, confirm returns true; otherwise, confirm returns false.

Our event handlers for the form’s onsubmit and onreset events simply return the value of the confirm dialog, which asks the users if they are sure they want to submit or reset (lines 39 and 44, respectively). By returning either true or false, the event handlers dictate whether the default action for the event—in this case submitting or resetting the form—is taken. (Recall that we also returned false from some event-handling functions to prevent forms from submitting in Chapter 10.) Other default actions, such as following a hyperlink, can be prevented by returning false from an onclick event handler on the link. If an event handler returns true or does not return a value, the default action is taken once the event handler finishes executing.

11.8 Event Bubbling

Event bubbling is the process by which events fired in child elements “bubble” up to their parent elements. When an event is fired on an element, it is first delivered to the element’s event handler (if any), then to the parent element’s event handler (if any). This might result in event handling that was not intended. If you intend to handle an event in a child element alone, you should cancel the bubbling of the event in the child element’s event-handling code by using the cancelBubble property of the event object, as shown in Fig. 11.8.

Fig. 11.8 | Canceling event bubbling. (Part 1 of 3.)

Image

Fig. 11.8 | Canceling event bubbling. (Part 2 of 3.)

Image

Fig. 11.8 | Canceling event bubbling. (Part 3 of 3.)

Image

Clicking the first p element (line 45) triggers a call to bubble. Then, because line 37 registers the document’s onclick event, documentClick is also called. This occurs because the onclick event bubbles up to the document. This is probably not the desired result. Clicking the second p element (line 46) calls noBubble, which disables the event bubbling for this event by setting the cancelBubble property of the event object to true. [Note: The default value of cancelBubble is false, so the statement in line 23 is unnecessary.]

Image

Common Programming Error 11.5

Forgetting to cancel event bubbling when necessary may cause unexpected results in your scripts.

11.9 More Events

The events we covered in this chapter are among the most commonly used. A list of some events supported by both Firefox and Internet Explorer is given with descriptions in Fig. 11.9.

Fig. 11.9 | Cross-browser events.

Image

11.10 Web Resources

http://www.quirksmode.org/js/introevents.html

An introduction and reference site for JavaScript events. Includes comprehensive information on history of events, the different event models, and making events work across multiple browsers.

wsabstract.com/dhtmltutors/domevent1.shtml

This JavaScript Kit tutorial introduces event handling and discusses the W3C DOM advanced event model.

http://www.w3schools.com/jsref/jsref_events.asp

The W3 School’s JavaScript Event Reference site has a comprehensive list of JavaScript events, a description of their usage and their browser compatibilities.

http://www.brainjar.com/dhtml/events/

BrainJar.com’s DOM Event Model site provdes a comprehensive introduction to the DOM event model, and has example code to demonstrate several different ways of assigning and using events.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset