Events And JavaScript: Part 3 - The Event Object

By HTMLGoodies Staff

written by Jon Perry

During normal program execution, a large number of events occur, so the event object is a fairly active object, constantly changing its properties.

Whenever an event fires, the computer places appropriate data about the event into the event object - for example, where the mouse pointer was on the screen at the time of the event, which mouse buttons were being pressed at the time of the event, and other useful information.

Skilled use of the event object can be very rewarding. It opens up possibilities for creating very intricate and complex programs.

The properties of the event object covered in this article are listed in the following table.

Event Object Property Description
SrcElement The element that fired the event
type Type of event
returnValue Determines whether the event is cancelled
cancelBubble Can cancel an event bubble
clientX Mouse pointer X coordinate relative to window
clientY Mouse pointer Y coordinate relative to window
offsetX Mouse pointer X coordinate relative to element that fired the event
offsetY Mouse pointer Y coordinate relative to element that fired the event
button Any mouse buttons that are pressed
altKey True if the alt key was also pressed
ctrlKey True if the ctrl key was also pressed
shiftKey True if the shift key was also pressed
keyCode Returns UniCode value of key pressed

Once we have received an event, we may need to know more about it, and this is the primary purpose of the event object. As we proceed through this article, you will see how we can successfully employ the event objects to overcome certain types of problems.

The first two properties on the list, srcElement and type, contain the data that effectively encapsulates our object/event pair.

srcElement and type

Of these two event object properties, you will probably find that you use srcElement a lot, and hardly ever use type, but the rare occasions that you do need to use type, it is very useful.

srcElement

The srcElement property returns the element that fired the event. This is an object, and has the same properties as the element.

So, if the we click on an image with an id attribute of 'Image1', and a src attribute of 'picture1.jpg', then event.srcElement.id will return 'Image1', and event.srcElement.src will return 'picture1.jpg', although this will be extended because the computer internally converts relative URLs into absolute URLs.

Similarly, the srcElement has a tagName property:

event.srcElement.tagName will return 'IMG'. And we can also read styles, so if the image has a style height of 100px, then event.srcElement.style.height will return '100px'.

type

The type property contains the other half of an object/event pair, the event name.

If the event we are capturing is the onclick event, the type will be 'click', and if the event is onkeypress, then type will be 'keypress'.

This is the same for non-physical events. If we capture and handle an onload event, type will be 'load', and so on.

To see this in action, we need a fairly complex HTML document.

<HTML>
<HEAD>
<TITLE>srcElement and type</TITLE>
<SCRIPT>
function catchevent() {
eventSrcID=(event.srcElement)?event.srcElement.id:'undefined';
eventtype=event.type;
status=eventSrcID+' has received a '+eventtype+' event.';
}
</SCRIPT>
</HEAD>
<BODY ID="MAINBODY" onload="catchevent();">
<DIV ID="FIRSTDIV" onclick="catchevent();" onmouseover="catchevent();" STYLE="position:absolute;top:10;left:10;height:100;width:200;background-color:red">
</DIV>
<FORM ID="MAINFORM" onmouseout="catchevent();"STYLE="position:absolute;top:150;left:10;height:50;width:200;background-color:yellow">
<INPUT TYPE="TEXT" ID="TEXTBOX" onfocus="catchevent();" onkeypress="catchevent();">
</FORM>
</BODY>
</HTML>

The code consists of a catchevent() function and several HTML elements which call the catchevent() function. Try activating different events over different elements - we get a running commentary on what is happening to our elements.

The catchevent() function reads the event object and determines the source element and the type of the event, then displays this information in the status bar.

We need to include the ternary operator '?' in the code, because some events are not particularly associated with any element. In this case, the onload event is not associated with the <BODY> element as we might expect.

If we use:

eventSrcID=(event.srcElement)?event.srcElement.id:'undefined';

then we are using the ternary operator to provide an alternative in the case of event.srcElement being false. This happens when no element claims to have fired the event.

For those readers who are not completely sure what the ternary operator is, it is shorthand for:

if (event.srcElement) eventSrcID=event.srcElement.id;
Else eventSrcID='undefined';

The technical syntax for '?' is:

variable=(condition)?action if true: action if false;

Once we have the catchevent() function, we add the HTML elements.

Every event that we wish to report on must be captured and sent to the catchevent() function.

This can cause slightly unexpected results - some events may seem mis-placed. This is because of event bubbling, covered in the second article in this series, which allows the event to continue up the element ownership hierarchy.

returnValue and cancelBubble

These two properties are associated with Event Bubbling and Cancelling Events, and were covered in part 2 of this series.

If we set the returnValue property to false, then the event is cancelled.

If we set the cancelBubble property to true, then event bubbling is cancelled.

clientX, clientY, offsetX, offsetY

After we know what caused the event, and what the event is, another set of very useful properties report the position of the mouse pointer when the event happened. These properties contain the mouse co-ordinates when the event was triggered.

(clientX, clientY) returns the position of the mouse pointer on the document, and (offsetX, offsetY) returns the position of the mouse pointer on the element.

The uses for these two co-ordinate systems are subtly different. The best one to select in each circumstance is the one that reduces the number of calculations we must perform.

clientX, clientY

We can use these to tie code in with the any movements of the mouse pointer. A typical example is for enhanced cursors.

An enhanced cursor involves attaching an element to the cursor.

<HTML>
<HEAD>
<TITLE>Enhanced Cursor</TITLE>
</HEAD>
<BODY onmousemove="enhancecursor();" >
<DIV ID="cursorplus" style="position:absolute;top:10;left:10;height:20;width:20;background-color:red"></DIV>
</BODY>
<SCRIPT>
function enhancecursor() {
cursorplus.style.posLeft=event.clientX-10;
cursorplus.style.posTop=event.clientY-10;
}
</SCRIPT>
</HTML>

In this example, the mouse pointer now has a red square attached to it.

Notice that the script element is placed after the body element. This is because the enhancecursor() function uses the element 'cursorplus', which needs to have be defined before the script will understand what 'cursorplus' means.

Once we have defined the 'cursorplus' <DIV> element, we attach it to the cursor by using the enhancecursor() function.

This function changes the left and top coordinates of the <DIV> element to that of the onmousemove event coordinates, and we offset the values slightly to ensure that the enhanced cursor is central.

offsetX, offsetY

These properties return values based on a coordinate system that is internal to the element.

There are several uses for these properties, They can save time and they can provide localised precision for mouse-based code. If we want a co-ordinate for inside an element, we do not particularly want to have to calculate these values from the client system and then subtract the left and top properties. This would prove to be very cumbersome especially if we also wanted to move the element.

Here is an example that demonstrates how these co-ordinates work.

<HTML>
<HEAD>
<TITLE>Offsets</TITLE>
<SCRIPT>
function statusreport() {
status='offsetX : '+event.offsetX+', offsetY : '+event.offsetY;
}
</SCRIPT>
</HEAD>
<BODY>
<DIV onmousemove="statusreport();" style="position:absolute;top:100;left:100;height:200;width:200;background-color:blue"></DIV>
</BODY>
</HTML>

When we move the mouse pointer over the <DIV> element, the local co-ordinates (the position of the mouse pointer relative to the element) are displayed in the status bar.

If we change the function to:

<HTML>
<HEAD>
<TITLE>Offsets</TITLE>
<SCRIPT>
function statusreport() {
status='offsetX : '+event.offsetX+', offsetY : '+event.offsetY+' ; clientX : '+event.clientX+', clientY : '+event.clientY;
}
</SCRIPT>
</HEAD>
<BODY onmousemove="statusreport();">
<DIV style="position:absolute;top:100;left:100;height:200;width:200;background-color:blue"></DIV>
</BODY>
</HTML>

We can see the relationship between the two co-ordinate systems.

Note that in the second example, we have moved the event handler from the <DIV> element to the <BODY> element. This allows us to demonstrate the different element ownership and event firing properties of a document, and we can observe the differences in the co-ordinate systems in more detail.

Next we look at what else was happening when the event was triggered.

button, altKey, ctrlKey, shiftKey

This collection of properties record which mouse buttons were pressed, and if any of the alt key, the ctrl key or the shift key were pressed when the event was triggered.

Once the green box is displayed, try clicking on it with a variety of mouse buttons, and while pressing a selection of the above keys.

<HTML>
<HEAD>
<TITLE>Buttons and Keys</TITLE>
<SCRIPT>
buttonname=new Array('Left','Right','','Middle');
function buttoninfo() {
message='button : '+buttonname[event.button-1]+'\n';
message+='altKey : '+event.altKey +'\n';
message+='ctrlKey : '+event.ctrlKey +'\n';
message+='shiftKey : '+event.shiftKey +'\n';
alert(message);
}
</SCRIPT>
</HEAD>
<BODY>
<DIV onmousedown="buttoninfo();" style="position:absolute;top:100;left:100;height:200;width:200;background-color:#00FF00"></DIV>
</BODY>
</HTML>

The four key components of this program are the four properties.

event.button
event.altKey
event.ctrlKey
event.shiftKey

The button property returns:

Event.button value Description
1 Left Mouse Button
2 Right Mouse Button
4 Middle Mouse Button

The other three key properties return true if the key was pressed, and false otherwise.

As a mask for the button value, we use the buttonname array, which stores the words 'Left', 'Right', and 'Middle' in array positions 0,1 and 3.

The final event object property we shall look at is the keyCode property.

keyCode

The keyCode property holds the UniCode value of any key that is pressed.

The following program demonstrates this. Note that we must use onkeydown if we wish to display non-visible keys, such as Caps Lock or the cursor keys.

<HTML>
<HEAD>
<TITLE>keyCode</TITLE>
</HEAD>
<BODY onkeydown="displaykey();">
<INPUT TYPE="text" name="text1">
</BODY>
<SCRIPT>
function displaykey() {
text1.value=event.keyCode+' : '+String.fromCharCode(event.keyCode);
}
</SCRIPT>
</HTML>

When a key is pressed on the body of the document, the keyCode property is set. This program displays the keyCode value, and the UniCode character from the keyCode value.

Similarly, we can respond to a UniCode value. This program allows you to move the <DIV> element with the cursor keys.

<HTML>
<HEAD>
<TITLE>Cursor Mover</TITLE>
<SCRIPT>
function move() {
ek=event.keyCode;
if (ek==37) DIV1.style.posLeft-=5;
if (ek==39) DIV1.style.posLeft+=5;
if (ek==38) DIV1.style.posTop-=5;
if (ek==40) DIV1.style.posTop+=5;
}
</SCRIPT>
</HEAD>
<BODY onkeydown="move();">
<DIV ID="DIV1" style="position:absolute;top:100;left:100;height:20;width:20;background-color:#FFFF00"></DIV>
</BODY>
</HTML>

This code detects whether the keyCode property corresponds to a cursor key, and then performs an appropriate action.

We can also alter the keyCode property, which is useful to create encryptions.

<HTML>
<HEAD>
<TITLE>Encryption</TITLE>
<SCRIPT>
function encrypt() {
event.keyCode+=1;
}
</SCRIPT>
</HEAD>
<BODY>
<INPUT TYPE="text" name="text1" onkeypress="encrypt();">
</BODY>
</HTML>

And this finishes my discussion on events.

Hope you enjoyed it.

This article first appeared on WebDevelopersJournal.com.



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •