When an event happens, an Event instance collects information about the event. Unfortunately, this instance has different behaviors between standard browsers and Internet Explorer. In standard browsers, an Event instance will be the first argument of the event handler, whereas Internet Explorer uses window.event to refer it. In order to deal with cross-browser compatibility, the following code is common.
function handler(event) {
event = event || window.event;
...
}
event = event || window.event;
...
}
If the first parameter is undefined, the variable event will refer to window.event. This difference, however, is not the only one; properties of an Event instance also have differences. For example, the event target is the target property of an Event instance in standard browsers, but is the srcElement property of an Event instance in Internet Explorer.
Then, what's the event target? If you click on a button, the button is the event target. It's mentioned in Basic Event Model that this in the event handler will refer to the operated element. Well, why do we still need a property to point out the event target?
In fact, when an event happens, it'll propagate from the event target to its parents and call their respect event handler if there's one. This can be demonstrated by the following example:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
function handler(event) {
event = event || window.event;
var target = event.target || event.srcElement;
document.getElementById('console').innerHTML +=
'<br><b>this.id:</b> ' + this.id +
', <b>target.id:</b> ' + target.id;
}
document.getElementById('bodyId').onclick = handler;
document.getElementById('divId').onclick = handler;
document.getElementById('btnId').onclick = handler;
};
</script>
</head>
<body id="bodyId">
<div id="divId"><button id="btnId">Click me</button></div>
<span id="console"></span>
</body>
</html>
In the above example, using the object detection makes retrieving Event instances and event targets cross-browser. The button element is nested in the div and the body is the outer element of div. All of them have respective event handler. If you try to click the button, you will see the following result:
this.id: btnId, target.id: btnId
this.id: divId, target.id: btnId
this.id: bodyId, target.id: btnId
this.id: divId, target.id: btnId
this.id: bodyId, target.id: btnId
The invoked functions are not only the event handler of the button, but also those of the div and body. This is so-called "Event Bubbling". When an event propagates, it triggers on parents too. When their respective event handler is called, this will refer to that parent. You can observe this from the above result. And note that, you click the button, so the event target is the button. You can observer this from target.id.
You can take advantage of the event bubbling. Take UpdatingDOMTree-1.html in Updating the DOM Tree for example, you can set each created img element a click event handler, so that clicking the img will remove itself automatically. Nevertheless, if you use the event bubbling, setting the div element an event handler can archive the same purpose. For example:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
var images = document.getElementById('images');
images.onclick = function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
this.removeChild(target);
};
document.getElementById('add').onclick = function() {
var img = document.createElement('img');
img.src = document.getElementById('src').value;
images.appendChild(img);
};
};
</script>
</head>
<body>
<input id="src" type="text"><button id="add">Add</button>
<div id="images"></div>
</body>
</html>
If you want to stop event propagation, there are also different ways between browsers. In standards-compliant browsers, you should invoke the stopPropagation function of an Event instance. In Internet Explorer, you should set its cancelBubble property false. For example, stopping the event propagation of the first example can be done as follows:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
function handler(event) {
event = event || window.event;
var target = event.target || event.srcElement;
document.getElementById('console').innerHTML +=
'<br><b>this.id:</b> ' + this.id +
', <b>target.id:</b> ' + target.id;
if(event.stopPropagation) {
event.stopPropagation();
}
else {
event.cancelBubble = true;
}
}
document.getElementById('bodyId').onclick = handler;
document.getElementById('divId').onclick = handler;
document.getElementById('btnId').onclick = handler;
};
</script>
</head>
<body id="bodyId">
<div id="divId"><button id="btnId">Click me</button></div>
<span id="console"></span>
</body>
</html>
There're still several cross-browser problems on properties of an Event instance, will be mentioned afterword. Usually, we'll write a library to encapsulate those differences. Solving cross-browser incompatibilities is one of the main goals for most libraries.