Event bubbling is one of those Flash Player concepts that has a tendency of stumbling the noob. What makes it worse is that there's not too many readily available examples out there on why you would need it.
So...I have an example that I stumbled across the other day that might help in solidifying the necessity of knowing this concept.
What is event bubbling?
In a nutshell, when the Flash Player dispatches an event, the event starts at the Stage, then it works it's way down a parent-child hierarchy in the display list - called the capture phase - until it reaches the target of the event - called the target phase - and finally it bubbles back up to the Stage - called the bubbling phase - going back up the same path it came down during the capture phase. For more info, here's the livedoc.
Why would I care?
Oftentimes, we'll have an eventListener function where we reference certain properties of a target using the event.target.{propertyName} style syntax. For instance, we need to know which label was moused over based on id. Here's a code example:
XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
-
layout="vertical">
-
-
<mx:Script>
-
<![CDATA[
-
import mx.controls.Alert;
-
-
private function onMouseOver(p_evt:MouseEvent):void
-
{
-
Alert.show('You just moused over ' + p_evt.target.id);
-
}
-
]]>
-
</mx:Script>
-
-
<mx:Canvas id="my_canvas"
-
backgroundColor="0xFF0000">
-
-
<mx:Label id="my_label"
-
color="0xFFFFFF"
-
fontSize="24"
-
text="Roll Over Me"
-
width="100%"
-
height="100%"
-
mouseOver="onMouseOver(event)"/>
-
-
</mx:Canvas>
-
-
</mx:Application>
Basically, we are trying to access the id of the label when someone mouses over it. Problem is, when you test the app and mouse over the label, you receive the following error:
ReferenceError: Error #1069: Property id not found on mx.core.UITextField and there is no default value.
at main/::onMouseOver()
at main/__my_label_mouseOver()
UITextField...huh? I thought I moused over a label? Well, the label is a composite class that has an internal child of type...yes you guessed it UITextField. Based on the error, even though you added the event listener to the Label, the mouseOver event is actually dispatched by the UITextField which unfortunately does not have an id property...but why is that?
Reason being, if you look at the Flex framework code for the Label.as class on line 1233 you'll realize that the UITextField is as large as it's parent Label if you're not using padding. Since I'm not using padding in the example code above, mousing over the Label is immediately mousing over the UITextField, and that is why the dispatch happens from there.
How do I use event bubbling to my advantage?
So, I didn't really care about the UITextField...I care about the Label...namely the id value. The good news is I know that event bubbling will cause an event to propagate from the UITextField to the Label since the Label is it's parent. I also know that an event object has a property called currentTarget in addition to target.
Although the target property will always represent the UITextField no matter where I'm adding the event listener in the display list, the currentTarget property will represent the display list ancestor of the target that I have added the event listener to, in this case, the immediate parent ancestor - the Label.
So, here is the code from above...using currentTarget vs. target. You'll notice that no errors occur during the mouseOver, and I can access the properties of the object where the event listener was added as I was expecting:
XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
-
layout="vertical">
-
-
<mx:Script>
-
<![CDATA[
-
import mx.controls.Alert;
-
-
private function onMouseOver(p_evt:MouseEvent):void
-
{
-
Alert.show('You just moused over ' + p_evt.currentTarget.id);
-
}
-
]]>
-
</mx:Script>
-
-
<mx:Canvas id="my_canvas"
-
backgroundColor="0xFF0000">
-
-
<mx:Label id="my_label"
-
color="0xFFFFFF"
-
fontSize="24"
-
text="Roll Over Me"
-
width="100%"
-
height="100%"
-
mouseOver="onMouseOver(event)"/>
-
-
</mx:Canvas>
-
-
</mx:Application>