User:Moncur/09
9. Responding to Events
wax ka badalUnderstanding Event Handlers
wax ka badalAs you learned in [Hour 3], "Getting Started with JavaScript Programming," JavaScript programs don't have to execute in order. You also learned they can detect events and react to them. Events are things that happen to the browser—the user clicking a button, the mouse pointer moving, or a web page or image loading from the server.
A wide variety of events enable your scripts to respond to the mouse, the keyboard, and other circumstances. Events are the key method JavaScript uses to make web documents interactive.
The script that you use to detect and respond to an event is called an event handler. Event handlers are among the most powerful features of JavaScript. Luckily, they're also among the easiest features to learn and use—often, a useful event handler requires only a single statement.
Objects and Events
wax ka badalAs you learned in [Hour 4], "Working with the Document Object Model (DOM)," JavaScript uses a set of objects to store information about the various parts of a web page—buttons, links, images, windows, and so on. An event can often happen in more than one place (for example, the user could click any one of the links on the page), so each event is associated with an object.
Each event has a name. For example, the onMouseOver event occurs when the mouse pointer moves over an object on the page. When the pointer moves over a particular link, the onMouseOver event is sent to that link's event handler, if it has one.
- By the Way
- Notice the strange capitalization on the onMouseOver keyword. This is the standard notation for event handlers. The on is always lowercase, and each word in the event name is capitalized.
Creating an Event Handler
wax ka badalYou don't need the <script> tag to define an event handler. Instead, you can add an event handler attribute to an individual HTML tag. For example, here is a link that includes an onMouseOver event handler:
<a href="http://www.jsworkshop.com/" onMouseOver="window.alert('You moved over the link.');"> Click here</a>
Note that this is all one <a> tag, although it's split into multiple lines. This specifies a statement to be used as the onMouseOver event handler for the link. This statement displays an alert message when the mouse moves over the link.
- By the Way
- The previous example uses single quotation marks to surround the text. This is necessary in an event handler because double quotation marks are used to surround the event handler itself. (You can also use single quotation marks to surround the event handler and double quotes within the script statements.)
You can use JavaScript statements like the previous one in an event handler, but if you need more than one statement, it's a good idea to use a function instead. Just define the function in the header of the document, and then call the function as the event handler like this:
<a href="#bottom" onMouseOver="DoIt();">Move the mouse over this link.</a>
This example calls a function called DoIt() when the user moves the mouse over the link. Using a function is convenient because you can use longer, more readable JavaScript routines as event handlers. You'll use a longer function to handle events in the "Try It Yourself: Adding Link Descriptions to a Web Page" section of this hour.
- Did you Know?
- For simple event handlers, you can use two statements if you separate them with a semicolon. However, in most cases it's easier to use a function to perform the statements.
Defining Event Handlers with JavaScript
wax ka badalRather than specifying an event handler in an HTML document, you can use JavaScript to assign a function as an event handler. This allows you to set event handlers conditionally, turn them on and off, and change the function that handles an event dynamically.
- Did you Know?
- Setting up event handlers this way is also a good practice in general: It allows you to use an external JavaScript file to define the function and set up the event, keeping the JavaScript code completely separate from the HTML file.
To define an event handler in this way, you first define a function, and then assign the function as an event handler. Event handlers are stored as properties of the document object or another object that can receive an event. For example, these statements define a function called mousealert(), and then assign it as the onMouseDown event handler for the document:
function mousealert() { alert ("You clicked the mouse!"); } document.onmousedown = mousealert;
You can use this technique to set up an event handler for any HTML element, but an additional step is required: You must first find the object corresponding to the element. To do this, use the document.getElementById() function. First, define an element in the HTML document and specify an id attribute:
<a href="http://www.google.com/" id="link1">
Next, in the JavaScript code, find the object and apply the event handler:
obj = document.getElementById("link1"); obj.onclick = MyFunction;
You can do this for any object as long as you've defined it with a unique id attribute in the HTML file. Using this technique, you can easily assign the same function to handle events for multiple objects without adding clutter to your HTML code. See the "Try It Yourself" section in this hour for an example of this technique.
Supporting Multiple Event Handlers
wax ka badalWhat if you want more than one thing to happen when you click on an element? For example, suppose you want two functions called update and display to both execute when a button is clicked. You can't assign two functions to the onclick property. One solution is to define a function that calls both functions:
function UpdateDisplay() { update(); display(); }
This isn't always the ideal way to do things. For example, if you're using two third-party scripts and both of them want to add an onLoad event to the page, there should be a way to add both. The W3C DOM standard defines a function, addEventListener, for this purpose. This function defines a listener for a particular event and object, and you can add as many listener functions as you need.
Unfortunately, addEventListener is not supported by Internet Explorer (as of versions 6 and 7), so you have to use a different function, attachEvent, in that browser. See [Hour 15], "Unobtrusive Scripting," for a function that combines these two for a cross-browser event-adding script.
Using the event Object
wax ka badalWhen an event occurs, you might need to know more about the event—for example, for a keyboard event, you need to know which key was pressed. The DOM includes an event object that provides this information.
To use the event object, you can pass it on to your event handler function. For example, this statement defines an onKeyPress event that passes the event object to a function:
<body onKeyPress="getkey(event);">
You can then define your function to accept the event as a parameter:
function getkey(e) { ... }
In Mozilla-based browsers (Firefox and Netscape), an event object is automatically passed to the event handler function, so this will work even if you use JavaScript rather than HTML to define an event handler. In Internet Explorer, the most recent event is stored in the window.event object. The previous HTML example passes this object to the event handler function. If you define the event handler with JavaScript, this is not possible, so you need to use some code to find the correct object:
Function getkey(e) { if (!e) e=window.event; ... }
This checks whether the e variable is already defined. If not, it gets the window.event object and stores it in e. This ensures that you have a valid event object in any browser.
Unfortunately, while both Internet Explorer and Mozilla-based browsers support event objects, they support different properties. One property that is the same in both browsers is event.type, the type of event. This is simply the name of the event, such as mouseover for an onMouseOver event, and keypress for an onKeyPress event. The following sections list some additional useful properties for each browser.
Internet Explorer event Properties
wax ka badalThe following are some of the commonly used properties of the event object for Internet Explorer 4.0 and later:
- event.button The mouse button that was pressed. This value is 1 for the left button and usually 2 for the right button.
- event.clientX The x-coordinate (column, in pixels) where the event occurred.
- event.clientY The y-coordinate (row, in pixels) where the event occurred.
- event.altkey A flag that indicates whether the Alt key was pressed during the event.
- event.ctrlkey Indicates whether the Ctrl key was pressed.
- event.shiftkey Indicates whether the Shift key was pressed.
- event.keyCode The key code (in Unicode) for the key that was pressed.
- event.srcElement The object where the element occurred.
- By the Way
- See the Try it Yourself section of this hour for an example that uses the srcElement property and Mozilla's target property for a cross-browser method of determining the object for an event.
Netscape and Firefox event Properties
wax ka badalThe following are some of the commonly used properties of the event object for Netscape 4.0 and later:
- event.modifiers Indicates which modifier keys (Shift, Ctrl, Alt, and so on) were held down during the event. This value is an integer that combines binary values representing the different keys.
- event.pageX The x-coordinate of the event within the web page.
- event.pageY The y-coordinate of the event within the web page.
- event.which The keycode for keyboard events (in Unicode), or the button that was pressed for mouse events (It's best to use the cross-browser button property instead.)
- event.button The mouse button that was pressed. This works just like Internet Explorer except that the left button's value is 0 and the right button's value is 2.
- event.target The object where the element occurred.
- By the Way
- The event.pageX and event.pageY properties are based on the top-left corner of the element where the event occurred, not always the exact position of the mouse pointer.
Using Mouse Events
wax ka badalThe DOM includes a number of event handlers for detecting mouse actions. Your script can detect the movement of the mouse pointer and when a button is clicked, released, or both.
Over and Out
wax ka badalYou've already seen the first and most common event handler, onMouseOver. This handler is called when the mouse pointer moves over a link or other object.
The onMouseOut handler is the opposite—it is called when the mouse pointer moves out of the object's border. Unless something strange happens, this always happens sometime after the onMouseOver event is called.
This handler is particularly useful if your script has made a change when the pointer moved over the object—for example, displaying a message in the status line or changing an image. You can use an onMouseOut handler to undo the action when the pointer moves away.
You'll use both onMouseOver and onMouseOut handlers in the "Try it Yourself: Adding Link Descriptions to a Web Page" section at the end of this hour.
- By the Way
- One of the most common uses for the onMouseOver and onMouseOut event handlers is to create rollovers—images that change when the mouse moves over them. You'll learn how to create these in [Hour 19], "Using Graphics and Animation."
Using the onMouseMove Event
wax ka badalThe onMouseMove event occurs any time the mouse pointer moves. As you might imagine, this happens quite often—the event can trigger hundreds of times as the mouse pointer moves across a page.
Because of the large number of generated events, browsers don't support the onMouseMove event by default. To enable it for a page, you need to use event capturing. This is similar to the dynamic events technique you learned earlier in this hour, but requires an extra step for some older browsers.
The basic syntax to support this event, for both browsers, is to set a function as the onMouseMove handler for the document or another object. For example, this statement sets the onMouseMove handler for the document to a function called MoveHere, which must be defined in the same page:
document.onMouseMove=MoveHere;
Additionally, older versions of Netscape require that you specifically enable the event using the document.captureEvents method:
document.captureEvents(Event.MOUSEMOVE);
Ups and Downs (and Clicks)
wax ka badalYou can also use events to detect when the mouse button is clicked. The basic event handler for this is onClick. This event handler is called when the mouse button is clicked while positioned over the appropriate object.
- By the Way
- The object in this case can be a link. It can also be a form element. You'll learn more about forms in [Hour 11], "Getting Data with Forms."
For example, you can use the following event handler to display an alert when a link is clicked:
<a href="http://www.jsworkshop.com/" onClick="alert('You are about to leave this site.');">Click Here</a>
In this case, the onClick event handler runs before the linked page is loaded into the browser. This is useful for making links conditional or displaying a disclaimer before launching the linked page.
If your onClick event handler returns the false value, the link will not be followed. For example, the following is a link that displays a confirmation dialog. If you click Cancel, the link is not followed; if you click OK, the new page is loaded:
<a href="http://www.jsworkshop.com/" onClick="return(window.confirm('Are you sure?'));"> Click Here</a>
This example uses the return statement to enclose the event handler. This ensures that the false value that is returned when the user clicks Cancel is returned from the event handler, which prevents the link from being followed.
The onDblClick event handler is similar, but is only used if the user double-clicks on an object. Because links usually require only a single click, you could use this to make a link do two different things depending on the number of clicks. (Needless to say, this could be confusing.) You can also detect double-clicks on images and other objects.
To give you even more control of what happens when the mouse button is pressed, two more events are included:
- onMouseDown is used when the user presses the mouse button.
- onMouseUp is used when the user releases the mouse button.
These two events are the two halves of a mouse click. If you want to detect an entire click, use onClick. Use onMouseUp and onMouseDown to detect just one or the other.
To detect which mouse button is pressed, you can use the button property of the event object. This property is assigned the value 0 or 1 for the left button, and 2 for the right button. This property is assigned for onClick, onDblClick, onMouseUp, and onMouseDown events.
- Watch Out!
- Browsers don't normally detect onClick or onDblClick events for the right mouse button. If you want to detect the right button, onMouseDown is the most reliable way.
As an example of these event handlers, you can create a script that displays information about mouse button events and determines which button is pressed. [Listing 9.1] shows the mouse event script.
- Listing 9.1. The JavaScript file for the mouse click example.
function mousestatus(e) { if (!e) e = window.event; btn = e.button; whichone = (btn < 2) ? "Left" : "Right"; message=e.type + " : "+ whichone + "\n"; document.form1.info.value += message; } obj=document.getElementById("testlink"); obj.onmousedown = mousestatus; obj.onmouseup = mousestatus; obj.onclick = mousestatus; obj.ondblclick = mousestatus;
This script includes a function, mousestatus(), that detects mouse events. This function uses the button property of the event object to determine which button was pressed. It also uses the type property to display the type of event, since the function will be used to handle multiple event types.
After the function, the script finds the object for a link with the id attribute testlink and assigns its onmousedown, onmouseup, onclick, and ondblclick events to the mousestatus function.
Save this script as click.js. Next, you will need an HTML document to work with the script, shown in [Listing 9.2].
- Listing 9.2. The HTML file for the mouse click example.
<html> <head> <title>Mouse click test</title> </head> <body> <h1>Mouse Click Test</h1> <p>Click the mouse on the test link below. A message below will indicate which button was clicked.</p> <h2><a href="#" id="testlink">Test Link</a></h2> <form name="form1"> <textarea rows="10" cols="70" name="info"></textarea> </form> <script language="javascript" type="text/javascript" src="click.js"> </script> </body> </html>
This file defines a test link with the id property testlink, which is used in the script to assign event handlers. It also defines a form and a textarea used by the script to display the events. To test this document, save it in the same folder as the JavaScript file you created previously and load the HTML document into a browser. The results are shown in [Figure 9.1].
- By the Way
- Notice that a single click of the left mouse button triggers three events: onMouseDown, onMouseUp, and then onClick.
Using Keyboard Events
wax ka badalJavaScript can also detect keyboard actions. The main event handler for this purpose is onKeyPress, which occurs when a key is pressed and released, or held down. As with mouse buttons, you can detect the down and up parts of the keypress with the onKeyDown and onKeyUp event handlers.
Of course, you might find it useful to know which key the user pressed. You can find this out with the event object, which is sent to your event handler when the event occurs. In Netscape and Firefox, the event.which property stores the ASCII character code for the key that was pressed. In Internet Explorer, event.keyCode serves the same purpose.
- By the Way
- ASCII (American Standard Code for Information Interchange) is the standard numeric code used by most computers to represent characters. It assigns the numbers 0—128 to various characters—for example, the capital letters A through Z are ASCII values 65 to 90.
Displaying Typed Characters
wax ka badalIf you'd rather deal with actual characters than key codes, you can use the fromCharCode string method to convert them. This method converts a numeric ASCII code to its corresponding string character. For example, the following statement converts the event.which property to a character and stores it in the key variable:
Key = String.fromCharCode(event.which);
Because different browsers have different ways of returning the key code, displaying keys browser independently is a bit harder. However, you can create a script that displays keys for either browser. The following function will display each key as it is typed:
function DisplayKey(e) { // which key was pressed? if (e.keyCode) keycode=e.keyCode; else keycode=e.which; character=String.fromCharCode(keycode); // find the object for the destination paragraph k = document.getElementById("keys"); // add the character to the paragraph k.innerHTML += character; }
The DisplayKey() function receives the event object from the event handler and stores it in the variable e. It checks whether the e.keyCode property exists, and stores it in the keycode variable if present. Otherwise, it assumes the browser is Netscape or Firefox and assigns keycode to the e.which property.
The remaining lines of the function convert the key code to a character and add it to the paragraph in the document with the id attribute keys. [Listing 9.3] shows a complete example using this function.
- By the Way
- The final lines in the DisplayKey() function use the getElementById() function and the innerHTML attribute to display the keys you type within a paragraph on the page. This technique is explained in [Hour 13], "Using the W3C DOM."
- Listing 9.3. Displaying Typed Characters
<html> <head> <title>Displaying Keypresses</title> <script language="javascript" type="text/javascript"> function DisplayKey(e) { // which key was pressed? if (e.keyCode) keycode=e.keyCode; else keycode=e.which; character=String.fromCharCode(keycode); // find the object for the destination paragraph k = document.getElementById("keys"); // add the character to the paragraph k.innerHTML += character; } </script> </head> <body onKeyPress="DisplayKey(event);"> <h1>Displaying Typed Characters</h1> <p>This document includes a simple script that displays the keys you type in the paragraph below. Type a few keys and try it. </p> <p id="keys"> </p> </body> </html>
When you load this example into either Netscape or Internet Explorer, you can type and see the characters you've typed appear in a paragraph of the document. [Figure 9.2] shows this example in action in Firefox.
Using the onLoad and onUnload Events
wax ka badalAnother event you'll use frequently is onLoad. This event occurs when the current page (including all of its images) finishes loading from the server.
The onLoad event is related to the window object, and to define it you use an event handler in the <body> tag. For example, the following is a <body> tag that uses a simple event handler to display an alert when the page finishes loading:
<body onLoad="alert('Loading complete.');">
- Watch Out!
- Because the onLoad event occurs after the HTML document has finished loading and displaying, you cannot use the document.write or document.open statements within an onLoad event handler. This would overwrite the current document.
In JavaScript 1.1 and later, images can also have an onLoad event handler. When you define an onLoad event handler for an <img> tag, it is triggered as soon as the specified image has completely loaded.
To set an onLoad event using JavaScript, you assign a function to the onload property of the window object:
window.onload = MyFunction;
You can also specify an onUnload event for the <body> tag. This event will be triggered whenever the browser unloads the current document—this occurs when another page is loaded or when the browser window is closed.
Try It Yourself — Adding Link Descriptions to a Web Page
wax ka badalOne of the most common uses for an event handler is to display descriptions of links when the user moves the mouse over them. For example, moving the mouse over the Order Form link might display a message such as "Order a product or check an order's status".
Link descriptions like these are typically displayed with the onMouseOver event handler. You will now create a script that displays messages in this manner and clears the message using the onMouseOut event handler. You'll use functions to simplify the process.
- By the Way
- This example uses the innerHTML property to display the descriptions within a heading on the page. See [Hour 13] for a complete description of this property.
This will also be an example of defining event handlers entirely with JavaScript. The HTML document, shown in [Listing 9.4], does not include any <script> tags or event handlers—the only thing it requires is some id attributes on the objects we will be using in the script.
- Listing 9.4. The HTML Document for the Descriptive Links Example
<html> <head> <title>Descriptive Links</title> </head> <body> <h1>Descriptive Links</h1> <p>Move the mouse pointer over one of these links to view a description:</p> <ul> <li><a href="order.html" id="order">Order Form</a> <li><a href="email.html" id="email">Email</a> <li><a href="complain.html" id="complain">Complaint Department</a> </ul> <h2 id="description"></h2> <script language="JavaScript" type="text/javascript" src="linkdesc.js"> </script> </body> </html>
This document defines three links in a bulleted list. Each <a> tag is defined with an id attribute for the script to use to attach an event handler. The <h2> tag with the id value description, currently blank, will be used to display a description of each link.
- By the Way
- Notice that the <script> tag is below the content of the HTML document. It would not work at the top of the document because the objects the script uses are not yet defined. You can also deal with this issue by using an onLoad event handler instead of a simple script to set up the event handlers.
The script will begin with a function to serve as the onMouseOver event handler for the links:
function hover(e) { if (!e) var e = window.event; // which link was the mouse over? whichlink = (e.target) ? e.target.id : e.srcElement.id; // choose the appropriate description if (whichlink=="order") desc = "Order a product"; else if (whichlink=="email") desc = "Send us a message"; else if (whichlink=="complain") desc = "Insult us, our products, or our families"; // display the description in the H2 d = document.getElementById("description"); d.innerHTML = desc; }
The hover function uses the target or srcElement properties to find the target object for the link, and then finds its id attribute. Three if statements evaluate the id and choose an appropriate description. Finally, the script uses the getElementById() method to find the <h2> tag that will display the descriptions, and displays the description using the innerHTML property.
- Did you Know?
- The conditional statement on the third line of the hover function checks whether the target property exists, and if not, it uses the srcElement property. This is called feature sensing—detecting whether the browser supports a feature—and is explained further in [Hour 15], "Unobtrusive Scripting."
One more function will be required. The cleardesc() function will serve as the onMouseOut event handler and clear the description when the mouse is no longer over one of the links.
function cleardesc() { d = document.getElementById("description"); d.innerHTML = ""; }
Now that the functions are defined, you need to set them as the event handlers for the links. Each link requires the following three lines of code:
orderlink = document.getElementById("order"); orderlink.onmouseover=hover; orderlink.onmouseout=cleardesc;
After using getElementById() to find the object with the id attribute "order", this sets up the hover() and cleardesc() functions as its onMouseOver and onMouseOut event handlers. This will need to be repeated for the other two links. Putting all of this together, the complete JavaScript file for this example is shown in [Listing 9.5].
- Listing 9.5. The JavaScript File for the Link Descriptions Example
function cleardesc() { d = document.getElementById("description"); d.innerHTML = ""; } function hover(e) { if (!e) var e = window.event; // which link was the mouse over? whichlink = (e.target) ? e.target.id : e.srcElement.id; // choose the appropriate description if (whichlink=="order") desc = "Order a product"; else if (whichlink=="email") desc = "Send us a message"; else if (whichlink=="complain") desc = "Insult us, our products, or our families"; // display the description in the H2 d = document.getElementById("description"); d.innerHTML = desc; } // Set up the event handlers orderlink = document.getElementById("order"); orderlink.onmouseover=hover; orderlink.onmouseout=cleardesc; emaillink = document.getElementById("email"); emaillink.onmouseover=hover; emaillink.onmouseout=cleardesc; complainlink = document.getElementById("complain"); complainlink.onmouseover=hover; complainlink.onmouseout=cleardesc;
To test the script, store it as linkdesc.js in the same folder as the HTML document, and load the HTML file into a browser; this script should work on any JavaScript-capable browser. Internet Explorer's display of the example is shown in [Figure 9.3].
- Did you Know?
- As usual, you can download the listings for this hour from this book's website.
Summary
wax ka badalIn this hour, you've learned to use events to detect mouse actions, keyboard actions, and other events, such as the loading of the page. You can use event handlers to perform a simple JavaScript statement when an event occurs, or to call a more complicated function.
JavaScript includes a variety of other events. Many of these are related to forms, which you'll learn more about in [Hour 11]. Another useful event is onError, which you can use to prevent error messages from displaying. This event is described in [Hour 16], "Debugging JavaScript Applications."
In the next hour, you'll continue learning about the objects in the DOM. Specifically, [Hour 10], "Using Windows and Frames," looks at the objects associated with windows, frames, and layers, and how they work with JavaScript.
Q&A
wax ka badalQ1: | I noticed that the <img> tag in HTML can't have onMouseOver or onClick event handlers in some browsers. How can my scripts respond when the mouse moves over an image? |
A1: | The easiest way to do this is to make the image a link by surrounding it with an <a> tag. You can include the BORDER=0 attribute to prevent the blue link border from being displayed around the image. |
Q2: | My image rollovers using onMouseOver work perfectly in Internet Explorer, but not in Netscape. Why? |
A2: | Re-read the previous answer, and check whether you've used an onMouseOver event for an <img> tag. This is supported by Internet Explorer and Netscape 6, but not by earlier versions of Netscape. |
Q3: | What happens if I define both onKeyDown and onKeyPress event handlers? Will they both be called when a key is pressed? |
A3: | The onKeyDown event handler is called first. If it returns TRue, the onKeyPress event is called. Otherwise, no keypress event is generated. |
Q4: | When I use the onLoad event, my event handler sometimes executes before the page is done loading, or before some of the graphics. Is there a better way? |
A4: | This is a bug in some older browsers. One solution is to add a slight delay to your script using the setTimeout method. You'll learn how to use this method in [Hour 10]. |
Quiz Questions
wax ka badalTest your knowledge of JavaScript events by answering the following questions.
1. | Which of the following is the correct event handler to detect a mouse click on a link?
|
2. | When does the onLoad event handler for the <body> tag execute?
|
3. | Which of the following event object properties indicates which key was pressed for an onKeyPress event in Internet Explorer?
|
Quiz Answers
wax ka badal1. | c. The event handler for a mouse click is onClick |
2. | b. The <body> tag's onLoad handler executes when the page and all its images are finished loading. |
3. | b. In Internet Explorer, the event.keyCode property stores the character code for each keypress. |
Exercises
wax ka badalTo gain more experience using event handlers in JavaScript, try the following exercises:
- Add one or more additional links to the document in [Listing 9.4]. Add event handlers to the script in [Listing 9.5] to display a unique description for each link.
- Modify [Listing 9.5] to display a default welcome message whenever a description isn't being displayed. (Hint: You'll need to include a statement to display the welcome message when the page loads. You'll also need to change the cleardesc function to restore the welcome message.)