4

Possible Duplicate:
What is event bubbling and capturing

I just learnt that in JS we have two event types: Capture and Bubble. Bubble can be used for avoiding the need of attaching the eventListener to all children; instead attach listener only to the parent and have it check the target. It sounds cool. And I tried out this example:

<div id="parent-list">
    <span>span1</span>
    <span class='target'>span2</span>
    <span>span3</span>
    <span>span4</span>
</div>

<script type="text/javascript">
document.getElementById('parent-list').addEventListener('click',function(e){
    if( e.target && e.target.nodeName=='SPAN' ){
        var classes = e.target.className.split(' ');
        for(var i=0; i<classes.length; ++i){
            if( classes[i]=='target' ){
                alert('Bingo! you hit the target.');
            }
        }
    }
});
</script>

But I haven't attached any listeners to the child spans. Yet the events on them are bubbling! So is bubbling the default event order in JS? Then in which scenario would the capture (top-down) be used?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Ivin
  • 4,435
  • 8
  • 46
  • 65
  • Not a direct duplicate but should answer your question about event propagation order. – Fabrício Matté Nov 06 '12 at 21:14
  • @FabricioMatte My question is about the default event ordering; not what they are. And I couldnt find anything like that in that post. Correct me if I'm wrong. – Ivin Nov 06 '12 at 21:16
  • 1
    Bubbling (innermost to outermost) is default in all modern browsers and is used by jQuery. Capture (outermost to innermost) is not as cross-browser and mostly old IE-proprietary AFAIK. – Fabrício Matté Nov 06 '12 at 21:19
  • @FabrícioMatté capturing is actually *NOT* supported by ghettoIE ***at all***, while W3C demanded compatibility with both. One of those things ghettoIE got right, along with CSS box-sizing based on borders, rather than content-only. – Norguard Nov 06 '12 at 21:42
  • @Norguard Yes you're right. I have to re-read some articles about default event propagation order again. `=]` – Fabrício Matté Nov 06 '12 at 21:45

2 Answers2

4

Imagine you have html that looks like this:

<div id="grandparent">
    <div id="parent">
        <button id="target"></button>
    </div>
</div>

And JS which looks like this:

function sayGrandpa (evt) { console.log("Grandpa"); }
function sayClicked (evt) { console.log("Clicked"); }

var grandparent = document.getElementById("grandparent"),
    target = document.getElementById("target");

grandparent.addEventListener("click", sayGrandpa, false);
target.addEventListener("click", sayClicked, false);

Bubbling vs Capture doesn't really have anything to do with what you're supposing, in that in both cases (on W3C-compliant browsers), you can use event listeners to attach to a parent, to listen to events which are triggered on a child.

The difference is that bubbling assumes that the chain of events starts at the target, and works its way back up through the chain of parents, like a bomb detonating at ground-zero, and sending a shockwave rippling outward.

Capturing starts at window (or at <html>), and goes down to the target element.

So when you use bubbling (more like rippling), any functions which are set directly on the element happen first, and any delegated functions, attached to ancestors, happen as the ripples go back up the chain.

When you use capturing, any delegated functions, attached to ancestors, happen BEFORE the event happens on the element.
So the grandparent element knows about a click, before target does.

So when you ask what order things happen in, things are pretty obvious:

When you set an event on grandparent which is captured and set a second event on grandparent which is bubbled, and set an event on target which is either, the order will be:

captured grandparent target bubbled grandparent

So when is it beneficial to have ancestors know about a click happening before the button that's actually being clicked?
Great question!

I'm sure somebody can think of something that isn't just a really-douchey way of making people miserable by hiding the thing they were supposed to be clicking on.

But the moral is that you expressly have to ask for it (setting the third parameter of .addEventListener to true).
Also, oldIE and others don't support capturing at all.

It's not really something which should be used in general.

Norguard
  • 26,167
  • 5
  • 41
  • 49
2

The default event order is browser specific.

Event capturing: the event handler of outer element fires first, the event handler of inner elements fires last.

Event Bubbling: the event handler of the inner element fires first, the event handler of outer element fires last.

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.

In the Microsoft model you must set the event’s cancelBubble property to true.

window.event.cancelBubble = true

In the W3C model you must call the event’s stopPropagation() method.

e.stopPropagation()

function doSomething(e)
{
    if (!e) var e = window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) e.stopPropagation();
}

http://www.quirksmode.org/js/events_order.html

Chase
  • 29,019
  • 1
  • 49
  • 48