Tutorial 3: DOM Events

This tutorial will teach you how to handle events in the DOM from JavaScript. Knowledge of how to access the DOM from JavaScript is assumed. There are five short lessons, followed by one exercise.

It is highly recommended that you open your browser's JavaScript console now. When stuff doesn't work, there's usually an error printed in the console. The console is your friend.

Lesson 1: Traditional Model

The simplest way to make an element on a web page respond to an event is to set the element's .onclick property to a function. When the element is clicked, the function is executed. Within the function, the magic variable this will be the element that was clicked.

This is the HTML for the 'Execute' button below:

<button id="first">Execute</button>

Write some JavaScript code below that finds the button using getElementById, then sets the element's .onclick property to a function that sets the button's style.background property to '#ff8'.


 

Sample solution document.getElementById('first').onclick = function() {
  this.style.background = '#ff8';
};

Lesson 2: WC3 Event Model

The traditional model used above scales badly. Don't use it. Consider what would happen if two different libraries attempted to set an event handler on the same element. The second library would clobber the first. As JavaScript applications grew in size this became an increasing problem.

The addEventListener[?] function provides a more flexible method of handling events. The syntax is: element.addEventListener('click', yourFunction, false)

This is the HTML for the 'Execute' button below:

<button id="w3c">Execute</button>

Write some JavaScript code below that uses addEventListener to turn the button's style.background property to '#ff8' when it is clicked. For bonus marks, try adding a second, separate click handler that calls: alert('Hello')


 

Sample solution var button = document.getElementById('w3c');
button.addEventListener('click', function() {this.style.background = '#ff8';}, false);
// Bonus:
button.addEventListener('click', function() {alert('Hello');}, false);

Lesson 3: removeEventListener

Once you add an event listener, it will fire every time that event occurs. To stop listening, use the element.removeEventListener('click', yourFunction, false) function.[?] Note that you must provide removeEventListener with a pointer to the same function that you provided to addEventListener.

Here is an image of a star:  

This is the HTML for the above image:

<img id="once_star" src="star_on.gif">

Write some JavaScript code below that uses addEventListener to pop open an alert('Hello') dialog when the star is clicked. This handler should also self-destruct, by using removeEventListener to stop it from firing ever again.


 

Sample solution var img = document.getElementById('once_star');
var clickFunc = function() {
  alert('Hello');
  img.removeEventListener('click', clickFunc, false);
};
img.addEventListener('click', clickFunc, false);

Lesson 4: Event object

When an event handler is called, it is passed one argument: an Event[?] object. This object contains a bunch of useful information about the event, including which mouse buttons were used, whether the shift or control keys were pressed, etc. Click this star, and check the console to see the resulting event object:

Here is the JavaScript code for the above star:

var handler = function(e) {
  console.log(e);
};
document.getElementById('event_star').addEventListener('click', handler, false);

One of the most useful properties is target[?] which contains the DOM node that was clicked (or otherwise manipulated). This allows one to add a single event handler to a parent node, then deal with the appropriate node when an event is triggered.

Here is a table containing 100 stars:

This is the HTML for the table to the left:

<table id="star_table">
  <tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    ...
  <tr>
  </tr>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    <td><img src="star_off.gif"><td>
    ...
  <tr>
  ...
</table>

The goal of this lesson is to be able to mouse over the table and have the stars turn 'on' wherever the mouse goes using the 'mouseover' event (see demo). But instead of creating 100 event handlers, just create one handler on the table that uses the event's target property to change the src property of the correct star.


 

Sample solution var func = function(e) {
  if (e.target.src) {
    e.target.src = 'star_on.gif';
  }
};
document.getElementById('star_table').addEventListener('mouseover', func, false);

Lesson 5: preventDefault

The event object that is passed to handler functions also includes some useful methods that can effect what happens after handler finishes executing. One of these methods is preventDefault[?]. When called, this method prevents the browser from taking its normal actions in response to the event. An example of this is to supress the appearance of the browser's context menu.

Phone number:

Write some JavaScript code below that adds a keypress event handler to the input field (id is "phone"). If the user types something other than a number (look at the event's charCode property for the ASCII[?] value), then cancel the event by calling preventDefault.


 

Sample solution var func = function(e) {
  if (e.charCode < 48 || e.charCode > 57) {
    e.preventDefault();
  }
};
document.getElementById('phone').addEventListener('keypress', func, false);

Exercise: Context Menu

For this exercise we want to implement a custom context menu for Tux, the penguin.

This is the HTML for a menu which exists, but is currently hidden:

<div id="menu">
  <div id="option1">Photograph</div>
  <div id="option2">Rub belly</div>
  <div id="option3">Feed a fish</div>
</div>

Write some JavaScript code below that does as many of the following as you can:

  1. Add a click event handler to the penguin (his id is "tux") that makes the menu visible (style.display = 'block').
  2. Move the menu (e.g. style.left = '123px' and style.top = '123px') to the mouse's location. Use the event's pageX and pageY properties.
  3. Instead of using click, use contextmenu to detect the right mouse button.
  4. Supress the browser's own context menu.
  5. Add a click handler to the whole page (document.body) that hides the menu (style.display = 'none').
  6. Add event handlers to each option that does something.


Use the Intro to JavaScript forum to share your solution to this exercise and see other people's solutions.