views:

2356

answers:

2

I have a series of MovieClips, held within several MovieClips, that dispatch a custom move event that I would like the stage to listen for and interact with. Is there a way to add to the stage (or any Object) an event listener for any event of one type, regardless of where it was dispatched from?

For instance, could I add to the stage an event listener to listen for any EVENT.COMPLETE that was dispatched from a child, or any of its children, or any of it's children's children?

+3  A: 

Hi Jeff,

What you are looking for is event bubbling. Set the third property of a new event to true to enable bubbling, and it will bubble up the display list, starting from the object dispatching the event to the stage. See the official docs for more info.

Tyler.

Edited: Change "starting from the stage" to "object dispatching the event"

Tyler Egeto
Perfect! I had always encountered the term "Bubbling" but I never understood *that's* what it refered to. +1
Jeff Winkworth
+2  A: 

Well, this is something I'll never understand... Why people always use bubbling events to capture events on the stage?

If you look at the doc, event is propagated from the stage to the target object (capture phase) and then bubbles if you enable bubbling.

So ... just use capture :

Main.as

package {
    import flash.display.Sprite;

    public class Main extends Sprite
    {
     public function Main()
     {
      var c:Circle = new Circle();
      var r:Rect = new Rect();
      c.addChild(r);
      addChild(c);
      addEventListener(CustomEvent.CUSTOM, customEventHandler, true);//don't forget third parameter to use capture
     }

     private function customEventHandler(e:CustomEvent):void
     {
      trace(e.eventPhase == EventPhase.CAPTURING_PHASE);//shows true
     }
    }
}

Circle.as

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    public class Circle extends Sprite
    {
     public function Circle()
     {
      super();
      init();
     }

     private function init():void
     {
      with(graphics)
      {
       beginFill(0xFF0000);
       drawCircle(25, 25, 50);
       endFill()
      }

     }
    }
}

Rect.as

package
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class Rect extends Sprite
    {
     public function Rect()
     {
      super();
      init();
     }

     private function init():void
     {
      with(graphics)
      {
       beginFill(0x000000);
       drawRect(0, 0, 25, 25);
       endFill();
      }

      addEventListener(MouseEvent.CLICK, mouseClickHandler);
     }

     private function mouseClickHandler(e:MouseEvent):void
     {
      dispatchEvent(new CustomEvent(CustomEvent.CUSTOM));
     }


    }
}

CustomEvent.as

package
{
    import flash.events.Event;

    public class CustomEvent extends Event
    {
     public static const CUSTOM:String = "custom";

     public function CustomEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
     {
      super(type, bubbles, cancelable);
     }

    }
}
PeZ
Hi PeZ, this is absolutly correct in a lot of cases, esspecially with mouse events. However in the situation described by the poster, bubbling needs to be set to true. This is because a manual event dispatch, Event.COMPLETE in this cases is starting from the child clip, not the stage, so there is no real capture phase that occurs.
Tyler Egeto
Tyler,I think your statement is wrong. As long as the object that dispatch an event is on the stage, there will be a capture phase, even if it's a manual event dispatch.Look at my example, this is a manual event dispatch, and bubbling is set to false in my custom event.
PeZ
PeZ, what type of event does your CustomEvent extend? MouseEvents bubble by default, while Events don't. Can you add this to your CustomEvent handler to see what it show's? Just in the nature of helping clarify this for everyone. trace(e.eventPhase == EventPhase.CAPTURING_PHASE);
Tyler Egeto
CustomEvent extends Event. I updated my code with the CustomEvent class.I've also added trace(e.eventPhase == EventPhase.CAPTURING_PHASE); in the event handler. The result is true.
PeZ
Ok thanks! I'm going to have to do some digging here, I've got a very simular situation with different results. I'll try track it down, very interesting.
Tyler Egeto
No problem :)If you have any question, feel free to ask me. Also, great work on the pv3d forum and your blog is interesting too!
PeZ
Ok, feeling kinda dumb right now, forgot to set useCapture to true... Ya so both are valid solutions, but useCapture is probably the better choice in this situation (tho not going to make a big difference) There is an importance difference between the two though, and it's worth looking up in the docs. Thanks for the correction PeZ!
Tyler Egeto
I have played around, and both are valid solutions. I am going to check out the documentation. Can someone explain in a nutshell why this is a better solution?
Jeff Winkworth