flash propagation_capture_phase
The capture phase
As we have already seen, the capture phase is the first phase of the event propagation process.
In reality, when we click on a button in the display list, all of the parent graphic objects of it are first notified about the event and can therefore broadcast it.
The following image illustrates a classic situation; a button is placed on the main timeline:
Once the user clicks on the myButton button the capture phase starts. The Flash player propagates the event from the top to the bottom of the hierarchy.
It is worth noting that the descent of the event stops at the direct parent of the button, the following phase will be the target phase.
The Stage object then the MainTimeline (root) are then notified about the event. If we then listen to the event being propagated on one of these, it is possible to intercept it.
By reading the signature of the addEventListener method we see the presence of the parameter useCapture:
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean =false):void
By default the addEventListener method does not subscribe the listener which has been passed to the capture phase. To benefit from it we need to pass the Boolean true value to the third parameter entitled useCapture.
The idea is to listen to the event on one of the parent objects of the target object:
objetParent.addEventListener ( MouseEvent.CLICK, clickButton, true );
Let’s now try it out. Create a new Flash CS3 document and create a button type symbol. Place an occurrence of it called myButton on the main stage.
In the following code we subscribe to a listener via the main timeline by activating the capture:
// subscription to the MouseEvent.CLICK event via the // main timeline for the capture phase addEventListener ( MouseEvent.CLICK, clickButton, true ); function clickButton ( pEvt:MouseEvent ) { // displays : [MouseEvent type="click" bubbles=true cancelable=false eventPhase=1 localX=13 localY=13 stageX=75.95 stageY=92 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0] trace( pEvt ); }
When the myButton button is clicked the MouseEvent.CLICK event starts its descent phase then reaches the main timeline which then broadcasts it. The clickButton listener function is then triggered.
Contrary to the hasEventListener method, the willTrigger method allows you to determine if a specific event is listened to by one of its parents during the capture or bubbling phase:
// subscription to the MouseEvent.CLICK event via the // main timeline for the capture phase addEventListener ( MouseEvent.CLICK, clickButton, true ); function clickButton ( pEvt:MouseEvent ) { trace( pEvt ); } // no listener was saved near to a button // displays : false trace( myButton.hasEventListener (MouseEvent.CLICK) ); // a listener was saved near to the parents of a button // displays : true trace( myButton.willTrigger( MouseEvent.CLICK ) ); // a listener is saved near to the main timeline // displays : true trace( willTrigger( MouseEvent.CLICK ) );
We therefore prefer using the willTrigger method in an event propagation context.
In the Event Model articles we discovered the target property of the event object corresponds to the original object of the environment that we generally call the target object.
Be careful, during the capture phase it is not the target object that broadcasts the event but the source of the event propagation. In our case, the MainTimeline object has broadcast the MouseEvent.CLICK event following an activation of the event propagation by our button.
The main interest of the capture phase is in the possibility of intercepting any event coming from a child via the parent.
The concept of nodes
When an event propagates, the notified graphic objects are called object nodes. To get the node with the propagating event, we use the currentTarget property of the event object.
The currentTarget property always returns the object on which we have called the addEventListener method.
Thanks to the target and currentTarget properties we can therefore know to which graphic object the event is heading as well as the currently affected node.
By testing the following code, we see that the main timeline is notified of the MouseEvent.CLICK event moving towards the target object:
// subscription to the MouseEvent.CLICK event via the // main timeline for the capture phase addEventListener ( MouseEvent.CLICK, clickButton, true ); function clickButton ( pEvt:MouseEvent ) { /* // displays : Target object : [object SimpleButton] Current node : [object MainTimeline] */ trace( "Target object : " + pEvt.target ) trace( "Current node : " + pEvt.currentTarget ); }
Even if we know graphic objects associated with the propagation of an event we cannot for the moment determine the phase in progress.
Does the currently broadcast event correspond to the capture, target or bubbling phase?
Determining the phase in progress
In order to know which phase an event corresponds to we use the eventPhase property of the event object.
During the capture phase the eventPhase property is 1, it is then 2 for the target phase and 3 for the bubbling phase.
In the same document that we previously listen to the MouseEvent.CLICK event near the main timeline during the capture phase:
// subscription to the MouseEvent.CLICK event via the // main timeline for the capture phase addEventListener ( MouseEvent.CLICK, clickButton, true ); function clickButton ( pEvt:MouseEvent ) { // displays : Phase in progress : 1 trace ( "Phase in progress : " + pEvt.eventPhase ); }
When we click on our button, the eventPhase property of the event object is 1.
To display information relative to the phase in progress we could be tempted to write the following code:
// subscription to the MouseEvent.CLICK event via the // main timeline for the capture phase addEventListener ( MouseEvent.CLICK, clickButton, true ); function clickButton ( pEvt:MouseEvent ) { // displays : Phase in progress : 1 if ( pEvt.eventPhase == 1 ) trace("CAPTURE PHASE"); }
Beware that as for the event subscription we use class constants to determine the phase in progress.
To do this the flash.events.EventPhase class contains three properties associated to each phase. By testing the value of each property we recuperate the corresponding values:
// displays : 1 trace( EventPhase.CAPTURING_PHASE ); // displays : 2 trace( EventPhase.AT_TARGET); // displays : 3 trace( EventPhase.BUBBLING_PHASE);
The following image shows the constants of the EventPhase class linked to each phase:
In taking that into consideration, we can rewrite the listener function clickButton in the following way:
function clickButton ( pEvt:MouseEvent ) { switch ( pEvt.eventPhase ) { case EventPhase.CAPTURING_PHASE : trace("CAPTURE PHASE"); break; case EventPhase.AT_TARGET : trace("target phase"); break; case EventPhase.BUBBLING_PHASE : trace("bubbling phase"); break; } }
All of this seems fairly abstract and we might wonder about its value in ActionScript 3 application development.
Thanks to this process we will make our code more flexible and optimized. We will find these benefits in the next article.
Worth remembering
- The CAPTURE PHASE starts from the Stage object to the parent of the target object.
- The CAPTURE PHASE doesn’t involve the parent objects.
- The target property of the event object always returns a reference to the target object.
- The currentTarget property of the event object always returns a reference to the object on which we have called the addEventListener method.
- During the propagation of an event, the target property doesn’t change and always makes reference to the same graphic object (the target object).
- The eventPhase property of the event object returns a value going from 1 to 3 associated with each phase of: CAPTURING_PHASE, AT_TARGET and BUBBLING_PHASE.
- To determine the phase linked to an event we compare the eventPhase property to the three constants of the flash.events.EventPhase class.
Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42





