Pages

June 25, 2010

Event Propagation in Flex/ActionScript 3

Posted by Jeff Krueger
I came across a question in an interview the other day about event propagation and I thought it would be a good topic to blog about. Most of the time you never need to know the details of event propagation in Flex. All you normally do is setup your event listener inline on the component.

<mx:Button id="myButton2" label="test" click="myButton_click(event)"/> 
or by adding it explicitly to the component via ActionScript.

myButton.addEventListener(MouseEvent.Click, myButton_click);
Then you put your code in your eventListener function and you are done. But what is truly going on when the user clicks the button? Event propagation is made up of 3 parts.
  • Capturing
  • Targeting
  • Bubbling
Capturing and Bubbling are similar but work in opposite directions. When a user clicks on a button the capturing phase begins working its way down the DisplayList looking for items listening for the given event type with the useCapture option set to true. By default, useCapture is set to false. When it is set to false, the eventListener will be called during the bubbling phase. To add an eventListener for the capture phase you have to use the second method mentioned above passing in true for the third parameter. For example:

myButton.addEventListener(MouseEvent.CLICK, myButton_click, true)
When the capturing phase hits the point where the object from the displayList being evaluated is the one that initiated the event, it changes to the Targeting phase. This is known because the target and currentTarget variables will equal. This is explained more later. Once this is reached then the BubblingPhase begins for events that support bubbling.

During the BubblingPhase the displayList is walked in reverse and the system is looking for eventListeners for this event with the useCapture set to false (the default value). When they are found, those eventListeners are executed.

During both Capturing and Bubbling the event object has two variables that are important. One is target and the other is currentTarget. Target is always the object that initiated the event. The currentTarget is always the current item in the displayList being processed. You should always use currentTarget in your eventListener functions. That will always be the object that the eventListener is associated to. For example, if the user clicks on the text of the button. The target will be set to a label class since that is the sub component that was truly clicked on and initiated the event process. But when your eventListener function, attached to the button, is executed the currentTarget will be the button and the target will still be the label.

At any point in the Capturing or Bubbling process you can stop the process from continuing to the next item in the display list. There are two options, stopPropagation and stopImmediatePropagation. The difference between the two functions is that stopPropagation will allow other items at the same level in the displayList to receive the event, where the stopImmediatePropagation function stops right then.

Understanding the event propagation within Flex provides many options. You can control what components get to see events. You can change the behavior of items, mostly done when you are building custom components. You can reduce code by putting shared code in a common click function at a higher level. And, of course, the more you understand about how components interact the better custom components you can build.

3 comments:

Anonymous said...

I would not recommend writing an application where all the event handling is at the top most level. It all sounds useful and handy, trying doing it on a project with 20+ developers and very soon things will be intermingled.

Jeff Krueger said...

@Anonymous

I could not agree with you more and concidered not even putting it in the post. Only reason I did is most of all of the Adobe documentation uses that example.

Thanks

Jeff

Anonymous said...

I still don't construe the bubbling and capturing phase, why do we need this????

Any advantage in using capturing phase...