The JavaScript events paradigm has three implementations, but all
incompatible each other.
Let's try to put some order and to understand which one to use and when.
The original DOM 0 model
It's the base model, the first implemented, supported by all browsers, but
with big limitations.
In practice the event handler is handled like a property of the objects
that fires the event.
myButton.onsubmit = myObject.onsubmiteventhandler;
This means two important things:
- You cannot set more than one event handler for each event, the
last one that you set will substitute the previous one.
Note that it is possible to set the same event handler for
different events.
- If you use the
this
object inside the event
handler, this will refer to the firing object (myButton
in the example) and not to the one that handles the event (myObject
),
as it happens in the classical Windows programming.
If the previous limitations are not a problem, for compatibility reasons this
is without doubt the model to use.
The advanced DOM 2 model
It' the evolution of the previous one, but actually it's not supported by Internet
Explorer versions older than 9.
document.myForm.myButton.addEventListener("submit", function(e) { ...
}, false);
Or if you want to subscribe one object's method (note that Firefox allows to
use the first method to directly pass object's methods):
document.myForm.myButton.addEventListener("submit", function(e) {
myObject.onsubmiteventhandler(e); }, false);
Offers the following additional features:
- You can register more event handler for the same event.
- Every event handler has as a parameter an
Event
object with all significant event data.
- If you subscribe more times the same event handler, all
the subscriptions after the first one are ignored.
- The events are propagated in three consecutive phases:
- Capturing Pahase: the event is propagated from the
Document
objects following the descendants chain to the
final object that subscribed to the event, to verify if any ancestor has
set the event capturing (the third boolean event of addEventListener
specifies if the event handling has to occur during this phase).
- Target Node: the event is handled by the subscribed
object.
- Bubbling Phase: the event returns to the root node,
from the subscribed node to the
Document
object.
In every moment the propagation can be interrupted by any event handler
calling stopPropagation()
.
Regarding the this
object, unfortunately there's no standardization,
the most diffused interpretation is identical to the DOM 0 level.
Internet Explorer model
It's supported only by Microsoft's browsers, it's similar to DOM 2, but with
some important differences.
document.myForm.myButton.attachEvent("onsubmit", function(e) { ...
});
- I does not implement the Capturing Phase during event
propagation (in fact the third parameter is missing).
- If you subscribe more times the same event handler, this will
be invoked more times.
- The
Event
object is not passed as a parameter to the event
handler, but it's a global variable (window.event
): this
is not a problem because JavaScript programming it's single-threaded.
- The
this
object inside event handlers refers to
the global window
object.
Let's take a look now to a typical example about handling all these
implementations.
It happens frequently to subscribe an event handler for the page load
completion, but if we have to use the DOM 0 APIs, there will be the risk to
override another previously subscribed event handler. To solve this
situation use the following function.
function subscribeOnLoad(eventHandler)
{
if (typeof window.addEventListener != "undefined")
window.addEventListener("load", eventHandler, false);
else if (typeof window.attachEvent != "undefined")
window.attachEvent("onload", eventHandler);
else
{
if (window.onload != null)
{
var exsistingOnLoad = window.onload;
window.onload = function (e)
{ exsistingOnLoad(e); window[eventHandler](); };
}
else
window.onload = eventHandler;
}
};