The Event Object

The event object is a very useful addition to the dom (document object model). The dom contains many objects that store a variety of information about the browser, the computer running the browser, visited urls, and so on. The event object stores data about events.

The Event ObjectThe History Of The World According To JavaScript

This is Javascript for IE5. See our policy on browser-specific JavaScript.

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.

 

Jon Perry is a Freelance Author and Programmer from the UK.

 Advanced JavaScript Event Handling

This is Javascript for IE5. See our policy on browser-specific JavaScript.

The first of these problems is discussed in this article. The second is explained in the next article, which covers the Event Object.

As an example for the basic ideas involved in this article, let us re-consider the bus problem I mentioned in the first piece. We may have designed our bus program to travel to the next destination when all the passengers are aboard and have paid. But what happens at the last stop on the bus's route?

Automatic event handling would immediately take us to the next stop on the list, probably the first stop in the list of stops. But we need greater control over the actual event. We want to ask if the bus is at the last stop on its route, and if it is, we need to stop it. This is advanced event handling.

This looks simple on the surface - but what if passengers get on at the last stop? And pay? What if people are still on the bus? Good programming would find answers to all of these problems.

Some problems do have solutions without advanced event handling, but if we are able to use advanced event handling, we will find that simple and practical solutions to these sort of problems are readily available.

Advanced Event Handling consists of three sections:

  • Cancelling Events
  • Event Bubbling
  • Mouse Capture

Cancelling Events stops them from happening. So, if you press a key, it cancels your onkeypress event.

Event Bubbling is slightly more involved, and uses the hierarchical nature of a web document. Elements have owners, or parents. An image on a document is owned by the document. This means that an event on the image creates an event for the document, and so on.

Mouse Capture is when we transfer all the events for a document to a single element, giving that element the capture.

We will look at all of these concepts in more detail in this article, beginning with Cancelling Events.

Cancelling Events

Cancelling Events allows us to prevent the event from being handled by the computer's inbuilt event handlers.

For example, when an onsubmit event is fired by, for example, someone pressing a submit button on a form, the CPU will receive the event and the computer will then begin the submission process.

This is the automated aspect of event handling that we wish to exercise greater control over. In the above situation, there may be a JavaScript routine that validates the form for required fields. If the form fails the validation testing, we do not want to send the form.

If the form is OK, we leave the event alone. The computer then receives a (submit button, onclick) pair, which automatically triggers the inbuilt mechanism for the form submission process (gather the data, roll into data packet and send to HREF address).

We can achieve this fine degree of control over the event with event cancelling.

The life span of normal event looks something like:

Event >>> Computer Event Handler

The Computer Event Handler may be nothing at all. For example, left-clicking a plain, unlinked image doesn't do anything.

With event handling, covered in my earlier article, we can add extra functionality to this process:

Event >>> Extra Event Handler >>> Computer Event Handler

With event cancelling, we can also break this chain:

Event >>> Extra Event Handler and Cancel Event

Because in this case we cancel the event, the Extra Event Handler is executed, but then we travel no further and we do not engage the Computer Event Handler

For the onsubmit example mention earlier, a flow chart for the code would look like:

onsubmit >>> Extra Event Handler formvalidation() function is called >>>
if Form Valid >>> onsubmit Computer Event Handler is called
else
if Form Not Valid >>> onsubmit event is cancelled

We now have branching capability inside our event handling model, which allows us to detect conditions and respond to them, intercepting the computer's normal flow.

Implementing an event cancel can be done in one of two ways. We can return false from a function called by an event handler, or use the event object's property returnValue.

return false

Using return false inside an event handler cancels the event. For example:

<HTML>
<HEAD>
<TITLE>Cancelling Hyperlinks</TITLE>
</HEAD>
<BODY>
<A HREF="c:" onclick="return false;">C drive</A>
</BODY>
</HTML>

Usually, the event sequence for a hyperlink is:

onclick >>> Hyperlink to URL in HREF attribute

But this example uses event cancelling to prevent this from happening.

When you click the hyperlink, nothing happens, because we have intercepted the onclick event before it reaches the anchor element's internal hyperlink function, and cancelled it. Now, when the onclick event is initiated, the sequence of events is:

onclick and Cancel event

There is another method we can use which achieves exactly the same effect, although there is an important difference.

event.returnValue

An event can be cancelled by setting the event.returnValue property from a function. If we set it to true, the event continues as normal, if we set it to false, the event is cancelled.

<HTML>
<HEAD>
<TITLE>Cancelling Hyperlinks with returnValue</TITLE>
</HEAD>
<BODY>
<A HREF="c:" onclick="event.returnValue=false;">C drive</A>
</BODY>
</HTML>

When we click the anchor (see example), we create an event object, which contains data relevant to the event that has just occurred. One of these properties is the returnValue of the event, which we can use to determine whether or not to cancel the event. If we set this to false, we are cancelling the onclick event.

Comparing return false to event.returnValue=false

The difference between return false and event.returnValue=false is subtle, and becomes apparent when we use the methods from inside a function.

When the interpreter reaches the JavaScript statement return false, the command is acted on immediately, and we are exited from any function that we are in.

Event handlers in this context are mini-functions.

Try this code to see the influence that the order of statements has on output.

<HTML>
<HEAD>
<TITLE>Order of Statments</TITLE>
</HEAD>
<BODY>
<A HREF="c:" onclick="alert('The Hyperlink has been cancelled.');return false;">C drive</A>
<BR>
<A HREF="c:" onclick="return false;alert('The Hyperlink has been cancelled.');">Drive C</A>
</BODY>
</HTML>

If we click 'C drive', we are told that the hyperlink has been cancelled.

If we click 'Drive C', we are not.

This is because as soon as the return false command is executed, control is restored to wherever sent it, and so the alert is never reached.

This is completely different to the event.returnValue=false version of the above program:

<HTML>
<HEAD>
<TITLE>Order of Statements with returnValue</TITLE>
</HEAD>
<BODY>
<A HREF="c:" onclick="alert('The Hyperlink has been cancelled.'); event.returnValue=false;">C drive</A>
<BR>
<A HREF="c:" onclick="event.returnValue=false;alert('The Hyperlink has been cancelled.');">Drive C</A>
</BODY>
</HTML>

In this case, both alerts are shown - the position of the event.returnValue=false statement makes no difference whatsoever. event.returnValue stores our INTENT for the event, but is not acted upon immediately.

Next, we shall look at event bubbling, which can allow us to simplify code and perform multiple operations with one event.

Event Bubbling

Event Bubbling is another advanced event handling technique. As I said at the beginning of this article, event bubbling uses the concept of element ownership.

With the development of the Document Object Model (DOM), all the elements on a web page are stored in a tree structure. This means that a document may own a form, which may own two radio groups, a text box and the two standard submit and reset buttons.

We can use the DOM to reference these elements, for example:

document.mainform['text1'].value

This statement can be used to read and to write to the text box, one of the many advantages offered by the DOM.

Through Event Bubbling, an onclick event on, say, a radio group, is 'bubbled' up to the form, and carries on to the document and ultimately to the window object, the topmost object of any browser.

This means that any event handlers we have defined for these higher-level objects are also activated.

To see this in action, we shall look at a form that demonstrates event bubbling.

<HTML>
<HEAD>
<TITLE>Event Bubbling</TITLE>
</HEAD>
<BODY onclick="alert('<BODY>');">
<FORM NAME="MAINFORM" style="background-color:yellow" onclick="alert('MAINFORM');">
<INPUT TYPE="TEXT" NAME="TEXT1" onclick="alert('TEXT1');">Name
<BR>
<INPUT TYPE="RADIO" NAME="R1" VALUE="RADIO1" onclick="alert('RADIO1');">Male
<BR>
<INPUT TYPE="RADIO" NAME="R1" VALUE="RADIO2" onclick="alert('RADIO2');">Female
</FORM>
</BODY>
</HTML>

Depending on where you click on the form (see example), you will get a different sequence of alerts.

As each element in our example has an onclick event handler, when we click a form element, the event activates:

(radio1, onclick)
(mainform, onclick)
(body, onclick)

If we just click the form, we only activate:

(mainform, onclick)
(body, onclick)

And if we only click the body, we only activate:

(body, onclick)

If these event handlers are not defined, then no action is taken. So, if (mainform, onclick) does not exist, then nothing would happen and the event would pass through mainform and continue onto the body.

We can also stop the event bubble, using event.cancelBubble.

event.cancelBubble

event.cancelBubble is very similar to cancelling events. We are allowed to 'burst' the bubble, and prevent it from carrying on up the ownership tree.

We can do this at any stage, and the event bubble will no longer exist.

Adapting the previous code, change the text box line of code to:

<INPUT TYPE="TEXT" NAME="TEXT1" onclick="alert('TEXT1');event.cancelBubble=true;">Name

All the other features are unaffected, but if you now click the text box, you will only get one alert box saying 'TEXT1' (see example).

We can use event bubbling to provide complex interactivity with a web page - we may have several functions all firing because of event bubbling. Imagine two <DIV> elements, one inside the other. We could use the event bubble to pass any event from the inner <DIV> element to the outer <DIV> element.

Or we can group elements together, which is useful if we have a lot of elements that use the same event handler. Instead of writing an event handler for every element, we can write one event handler for a containing element, and use the principle of event bubbling to pass any events to the containing element, which knows what to do.

Most advanced event handling involves the event object - this will be covered in the next article in this series. For now, we will look at another advanced event feature, namely Mouse Capture.

Mouse Capture

Mouse Capture is the strangest of the three concepts presented here, and can be quite tricky to visualize at first.

Mouse Capture passes all the events on a document to one element. So, if a given element has the mouse capture, then all the events that happen to the document are passed to this element.

This causes its own set of problems - for example, if all the events are passed to the element, then it is difficult to minimize or close the browser. These are window events, which are passed to the element with the capture.

So clicking the close button creates an (element, onclick) pair, and doesn't close the window.

To give an element the mouse capture, we use:

object.setCapture();

To release mouse capture from an element, we use:

object.releaseCapture();

Mouse capture is automatically released if certain events occur.

· A context-menu is opened (right-click)
· An alert, prompt or confirm method is issued in script
· The document is scrolled
· Another application gets the main focus.

Example code for this looks like:

<HTML>
<HEAD>
<TITLE>Mouse Capture</TITLE>
<SCRIPT>
function action() {
if (event.srcElement.id=='DIV1') DIV1.releaseCapture();
else DIV1.style.backgroundColor=Math.floor(Math.random()*16777216);
}
</SCRIPT>
</HEAD>
<BODY onload="DIV1.setCapture();">
<DIV ID="DIV1" onclick="action();" STYLE="position:absolute;top:10;left:10;height:100;width:200;background-color:red">
</DIV>
</BODY>
</HTML>

Clicking anywhere on the web page changes the color of the <DIV> element, except for clicking the <DIV> element, which releases the mouse capture from the <DIV> element, and allows you to resume normal operations (in practice, your browser may override the capture and release it after two or more clicks in a navigation area).

The code may be quite difficult to follow.

We create an HTML with a <DIV> element, and attach an onclick event handler to call the function action().

When the document has completely loaded, the onload event fires. We handle this in the program, and use the fact that all the elements are now loaded and initialised to give the <DIV> element the mouse capture.

Inside the action() function, we first check to see if the <DIV> element was clicked.

if (event.srcElement.id=='DIV1') DIV1.releaseCapture();
else DIV1.style.backgroundColor=Math.floor(Math.random()*16777216);

If so, we release the capture, if not, we randomly change the background color of the <DIV> element.

It is not completely necessary to program the code that releases the mouse capture, but this is how it is done.

A common use of mouse capture is to write pop-up menu code, where we open a pop-up menu by clicking an element, and we close it by clicking on the pop-up menu. To do this we need to know which element fired the event, and act upon this information. This code releases the mouse capture neatly and correctly.

With these advanced event-handling techniques, we have far greater control over the flow of a document, and we can use these features to produce complex procedures.

The final article in this series will look at the Event Object, which provides us with information about the event that occurred - where it occurred, which element fired it, which mouse buttons and keys were also pressed with the event, and other useful data.

Kaynak www.webdevelopersjournal.com/articles/jsevents3/jsevents3.html

 

Yorumunuzu Ekleyin


Yükleniyor...
Yükleniyor...