<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="vertical" verticalGap="10" 
    horizontalScrollPolicy="off" verticalScrollPolicy="off"
    backgroundColor="#333333" backgroundGradientAlphas="1,1"
    applicationComplete="onCreationComplete()"
    viewSourceURL="http://www.rubenswieringa.com/blog/wp-content/uploads/2007/flexeventbubbling/source/index.html">
    
    <mx:Script>
        <![CDATA[
            
            public const CANCEL:String = "cancel Event here?";
            public const EVENT_RECEIVED:String = "Event bubbled by";
            public const EVENT_RECEIVED_STAGE:String = "Stage has received Event";
            public const SOME_EVENT_TYPE:String = "someEventType";
            
            private function onCreationComplete ():void {
                // add listeners:
                this.container1.addEventListener(SOME_EVENT_TYPE, this.onEvent);
                this.container2.addEventListener(SOME_EVENT_TYPE, this.onEvent);
                this.container3.addEventListener(SOME_EVENT_TYPE, this.onEvent);
                this.stage.addEventListener(SOME_EVENT_TYPE, this.onEvent);
            }
            
            private function onEvent (event:Event):void {
                if (!(event.currentTarget is Panel) && !(event.currentTarget is Stage)){
                    return;
                }
                // figure out ID:
                var id:int = (event.currentTarget is Stage) ? 4 : int(event.currentTarget.id.slice(-1));
                // set status-text:
                this['status'+id].text = (id != 4) ? EVENT_RECEIVED : EVENT_RECEIVED_STAGE;
                // cancel Event if CheckBox was ticked and we're not bubbling at the Stage:
                if (id != 4 && this['cancel'+id].selected){
                    event.stopPropagation();
                }
            }
            
            private function fireEvent ():void {
                // clear textfields:
                this.clear();
                // create a bubbling and cancelable Event and dispatch it from within the Button:
                var event:Event = new Event(SOME_EVENT_TYPE, true, true);
                this.button.dispatchEvent(event);
            }
            
            private function clear ():void {
                this.status1.text = this.status2.text = this.status3.text = this.status4.text = "";
            }
            
        ]]>
    </mx:Script>
    
    <mx:Style source="assets/style.css" />
    
    <mx:HBox width="{container3.width}">
        <mx:Label id="status4" styleName="stage" />
        <mx:Spacer width="100%" />
        <mx:Button label="clear" toolTip="clear bubble-results" click="clear()" alpha="0.5" />
    </mx:HBox>
    
    <mx:Panel id="container3" title="great-grandpa container" layout="absolute" styleName="container3" width="300" height="300">
        <mx:HBox width="100%">
            <mx:Label id="status3" />
            <mx:Spacer width="100%" />
            <mx:CheckBox id="cancel3" toolTip="{CANCEL}" />
        </mx:HBox>
        
        <mx:Panel id="container2" title="grandpa container" layout="absolute" styleName="container2">
            <mx:HBox width="100%">
                <mx:Label id="status2" />
                <mx:Spacer width="100%" />
                <mx:CheckBox id="cancel2" toolTip="{CANCEL}" />
            </mx:HBox>
            
            <mx:Panel id="container1" title="daddy container" layout="absolute" styleName="container1">
                <mx:VBox width="100%" verticalGap="15" horizontalAlign="center">
                    <mx:HBox width="100%">
                        <mx:Label id="status1" />
                        <mx:Spacer width="100%" />
                        <mx:CheckBox id="cancel1" toolTip="{CANCEL}" />
                    </mx:HBox>
                    <mx:Button id="button" label="dispatch Event" click="fireEvent()" height="40" />
                </mx:VBox>
            </mx:Panel>
            
        </mx:Panel>
        
    </mx:Panel>
    
</mx:Application>