Event Bubbling and Capturing

Event bubbling and capturing are two ways of event propagation in HTML DOM.

In bubbling the event is first captured and handled by the inner most element and then propagated to outer elements.

In capturing the event is first captured by the outer most element and propagated to the inner most element.

During the time of Netscape browser they were advocates of event capturing and Microsoft was from event bubbling school.

Both are part of the w3 standard. As per the standard first the event will capture it till it reaches the target then it will bubble up to the outer most element.

IE uses only event bubbling where as firefox supports both bubbling and capturing.

We can use the addEventListener(type, listener, useCapture) to register event handlers for bubbling and capturing phases. To use the capturing phase event handling pass the third argument as true.

Only event bubbling model is supported by all the major browsers. So if you are going to use event capturing still you need to handle event bubbling for IE. So it will easier to use event bubbling instead of capturing.

<div>
    <ul>
        <li></li>
    </ul>
</div>

If you take this structure and assume that a click event has happened in the li element.

In capturing model the event will be handled by the div first(click event handlers in the div will fire first) then in the ul then at the last in the target element li.

In bubbling model it is the opposite. In this model the event will be first handled by the li first and the ul and at the last by the div element.

The two event orders are radically opposed. Explorer only supports event bubbling. Mozilla, Opera 7 and Konqueror support both. Older Opera’s and iCab support neither.

If an element and one of its ancestors have an event handler for the same event, which one should fire first?
Not surprisingly, this depends on the browser.

The basic problem is very simple. Suppose you have a element inside an element

-----------------------------------
| element1                        |
|   -------------------------     |
|   |element2               |     |
|   -------------------------     |
|                                 |
-----------------------------------

and both have an onClick event handler. If the user clicks on element2 he causes a click event in both element1 and element2. But which event fires first? Which event handler should be executed first? What, in other words, is the event order?

Two models

Not surprisingly, back in the bad old days Netscape and Microsoft came to different conclusions.

  • Netscape said that the event on element1 takes place first. This is called event capturing.
  • Microsoft maintained that the event on element2 takes precedence. This is called event bubbling.

The two event orders are radically opposed. Explorer only supports event bubbling. Mozilla, Opera 7 and Konqueror support both. Older Opera’s and iCab support neither.

Event capturing

When you use event capturing

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

the event handler of element1 fires first, the event handler of element2 fires last.

Event bubbling

When you use event bubbling

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

the event handler of element2 fires first, the event handler of element1 fires last.

The developer, can choose whether to register an event handler in the capturing or in the bubbling phase. This is done through the addEventListener() method. If its last argument is true the event handler is set for the capturing phase, if it is false the event handler is set for the bubbling phase.

Suppose you do :

element1.addEventListener('click',doSomething2,true)
element2.addEventListener('click',doSomething,false)

If the user clicks on element2 the following happens:

  • The click event starts in the capturing phase. The event looks if any ancestor element of element2 has a onclick event handler for the capturing phase.
  • The event finds one on element1. doSomething2() is executed.
  • The event travels down to the target itself, no more event handlers for the capturing phase are found. The event moves to its bubbling phase and executes doSomething(), which is registered to element2 for the bubbling phase.
  • The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase. This is not the case, so nothing happens.

The reverse would be :

element1.addEventListener('click',doSomething2,false);
element2.addEventListener('click',doSomething,false);

Now if the user clicks on element2 the following happens:

  • The click event starts in the capturing phase. The event looks if any ancestor element of element2 has a onclick event handler for the capturing phase and doesn’t find any.
  • The event travels down to the target itself. The event moves to its bubbling phase and executes doSomething(), which is registered to element2 for the bubbling phase.
  • The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase.
  • The event finds one on element1. Now doSomething2() is executed.

What to use?

It depends on what you want to do. There is no better. The difference is the order of the execution of the event handlers. Most of the time it will be fine to fire event handlers in the bubbling phase but it can also be necessary to fire them earlier.

Cheers.

Leave a Reply

Your email address will not be published. Required fields are marked *