So, what is the impact of this decision for web developers? IE9 and later versions, in Standards Mode, now support 3 event models: DOM Level 2 Events, the Microsoft Event Model, and the so-called DOM Level 0 or legacy event model. But to what extent are these models compatible? It turns out that both DOM2+ and MS events will be received by DOM0 handlers, but that DOM2+ events are not received by MS handlers or vice versa.
To illustrate the problem, consider the following example fragment:
Now consider what happens if the user clicks on the element. What happens if element.fireEvent('onclick') is called? What about element.dispatchEvent(clickevent)? If the user clicks the element, each of the three alert boxes appears in the order it was attached, exactly what you would expect. If element.fireEvent('onclick') is called, the DOM0 alert box appears first followed by the MS alert box and the DOM2+ alert never appears, regardless of the order in which they were registered. If element.dispatchEvent(clickevent) is called, the DOM0 alert box and the DOM2+ alert boxes appear in the order they were attached and the MS alert box never appears.
The Takeaway Message
For anyone in the unenviable position of needing to use/interoperate with frameworks that send events in both the Microsoft Event Model and the DOM Level 2 event model, my suggestion is to register event listeners using the legacy DOM Level 0 event model on Internet Explorer (note that the Dojo Toolkit appears to be the only framework which does this). This is the only event model which receives all events and by using it (rather than using both the DOM2+ and MS event models) events are only received once. I typically use code similar to the following:
In the above snippet, addLegacyEventListener can be any function that hooks up the listener to the DOM Level 0 event model. It can be as simple as element['on' + evtType] = listener, if there is ever at most one listener, or it can chain listeners in whatever style is preferred. Here is an example of an addLegacyEventListener function that I commonly use.