Understanding the Flex Event propagation

Everybody knows that ActionScript is an event based language and that dispatching and listening events are the base of Flex development, so I’ll not emphasize it here. I will talk about something else, something more intriguing: event propagation. Most components communicate with others using events which conveys useful informations and data but only visual components (objects in the display list) can participate in what is called “event flow“. The event flow describes how an event object propagates through the display list in three phases: capturing, targeting and bubbling. Non-visual components are only concerned by what is called targeting phase.

Event propagation mechanism is rather counter-intuitive and often misunderstood by new Flex developers. I’ll try to explain some of the key principles that you should keep in mind when working with events.

The Flex event model is based on (a not so perfect implementation of) the Document Object Model (DOM) Level 3 events model. Visit the w3 site for more informations on the subject.

Take a look at the EventPropagation application :

Event Propagation

Event Propagation

As you can see, the blueBox (Vbox) is child of the EventPropagation (Application), the redBox (Vbox) is child of the blueBox and finally, “Click me!” button (Button) is child of the redBox :

EventPropagation > blueBox > redBox > button

There is something else that you can’t see in the application, but that is very important to know: Application has one parent, mx.managers.SystemManager, who has also one parent: flash.display.Stage (display list root). Both of them are DisplayObjects in the display list and thus participate in event flow. The final chain is as follows :

Stage > SystemManager > EventPropagation > blueBox > redBox > button

When you click on the “Click me!” button, the flash player initiates the event flow starting from the root element of the display list, Stage, goes down to the event dispatcher (Button) then it returns up again to the stage. It visits all of display objects between the root object and the event dispatcher, looking for registered MouseEvent.CLICK listeners in three phases.

If the “useCapture” CheckBox is checked, six event listeners are set for all display objects in our chain with useCapture property set to true, that means that listeners will handle only the capturing phase. Because of that behavior, useCapture should be named useCaptureOnly in my opinion.

Example:

this.addEventListener( MouseEvent.CLICK, onClick, true );

If the CheckBox is unchecked, all event listeners are removed then re-added with useCapture set to false (default behavior) thus the targeting and bubbling phases are monitored and the capturing phase is skipped.

note: To monitor all three phases, event listeners need to be registered with useCapture set to false AND true.

Example:

this.addEventListener( MouseEvent.CLICK, onClick );
this.addEventListener( MouseEvent.CLICK, onClick, true );

The status TextArea will display information about event propagation as it gathers it. Click on the button, the colored boxes or the application, with useCapture enabled or disabled and observe the status zone.

This image shows aforementioned three distinct event flow phases: capturing, targeting and bubbling:

Event flow

Event flow

Capturing Phase

Stage > SystemManager > EventPropagation > blueBox > redBox

If capturing is enabled, each item in the display list tree, starting from the root ancestor flash.display.Stage and going down the display list to the direct ancestor of the event dispatcher (target), is checked for event listeners. If one of those display objects is registered as an event listener for that specific triggered event, flash player creates the event object and pass it to the listener so it can handle it (event object is created when needed, not before, furthermore, once created its properties are changed as it propagates, no new event object is created). Event listeners registered for this phase can handle the event before it reaches its target.

Targeting Phase

> button >

During this phase, the event object has reached the event’s target and its listeners are invoked (if any). Event’s currentTarget and target properties are the same at this very moment.

Bubbling Phase

redBox > blueBox > EventPropagation > SystemManager > Stage

In bubbling phase, if bubbling is enabled (MouseEvent bubbles by default), events are emerging like Champagne bubbles on the surface taking the exact opposite path from capturing phase examining all event dispatcher’s ancestors starting from it’s direct parent and continuing up the display list to the flash.display.Stage root. Event listeners registered for this phase can handle the event after it has reached its target.

Why should I care ?

Most of the time, we don’t have to care about all this stuff. All that matters is the targeting phase: we add the listener for the event on the target dispatching object and that’s it ! But sometimes you will be confronted to a situation where you will need to intercept and stop the propagation of an event before it even reaches the dispatching object ( it sounds weird I know :) ).

Stopping the propagation

If an object is listening for this particular event, it can intercept it and stop its propagation if needed at any given moment in any phase. Two methods: stopPropagation() prevents the event to propagate after the current listener was executed, stopImmediatePropagation() prevents even the current object’s remaining listeners to execute.

An obvious example would be an itemRenderer in a List-based component. Maybe you don’t want to select the item in the list when clicking it, but still want to execute some logic inside the renderer ?

In the following example, the MouseEvent.DOWN is captured inside the itemRenderer and its propagation is stopped during the bubbling phase so it’s containing List will not be notified thus the related item will not be selected.

Example:
Please enable Javascript and Flash to view this Flash video.

Prioritize Events

If several listeners are listening a same event on a dispatcher, it is possible to define priority for each of them and thus control the order they are executed. Higher the priority, sooner the listener is triggered.

Example:

this.addEventListener( MouseEvent.CLICK, onClick3, false, -8 );
this.addEventListener( MouseEvent.CLICK, onClick1, false, 4 );
this.addEventListener( MouseEvent.CLICK, onClick2, false, 1 );

In this example, the handlers will be called in this order : onClick1, onClick2, onClick3.

That’s all folks !

Share this article:
  • Twitter
  • del.icio.us
  • Google Bookmarks
  • StumbleUpon
  • Digg
  • Technorati
  • Reddit
  • Live
  • Tumblr
  • Yahoo! Buzz

22 Comments

  1. Hi,

    thanks for your post…it’s very cool!

    can i ask you some questions?

    when capturing phase is set to false is always skipped.is it true? so only phases that are excuted are first targeting and then bubbling.

    How to add eventlisteners for bubbling phase when i have a generic event and not a MouseEvent?

    finally i can’t understand the difference between stopPropagation and stopImmediatePropagation()..

    Thanks a lot
    Regards Lorenzo

    • Hi,

      - setting «useCapture» to «false» while adding an event listener means that you will not listen during that phase (capturing phase always exists).

      - your generic event just have to bubble: dispatchEvent( new Event( “someEvent”, true ) );

      - stopPropagation() prevents processing of any event listeners in nodes subsequent to the current node in the event flow.
      stopImmediatePropagation() means same, plus currentTarget’s listeners are also not processed.
      more infos on the subject here:
      http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html#stopImmediatePropagation()

      cheers,
      Adnan

  2. David Leal

    Great article, Adnan. Flex events have always been a fuzzy business to me until I read this. Thank you.

    Cheers,

    David

  3. Thanks this post.

  4. Kirti Kishan

    I was always confused on the Flex event propagation. Thanks for providing in depth event mechanism.. especially regarding
    the event propagating to SystemManager class and then to the
    stage..!!

    Thanks a lot!

  5. this is a great post…..i was reading it through the live docs….but wasn’t able to really understand it…..but the sample you have…..that made it really clear……..

    thanks

  6. Jaychandra kushwaha

    Great post for the all who donot understand the Event phase. I realy appriciate this.

    Thanx Brd

  7. What a great blog you have! Super job!

  8. Kamaal Hasan

    Great article! you made understanding the Event Handling very easy.
    Keep up good work. Thanks a lot.

  9. Very good post. Got it cleared after a long time.

  10. Great job!!!

  11. Jaychandra kushwaha

    Its greate about the Event Phases and now i understood about the StopPropagation and stopImmediatePropagation().

    Thanx Man its greatness.

Trackbacks/Pingbacks

  1. Flex Hacking Series Part 1 – Event Model | Solution Hacker - [...] and a set of actions is taken in response. To understand it a bit more in detail, you can ...

Leave a Reply