Using standard DOM event methods for Internet Explorer

Published June 2nd, 2006 under JavaScript, Web Development
by Mashhoor Al Dubayan

If there’s one thing that frustrated me so much in JavaScript, it would be dealing with events (thanks to Internet Explorer). Most of the scripts handling events out there contain lots of browser and/or feature sniffing to decide which event method to use. For example, the following is a code excerpt from Sitepoints DHTML Utopia (the worst books I’ve read on the topic by the way):

if(window.event) // IE check
   el = window.event.srcElement;
if(e && e.target) // standard-compliant browsers
   el = e.target;

This seems like the only way for many JavaScript coders to deal with browser differences. That’s what i thought ,too, until i read Wrox’s Professional JavaScript for Web Developers (a must-get). The book’s author, Nicholas Zakas, introduces a much more convenient way for dealing with events. It basically involves using a cross-browser event object which creates DOM-like event methods for Internet Explorer.

Brief Explanation:

EventUtil.addEventHandler = function (oTarget, sEventType, fnHandler) {
    if (oTarget.addEventListener) {
        oTarget.addEventListener(sEventType, fnHandler, false);
    } else if (oTarget.attachEvent) {
        oTarget.attachEvent("on" + sEventType, fnHandler);
    } else {
        oTarget["on" + sEventType] = fnHandler;
    }
};

This function uses feature sniffing to add event listeners to elements. The first if statement checks for DOM-compliance, the second for IE-compliance and the elsestatement for any browser that’s neither IE nor DOM compliant. The removeEventHandle uses the same code, but with different function names.

EventUtil.getEvent = function() {
    if (window.event) {
        return this.formatEvent(window.event);
    } else {
        return EventUtil.getEvent.caller.arguments[0];
    }
};

This one also uses feature sniffing. If the browser is Internet Explorer (the one supporting window.event), then send the event to formatEvent. The else statement (for DOM-compliant browsers) sends the first argument of the function that called getEvent. I’ve never encountered this in other languages i’ve worked with, but in JavaScript, functions are apparently treated as objects (or let’s say functions are objects), therefore they have properties, and caller happens to be one of them. caller basically points to the function that called formatEvent, and argument is an array that contains the arguments sent to that function. The first argument in this case is the event, which is why we are retrieving arguments[0].

if (oEvent.srcElement)

Yet another feature sniffing to detect Internet Explorer. The original code used to detect Internet Explorer by analyzing it’s user-agent string which, as far as i know, isn’t always correct. Regardless of it’s accuracy, it needed much more code, so it’s not a good option in my opinion.

oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;

Since IE doesn’t support the charCode property ,which returns a number representing the character that was pressed, we’ll assign the keyCode of the event to it whenever the event type is keypress, otherwise it will be equal to zero.

oEvent.eventPhase = 2;
oEvent.isChar = (oEvent.charCode > 0);

I don’t quite understand why the original coder decided to assign ‘2′ to the eventPhase property. He said he did it because that’s all IE supports, but i don’t see how this can be useful (i left it there anyway). The charCode property returns a Boolean indicating whether the event produced a key character or not.

oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
oEvent.pageY = oEvent.clientY + document.body.scrollTop;

Next we need to create pageX and pageY equivalents for IE. These properties return the coordinates of the mouse relative to the document. IE supports clientX/clientY (return mouse coordinates relative to the window) and scrollLeft/scrollTop (returns the distance between the actual left/top edge of an element and it’s left/top edge in view). By adding these two we get the pageX/pageY of an event.

if (oEvent.type == "mouseout") {
    oEvent.relatedTarget = oEvent.toElement;
} else if (oEvent.type == "mouseover") {
    oEvent.relatedTarget = oEvent.fromElement;
}

The DOM relatedTarget property contains the element the mouse came from onmousover, and the element the mouse just went to onmouseout. IE doesn’t support relatedTarget, but we could still use its toElement and fromElement properties and a bit of code to acquire it.

oEvent.stopPropagation = function () {
    this.cancelBubble = true;
};

This one is pretty simple. It’s a small trick to use IE’s cancelBubble method within our new DOM-like stopPropagation method.

oEvent.target = oEvent.srcElement;
oEvent.time = (new Date).getTime();

And finally, we create a new method called target and assign srcElement to it. The other line just retrieves the event’s time.

I’ve made a simple example eariler that will hopefully clarify the usage of this object. From now on, you could start using standard DOM event methods for all modern browsers. It’s a developer’s dream come true!

References:

2 Responses to “Using standard DOM event methods for Internet Explorer”

  1. 1 John Vance

    oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
    oEvent.pageY = oEvent.clientY + document.body.scrollTop;

    This only works in IE quirks mode. In standards mode, you have to use document.documentElement.scrollLeft and document.documentElement.scrollTop.

  2. 2 Mashhoor Al Dubayan

    Hmm.. both procduced the same results under standards mode. Are you sure about that?

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>