Monday, April 25, 2011

AS3 Event Bubbling outside of the Scenegraph/DisplayList

Hi just wondering if it is possible to take advantage of event bubbling in non display list classes in AS3.

For example in the model of an application where there is a City class that contains many Cars. What methods are there to attach an event listener to a City object and receive events that bubble up from the child Cars. To clarify The City and Car objects are not part of the display list, they are not DisplayObjects. So can bubbling be implemented outside of the display list somehow?

As far as I know, this is not possible without manually attaching event listeners to each Car object and re dispatching the event from the City object. Anyone else have a cleaner solution?

From stackoverflow
  • I'm not sure I am fully understanding, but when you create an event you can say that it bubbles and so when it dispatches it will bubble.

    http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html

    http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html#Event()

    I believe that would allow you to attach an event listener to your city for the right types of events and that would catch events thrown by cars. I haven't ever tried this though so I am not sure.

    update:

    Ah, I didn't realize this. You are correct. From the following link:

    http://livedocs.adobe.com/flex/3/html/help.html?content=events_08.html

    Capturing and bubbling happen as the Event object moves from node to node in the display list: parent-to-child for capturing and child-to-parent for bubbling. This process has nothing to do with the inheritance hierarchy. Only DisplayObject objects (visual objects such as containers and controls) can have a capturing phase and a bubbling phase in addition to the targeting phase.

    The only way I can see around this would be for you to register the child with the parent (the car with the city) every time a new one is added as a child. At that point you could add an event listener in the parent (city) and then re-dispatch an event from the parent (city) any time a event is handled from the child (car). Its ugly I know, and you would want to make sure you remove the event listener anytime that you remove a child, but it's the only real solution I can see.

    Brian Heylin : It bubbles, but only in the DisplayList, so only if it's dispatched from a DisplayObject, so then the event knows the children and parents of its current node, and so can travel up and down the tree. My imaginary City object is not part of the DisplayList.
    Ryan Guill : You're right, sorry about that. updated my answer with a possible solution, see what you think.
    Brian Heylin : Cools thanks Ryan, that's my clumsy solution too, I was hoping that there was maybe some sort of IBubbleTree interface that my model could implement and insert itself into a bubbling system. Although, now that I say it I could write that system myself for a generalized tree of IEventDispatchers.hmmm
  • I'm not sure what year this was posted, but I just discovered this and boy is it stupid. Why would bubbling be dependent on the display list? It seems to me that in building the Event model in AS3, Adobe should have implemented bubbling for any Classes. I need to pass data between disparate classes much more often than I need to make multiple display objects listen to each other. Not to mention it is much easier to reference display objects with the display list and root than it is to reference a dynamic instance used by a dynamic instance used by a dynamic instance (you get it). AS2's event model isn't that far away from what AS3's event model is after all

    Brian Heylin : Well yes, I find that bubbling is quite handy in the display list and I would like to utilize it in the model of an application too. But to satisfy this, your model classes would need to implement some sort of ITree or IHasParent interface system so that bubbling can take place automatically.
  • This class was my solution to that problem. Basically have your classes that would normally extend EventDispatcher instead extend BubblingEventDispatcher

    and then call the addChildTarget( target:BubblingEventDispatcher ) function to setup children that you can catch bubbled events from.

    This solution uses a sprite for each event dispatcher, but results in only 1 byte of extra memory usage per class

    package 
    {
     import flash.display.Sprite;
     import flash.events.Event;
     import flash.events.EventDispatcher;
    
     public class BubblingEventDispatcher extends EventDispatcher
     {
      //We have to use a sprite to take advantage of flash's internal event bubbling system
      private var sprite:Sprite;
    
      public function BubblingEventDispatcher()
      {
       //initialize our sprite
       sprite = new Sprite();
      }
    
      public override function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
      {
       sprite.addEventListener( type, listener, useCapture, priority, useWeakReference );
      }
    
      public override function dispatchEvent(event:Event):Boolean
      {
       return sprite.dispatchEvent( event );
      }
    
      //We must add child targets if we want to take advantage of the bubbling
      public function addChildTarget( target:BubblingEventDispatcher ):void
      {
       sprite.addChild( target.eventTarget as Sprite );
      }
    
      public function get eventTarget():EventDispatcher
      {
       return sprite;
      }
     }
    }
    
    Brian Heylin : Thanks for the response. I'm trying to move over to as3-signals at the moment, they also have a bubbling solution. This looks like it does the job for native Events. Nice work ;)

0 comments:

Post a Comment