Adept Software Development

Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.

http://marringtons.com

Monday, September 05, 2005

JavaScript Events - Part 2 - The Event Object

I've no intention to describe the event object in detail. After all, the subject could easily fill a book (and it has). Given the depth to which I use this object, I will describe the browser differences I've found and how I've overcome them.

Retrieving The Event Object

In Mozilla the event object is passed to the event function as the one and only parameter. IE, however, has a nasty global variable called event. Does that make IE single threaded? Probably. I don't want to even think of the havoc multiple threads running the same Java code would cause. I think Mozilla must handle it. I can set a breakpoint in an event manager and have setTimeout() JavaScript trigger while still stopped in the debugger.

When an event is set from a HTML tag, Mozilla hides the difference between the two schemes.

<a id="test" href="" onclick="runOnClick(event)">
<script>
alert( document.getElementById( "test"));
</script>

 

generates different implicit JavaScript depending on the platform. Mozilla will create:
function( event) { runOnClick(event); }

 

While IE will generate:
function() { runOnClick(event); }

 

This is quite clever. This means that events set in HTML tags can all get the event in the same way.

Events set on an element by JavaScript is not so lucky. They have to account for the different platforms:

document.getElementById( "test").onclick = function( evt)
  {
    evt = evt || event;
    ...
  }

 

This is the simplest working method for retrieving the event object. We try and pass it in. If the event caller does not have an argument we use the global event object used by IE. For this reason we have to call the argument evt so as not to hide the global one called event.

The Event Target

The event target is the HTML element that captures the event. This isn't necessarily the element that event has set up. It's more often a child of that element. You can, for example, set an onclick event for a table. The target returned could be the TD cell element. IE does not have a target field in it's event object. It uses srcElement instead. The easiest way to normalise the object is to always have code like:
evt.target = evt.target || evt.srcElement;

 

The Event Owner

The owner is the element that has the event that was triggered as an attribute. This is more often of use than the target, because it is the element we most associated with the even in our code. The problem is that IE does not provide any direct way to get this item. In Mozilla this refers to it, as does the field currentTarget.

There are a number of ways around this. If the event is set in the HTML you can call a function giving the ID of the calling element. More general code could walk up from the target element until it finds an element with the correct event. The most general solution uses some of the more obtuse properties of the JavaScript OO system to set the owner. If the event is set functionally, you can have an inner function that refers to the element being set that is an argument to the outer function. This becomes a dirty circular reference - so that the event data is not released when the outer function returns - but it does the job. This last method isn't obvious, so perhaps an example will clear it up. The code calls an action method with a normalised event object. Note that the element argument for the add function is used inside a event function that can be called at any arbitrary time later. It's magic.

Events.add = function( element, name, action)
  {
    ...
    element["on"+name] = function( evt)
      {
        evt = evt || event;
        evt.target = evt.target || evt.srcElement;
        evt.owner = element;
        action( evt);
      }
  }

 

1 Comments:

Anonymous Anonymous said...

Really Good Information

Regards
SBL Software

Thursday, February 05, 2009 4:14:00 pm  

Post a Comment

<< Home