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?
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.