flash propagation_bubbling

The bubbling phase

The bubbling phase is the last propagation phase. During this phase the event traverses the opposite direction from the capture phase, notifying each parent node of the target object. The direction of the event during this phase is compared to a bubble rising to the water’s surface. It is for this reason that it is called the bubbling phase. The rising event ultimately targets the stage object:

6.6.1.jpg

To subscribe a listener to the bubbling phase we call the add EventListener method on one of the parent graphic objects by passing the Boolean value false to the useCapture parameter:

myParentObject.addEventListener ( MouseEvent.CLICK, clickBubbling, false );

By reading the signature of the addEventListener method we see that the useCapture parameter is false by default:

public function addEventListener(type:
String, listener:Function,
useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean =
false):void

The subscription to the bubbling phase can be written without specifying the useCapture parameter:

objetParent.addEventListener ( MouseEvent.CLICK, clickBubbling );

This indicates that when we listen to an event for the target phase, the bubbling phase is automatically listened to.

The clickBubbling function will also therefore receive the MouseEvent.CLICK events coming from the children during their bubbling phase.

In the following example we listen to the MouseEvent.CLICK event at the time of capture and the bubbling phase in the container:

// number of windows
var lng:int = 12;
// creation of a container
var windowsContainer:Sprite = new Sprite();
// added to the display list
addChild ( windowsContainer );
var myWindow:Window;
for (var i:int = 0; i< lng; i++ )
{
myWindow = new Window();
myWindow.x = 7 + Math.round ( i % 3 ) * ( myWindow.width + 10 );
myWindow.y = 7 + Math.floor ( i / 3 ) * ( myWindow.height + 10 );
windowsContainer.addChild ( myWindow );
}
// subscription of the container for the capture phase
windowsContainer.addEventListener ( MouseEvent.CLICK, captureClick, true );
// subscription of the container for the bubbling phase
windowsContainer.addEventListener ( MouseEvent.CLICK, clickBubbling );
function captureClick ( pEvt:MouseEvent ):void
{
/* displays :
capture phase of the event: click
node in notification progress: [object Sprite]
*/
if ( pEvt.eventPhase == EventPhase.CAPTURING_PHASE )
{
trace("capture phase of the event: " + pEvt.type );
trace("node in notification progress: " + pEvt.currentTarget );
}
}
function clickBubbling ( pEvt:MouseEvent ):void
{
/* displays :
bubbling phase of the event: click
node in notification progress: [object Sprite]
*/
if ( pEvt.eventPhase == EventPhase.BUBBLING_PHASE )
{
trace("bubbling phase of the event: " + pEvt.type );
trace("node in notification progress: " + pEvt.currentTarget );
}
}

We’re going to go further by adding an automatic re-organisation of the windows when one of them is deleted.

To do this we modify the code by integrating an inertia effect in order to give each instance of the Window class a slowing down effect:

// modification of the animation speed
stage.frameRate = 30;
for (var i:int = 0; i< lng; i++ )
{
myWindow = new Window();
myWindow.destX = 7 + Math.round ( i % 3 ) * ( myWindow.width + 10 );
myWindow.destY = 7 + Math.floor ( i / 3 ) * ( myWindow.height + 10
);
myWindow.addEventListener ( Event.ENTER_FRAME, movement );
windowsContainer.addChild ( myWindow );
}
function movement ( pEvt:Event ):void
{
// inertia algorithm
pEvt.target.x -= ( pEvt.target.x - pEvt.target.destX ) * .3;
pEvt.target.y -= ( pEvt.target.y - pEvt.target.destY ) * .3;
}

Then we integrate the necessary logic in the captureClick and clickBubbling listening functions:

// number of windows
var lng:int = 12;
// creation of a container
var windowsContainer:Sprite = new Sprite();
// added to the display list
addChild ( windowsContainer );
var myWindow:Window;
// modification of the animation speed
stage.frameRate = 30;
for (var i:int = 0; i< lng; i++ )
{
myWindow = new Window();
myWindow.destX = 7 + Math.round ( i % 3 ) * ( myWindow.width + 10 );
myWindow.destY = 7 + Math.floor ( i / 3 ) * ( myWindow.height + 10
);
myWindow.addEventListener ( Event.ENTER_FRAME, movement );
windowsContainer.addChild ( myWindow );
}
function movement ( pEvt:Event ):void
{
// inertia algorithm
pEvt.target.x -= ( pEvt.target.x - pEvt.target.destX ) * .3;
pEvt.target.y -= ( pEvt.target.y - pEvt.target.destY ) * .3;
}
// subscription of the container for the capture phase
windowsContainer.addEventListener ( MouseEvent.CLICK, captureClick, true );
// subscription of the container for the bubbling phase
windowsContainer.addEventListener ( MouseEvent.CLICK, clickBubbling );
function captureClick ( pEvt:MouseEvent ):void
{
pEvt.currentTarget.removeChild ( DisplayObject ( pEvt.target ) );
}
function clickBubbling ( pEvt:MouseEvent ):void
{
var lng:int = pEvt.currentTarget.numChildren;
var graphicObject:DisplayObject;
var myWindow:Window;
while ( lng-- )
{
// recuperation of graphic objects
graphicObject = pEvt.currentTarget.getChildAt ( lng );
// if one of them is a Window type
if ( graphicObject is Window )
{
// we transtype it into a Window type
myWindow = Window ( graphicObject );
// repositioning of each occurrence
myWindow.destX = 7 + Math.round ( lng % 3 ) * ( myWindow.width
+ 10 );
myWindow.destY = 7 + Math.floor ( lng / 3 ) * ( myWindow.height
+ 10 );
}
}
}

We benefit from the bubbling phase in that the container reorganizes its child objects when one of them is deleted from the display list.

We will see in the article entitled Object Oriented Programming how our code could be even better.








Adobe Training center


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