Internet Explorer Event Model



Internet Explorer doesn't support DOM Level 2 Event Model, yet has a similar model. Because of the exclusive use of Internet Explorer, it's usually called Internet Explorer Event Model.

In Internet Explorer, registering multiple event handlers needs functions attachEvent and detachEvent. And notice that, when an event happens, the event handler will be called globally. That's to say that this will refer to the global object. Unfortunately, Internet Explorer Event Model doesn't a currentTarget property on an Event Instance used to return the element which triggers the event currently (such as that in DOM Level 2 Event Model).

To get the element triggering the event is binding the element in some way. One way is to bind this to the element. For example, through a proxy function:
function proxy(element, handler) {
    return function() {
        return handler.apply(element, arguments);
    };
}

The proxy function will return a function. The function calls the apply function of the parameter handler of the enclosing function, and uses the parameter element as the first argument. The parameter element accepts the element which your handler will bind this to.

With the above proxy function, we can rewrite the first example in DOM Level 2 Event Model. Because the model is for the exclusive use of Internet Explorer, the following examples only work in Internet Explorer.
<html>
    <head>
        <meta content="text/html; charset=UTF-8" http-equiv="content-type">
        <script type="text/javascript">
            window.attachEvent('onload', function() {
                function proxy(element, handler) {
                    return function() {
                        return handler.apply(element, arguments);
                    };
                }
                function handler() {
                    document.getElementById('console').innerHTML 
                         = 'Who\'s clicked: ' + this.id;
                }
                var btn1 = document.getElementById('btn1');
                btn1.attachEvent('onclick', proxy(btn1, handler));
                
                var btn2 = document.getElementById('btn2');
                btn2.attachEvent('onclick', proxy(btn2, handler));
            });
        </script>
    </head>
    <body>
        <button id="btn1">Button 1</button><br>
        <button id="btn2">Button 2</button><br>
        <div id="console"></div>
    </body>
</html>

Note that, the first parameter of attachEvent accepts the event name, started with a 'on'. The second parameter accepts the event handler. The difference from DOM Level 2 Event Model is, Internet Explorer has no capturing event, there's only bubbling event.

Some events have a default action. In Internet Explorer Event Model, returning false from an event handler, or setting the returnValue property of an Event instance false can stop the default action. For example, we can rewrite the second sample in DOM Level 2 Event Model as follows:
<html>
    <head>
        <meta content="text/html; charset=UTF-8" http-equiv="content-type">
        <script type="text/javascript">
            window.attachEvent('onload', function() {
                function proxy(element, handler) {
                    return function() {
                        return handler.apply(element, arguments);
                    };
                }
                var form = document.form1;
                form.attachEvent('onsubmit', proxy(form, function() {
                    if(this.data.value.length === 0) {
                        window.event.returnValue = false;
                    } 
                }));
            });
        </script>
    </head>
    <body>
        <form name="form1" action="fake.do">
            Input data <input name="data"><br>
            <button type="submit">Submit</button>
        </form>
    </body>
</html>

In Internet Explorer, the event property of window refers to an Event instance, not the first parameter of the event handler. Internet Explorer supports only event bubbling. The srcElement property of an Event instance is used to return the operated target element. For example, you can rewrite the third sample in DOM Level 2 Event Model to observe an event bubbling.
<html>
    <head>
        <meta content="text/html; charset=UTF-8" http-equiv="content-type">
        <script type="text/javascript">
            window.attachEvent('onload', function() {
                function proxy(element, handler) {
                    return function() {
                        return handler.apply(element, arguments);
                    };
                }
                function handler() {
                    document.getElementById('console').innerHTML += 
                      '<br><b>this.id:</b> ' + this.id + 
                      ', <b>srcElement.id:</b> ' + window.event.srcElement.id;
                }
                var body = document.getElementById('bodyId');
                body.attachEvent('onclick', proxy(body, handler));
                
                var div = document.getElementById('divId');
                div.attachEvent('onclick', proxy(div, handler));
                
                var btn = document.getElementById('btnId');
                btn.attachEvent('onclick', proxy(btn, handler));
            });
        </script>
    </head>
    <body id="bodyId">
        <div id="divId"><button id="btnId">Click me</button></div>
        <span id="console"></span>
    </body>
</html>

Clicking the button will cause the following result. It can be observed that the event propagate from inside to outside.
this.id: btnId, srcElement.id: btnId
this.id: divId, srcElement.id: btnId
this.id: bodyId, srcElement.id: btnId

The cancelBubble property of an Event instance is used to stop the event propagation. Stopping the event propagation of the above example can be as follows:
<html>
    <head>
        <meta content="text/html; charset=UTF-8" http-equiv="content-type">
        <script type="text/javascript">
            window.attachEvent('onload', function() {
                function proxy(element, handler) {
                    return function() {
                        return handler.apply(element, arguments);
                    };
                }
                function handler() {
                    document.getElementById('console').innerHTML += 
                      '<br><b>this.id:</b> ' + this.id + 
                      ', <b>srcElement.id:</b> ' + window.event.srcElement.id;
                      window.event.cancelBubble = true;
                }
                var body = document.getElementById('bodyId');
                body.attachEvent('onclick', proxy(body, handler));
                
                var div = document.getElementById('divId');
                div.attachEvent('onclick', proxy(div, handler));
                
                var btn = document.getElementById('btnId');
                btn.attachEvent('onclick', proxy(btn, handler));
            });
        </script>
    </head>
    <body id="bodyId">
        <div id="divId"><button id="btnId">Click me</button></div>
        <span id="console"></span>
    </body>
</html>