Understanding The JavaScript Event Model (part 1)

The JavaScript event model hides a whole lotta surprises. Take a look.

The Next Step

If you're new to Web development, it's quite likely that you started off with JavaScript, the simple client-side scripting language that's supported in almost every Web browser. Maybe you've learnt a little bit of the language, and have understood how useful it is for basic browser detection and form validation tasks. And maybe you're wondering if there's more to the language, or if this is all she wrote...

Well, you're right to wonder, and right in thinking there's more. JavaScript comes with a fairly well-thought-out event model, one which can be exploited by a clever developer to perform fairly complicated tasks on the client side. This event model is one of the most fundamental things about the language - and, over the next few pages, I'm going to show you the basics of how it works. Keep reading.

Popeye() And Olive()

Simply put, the event model provides a way for a user to interact with JavaScript. It consists of two basic components, events and event handlers, which together define what happens when the user performs a particular action.

An event may be defined, very simply, as an action performed on a Web page - for example, clicking a button, moving the mouse pointer over a hyperlink and so on. Events are not necessarily generated by the user; they may be generated automatically by a piece of code as well.

An event handler, as the name suggests, handles an event - it defines the action to be taken by a script when a particular event (or type of event) occurs. Event handlers exist for most of the common events that are generated on a Web page, including mouse movement, mouse clicks, keyboard activity and page loads.

Here's a quick example that might make this theory a little clearer:

<body onLoad="thisFunction()">
...
</body>

If you were to translate the line of code above into English, it would read, "invoke the JavaScript function thisFunction() when the page loads". The event handler in this case is the onLoad handler, which can be used to perform specific actions when a Web page loads into the browser.

Another example, and one you've probably seen before, is

<a href="http://somewhere" onMouseOver="popeye()" onMouseOut="olive()"><img name="myimage" src="normal.jpg"></a>

Or, in English, "call the JavaScript function popeye() when the mouse pointer moves over this hyperlink, and the JavaScript function olive() when the pointer moves away from this hyperlink". These event handlers are most commonly used for image swaps...as you'll see very shortly.

Handling Things

Unlike some other programming languages, JavaScript doesn't require you to declare and define functions before they're called. So it's possible to invoke a function via an event handler, and define that function later on in your script - as the following example demonstrates:

<html>
<head>
</head>

<body>

<a href="http://somewhere" onMouseOver="popeye()" onMouseOut="olive()"><img name="myimage" src="normal.jpg"></a>

<script language="JavaScript">
function popeye()
{
    document.myimage.src='hover.jpg';
}

function olive()
{
    document.myimage.src='normal.jpg';
}
</script>
</body>
</html>

If modularizing your code into functions isn't really your cup of tea (why ever not?!), you can even have the JavaScript code accompany the event handler directly.

<html>
<head>
</head>

<body>

<a href="http://somewhere" onMouseOver="document.myimage.src='hover.jpg'" onMouseOut=" document.myimage.src='normal.jpg'"><img name="myimage" src="normal.jpg"></a>

</body>
</html>

JavaScript comes with handlers for most common user events...and quite a few uncommon ones. Here's a brief list of the more important ones.

onAbort - invoked when the user aborts the loading of an image by clicking the STOP button

onClick - invoked when the user clicks the specified object

onFocus - invoked when the target object receives focus

onBlur - invoked when the target object loses focus

onMouseOver - invoked when the user passes the mouse over the target object

onMouseOut - invoked when the mouse pointer leaves the target object

onSubmit - invoked when the user clicks the Submit button in a form

onChange - invoked when the user changes the contents of a text field

onSelect - invoked when the user selects the contents of a text field

onReset - invoked when the user clicks the Reset button in a form

onLoad - invoked when the target image or document is loaded

onUnload - invoked when the target image or document is unloaded

Let's now look at these in greater detail.

Red Alert

The "document" object refers to the document body, or the Web page itself. When this page loads into the Web browser (or when the browser leaves a page for a new one), an event is triggered, which may be captured and processed by appropriate JavaScript.

Here's a quick example, which pops up a dialog box when the page has finished loading.

<html>
<head>
<script language="JavaScript">
function redAlert()
{
    alert("Page successfully loaded");
}
</script>
</head>

<body onLoad="redAlert()">

</body>
</html>

The onLoad and onUnload event handlers for the "document" object are usually placed in the <body> tag. Once the page has finished loading, the onLoad handler is triggered, the redAlert() JavaScript function is invoked and an alert box is generated.

You can also run a function when the user leaves a Web page with the onUnload handler - as the following example demonstrates:

<html>
<head>
<script language="JavaScript">
function redAlert()
{
    confirm("Are you sure you want to leave this Web page?");
}
</script>
</head>

<body onUnload="redAlert()">

</body>
</html>

onLoad and onUnload can be used individually, or together.

In order to simplify the entire process and save time, you can place JavaScript code within the event handler invocation itself - as the following rework of the example above demonstrates:

<html>
<head>
</head>

<body onLoad="javascript:alert('This is simpler, right?')">
</body>
</html>

Yes, it is. Though only so long as you have a couple of lines of code to be executed - anything more complicated, and you're better off putting it into a function.

Mouse Hunt

JavaScript also defines event handlers for mouse movement, allowing you to do things as the mouse pointer moves over your Web page. The simplest - and most overused - example of this has to be the image swap, which involves changing an image when the mouse moves over it, and switching it back to the original when the mouse moves away from it.

Here's an example - whenever the mouse moves over the image "normal.jpg", it swaps into "hover.jpg", and back into "normal.jpg" once the mouse moves away from it.

<html>
<head>
</head>

<body>
<a href="http://somedomain.com" onMouseOver="javascript:document.myimage.src='hover.jpg'" onMouseOut="javascript:document.myimage.src='normal.jpg'">  <img name="myimage" src="normal.jpg">  </a>
</body>
</html>

Note that the event handlers must be attached to the hyperlink, not to the image enclosed within it - this is one of the most common errors newbies make.

Here's another example, this one demonstrating the onClick handler, which is triggered when the user clicks on a hyperlink:

<html>
<head>
</head>

<body>
<a href="http://somedomain.com" onClick="window.open('http//www.someotherdomain.com/ad.jpg', 'new')">  <img name="myimage" src="normal.jpg">  </a>
</body>
</html>

In this case, when the user clicks the link, not only does the browser attempt to connect to the specified resource, it also pops open a new browser window (displaying a different resource) via the onClick event handler.

Forty Two

JavaScript also includes a bunch of event handlers for forms and form elements, including text fields, selection lists, and buttons.

The onSubmit handler is triggered when a form is submitted. This handler is usually placed in the <form> tag. For example, consider the following form, which asks the user to enter a value into the text field and then pops up an alert with a message incorporating that value:

<html>
<head>
<script language="JavaScript">
function printMessage()
{
    alert("No, the answer is not " + document.forms[0].answer.value + ".\nEveryone knows the answer is 42.");
    return false;
}
</script>
</head>

<body>

<form action="submit.php" method="post" onSubmit="return printMessage()">
What is the answer?
<br>
<input type="text" name="answer">
<br>
<input type="submit" value="Tell me the answer!">
</form>

</body>
</html>

Of course, this isn't all that useful. Here's another, more practical example:

<html>
<head>
<script language="JavaScript">
// check name field
function checkName()
{
    // if empty, pop up alert
    if (document.forms[0].name.value == "")
    {
        alert("Please enter a valid name");
        return false;
    }
    else
    {
        return true;
    }
}

// check email field
function checkEmail()
{
    var flag;
    var str = document.forms[0].email.value;
    // regex to match email addresses
    var pattern = /^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/;
    var flag = pattern.test(str);

    if(!flag)
    {
        alert ("Please enter a valid email address");
        return false;
    }
        else
        {
        return true;
        }
}

// function to check all form data
function checkForm()
{
    if (checkName() && checkEmail())
    {
        return true;
    }
    else
    {
        return false;
    }
}

</script>
</head>

<body>

<form action="submit.php" method="post" onSubmit="return checkForm()">
Please enter your name.
<br>
<input type="text" name="name">
<p>
Please enter your email address.
<br>
<input type="text" name="email" size="25">
<br>
<input type="submit" value="Hit me!">
</form>

</body>
</html>

In case you haven't figured this one out yet, it pops up a warning dialog box if the user attempts to submit the form with an invalid name or email address - very useful when you want to cut down on mistyped or incorrect data being entered into your forms.

There's one important quirk of the onSubmit handler that you should know about, because I've used it in both scripts above. Once the onSubmit event handler is invoked, the browser decides whether or not to process the form further on the basis of the value returned by the event handler. If the handler returns false, the form is not processed further; if it returns true, the form is submitted to the named form processing script.

As the example above demonstrates, this comes in particularly handy when attempting to perform JavaScript-based validation of form data. It's possible to write a comprehensive set of JavaScript routines to verify the data entered into the form by the user, activate these routines via the onSubmit handler once the user submits the form, and only process the data in the form if the validation routines return a positive result. This is a technique used commonly on the Web to reduce the incidence of bad data entry.

Flavour Of The Month

You can also use the onFocus and onBlur handlers to perform actions when the user tabs into or out of a form field. Here's a quick example:

<html>
<head>
</head>

<body>

<form action="submit.php" method="post">
<input type="text" name="box" value="Click me" size="20" onFocus="document.forms[0].box.value='Now click outside'" onBlur="document.forms[0].box.value='Click me'">
</form>

</body>
</html>

In this case, every time the user clicks inside or outside the text field, either the onFocus() or onBlur() handler is triggered and an appropriate message displayed.

The next example reworks the one on the previous page to perform field validation when the user tabs out of each field on a form:

<html>
<head>
<script language="JavaScript">
// check name field
function checkName()
{
    // if empty, pop up alert
    if (document.forms[0].name.value == "")
    {
        alert("Please enter a valid name");
        return false;
    }
    else
    {
        return true;
    }
}

// check email field
function checkEmail()
{
    var flag;
    var str = document.forms[0].email.value;
    // regex to match email addresses
    var pattern = /^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/;
    var flag = pattern.test(str);

    if(!flag)
    {
        alert ("Please enter a valid email address");
        return false;
    }
        else
        {
        return true;
        }
}

</script>
</head>

<body>

<form action="submit.php" method="post">
Please enter your name.
<br>
<input type="text" name="name" onBlur="checkName()">
<p>
Please enter your email address.
<br>
<input type="text" name="email" size="25" onBlur="checkEmail()">
<br>
<input type="submit" value="Hit me!">
</form>

</body>
</html>

Another very useful event handler, especially in the context of forms, is one you've already seen before - the onClick handler. Consider the following example, which demonstrates it in the context of a radio button,

<html>
<head>
<script language="JavaScript">
function displayFlavour()
{
    for(i=0;i<document.displayForm.flavourSelect.length;i++)
    {
        if(document.displayForm.flavourSelect[i].checked)
        {
            alert("You picked " + document.displayForm.flavourSelect[i].value);
        }
    }
}
</script>
</head>

<body>

<form name="displayForm" action="submit.php" method="post">
Pick a flavour:
<br>
<input type="radio" name="flavourSelect" value="Strawberry" onClick="displayFlavour()">Strawberry
<br>
<input type="radio" name="flavourSelect" value="Raspberry" onClick="displayFlavour()">Raspberry
<br>
<input type="radio" name="flavourSelect" value="Chocolate" onClick="displayFlavour()">Chocolate
</form>

</body>
</html>

and this one, which demonstrates it in the context of a check box.

<html>
<head>
<script language="JavaScript">
function displayFlavour()
{
    for(i=0;i<document.displayForm.flavourSelect.length;i++)
    {
        if(document.displayForm.flavourSelect[i].checked)
        {
            alert("You picked " + document.displayForm.flavourSelect[i].value);
        }
    }
}
</script>
</head>

<body>

<form name="displayForm" action="submit.php" method="post">
Pick a flavour:
<br>
<input type="checkbox" name="flavourSelect" value="Strawberry" onClick="displayFlavour()">Strawberry
<br>
<input type="checkbox" name="flavourSelect" value="Raspberry" onClick="displayFlavour()">Raspberry
<br>
<input type="checkbox" name="flavourSelect" value="Chocolate" onClick="displayFlavour()">Chocolate
</form>

</body>
</html>

Linking Up

Finally, the onSelect and onChange handlers come in handy when dealing with selection lists and editable text fields. Consider the following example, which demonstrates them both:

<html>
<head>
</head>

<body>

<form action="submit.php" method="post">
Enter the name of your favourite superhero:
<br>
<input type="text" name="superhero" onSelect="alert('You just selected something!')" onChange="alert('You just changed something!')">
</form>

</body>
</html>

In this case, when the contents of the text field are selected, the onSelect handler is triggered - and when the contents are changed, the onChange handler is triggered and an appropriate message displayed.

The onChange handler is frequently used with drop-down selection lists, as in the following example:

<html>
<head>
<script language="JavaScript">
function goto()
{
    document.location.href = document.forms[0].url.options[document.forms[0].url.selectedIndex].value;
}
</script>
</head>

<body>

<form action="submit.php" method="post">
Select from the list below:
<br>
<select name="url" size="1" onChange="goto()">
<option value="http://www.melonfire.com/">Melonfire</option>
<option value="http://www.yahoo.com/">Yahoo!</option>
<option value="http://www.cnn.com/">CNN</option>
</select>
</form>

</body>
</html>

In this case, when the user makes a selection from the list, the onChange handler is triggered and the goto() function invoked. This function looks up the list to find the index of the currently-selected item, and uses the corresponding value to redirect the browser to the named URL.

Game Over

And that's about all I have for the moment. In this article, I taught you a little bit about the JavaScript event model, demonstrating the most common event handlers with code snippets and examples. I explained some of the most popular uses of these event handles, including image swapping and URL selection lists, and also demonstrated how they can be used, in combination with simple validation routines, to perform basic form validation on the client side.

If you're new to JavaScript, this article should have demonstrated some of the many uses to which clever developers can put this powerful client-side scripting language. In case you already knew all this, though, don't worry - I'll be back soon with an in-depth look at the internals of the JavaScript event model, explaining the intricacies of the Event object and how it can be used to add even more ammunition to your JavaScript armory. Till then, though, stay healthy...and keep practicing!

Note: All examples in this article have been tested on Windows 95 with Internet Explorer 5.x+ and Netscape Communicator 4.x+. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!

This article was first published on27 May 2002.