Examples and Code

We look at basic properties of events and event flow in AS3: target, currentTarget, localX, localY, as well as eventPhase. We provide a simple utility that displays those properties for MouseEvent.CLICK. Some results may surprise you, especially Event.target and localX, localY. Throughout event's propagation, localX and localY remain relative to the interactive display object that was clicked, and that object remains the event's target even if the object itself has no listeners registered to it. Click a screen shot or the link above it to open each example in a new window:

Example 1
Example 2

Download the Complete AS3 Code

The following zip package contains complete, well-commented code behind the examples:

Example 1: Event.target, localX, localY

In the first example (ev_example1.fla), we created on the Stage, stored in the Library, and linked to AS3 three MovieClips: BigBoard, BlueChild, and RedChild. (They could be Sprites or MovieClips created programmatically. It wouldn't affect the way events are dispatched.) We create instances, 'board', 'blueChild' and 'redChild' of those clips at runtime. 'board' is a child of 'this' - the MainTimeline which, in turn, is a child of the Stage, 'stage'). 'blueChild' is a child of 'board', 'redChild' is a child of 'board'.

We are adding listeners to MouseEvent.CLICK to 'board', 'blueChild', and 'stage'. We add the listeners the ususal way:

someObj.addEventListener(MouseEvent.CLICK,someHandler);

Hence, the third parameter, 'useCapture' is omitted, its value is left to 'false', by default. That means that the listeners will be triggered during the AT_TARGET phase of a click, if a clicked object is registered for MouseEvent.CLICK, or during the BUBBLING phase if an ancestor of the object is registered for MouseEvent.CLICK. None of the listeners will be triggered during CAPTURING phase.

What happens if you click the red rectangle? 'RedChild' has no listeners added to it. Its ancestors, 'stage' and 'BigBoard' do. This is the output in the output text field after a click:

As we see, the ancestors 'stage' and 'BigBoard' of 'RedChild' respond to the click in the BUBBLING phase. As the event propagates, the event's target remains 'RedChild' and event's localX and localY are all along the coordinates of the point at which the mouse click occured relative to the red rectangle; that is, to RedChild.

Note About Event's Phases: Most of events, including MouseEvent.CLICK, go through three phases: EventPhase.CAPTURING, EventPhase.AT_TARGET, and EventPhase.BUBBLING. During the CAPTURING phase, clicked object's ancestors are notified about the event (in order from the 'oldest' to the 'youngest'). One must not confuse 'being notified' with 'responding'. Only those will respond which have a listener to MouseEvent.CLICK attached to them with the useCapture set to true. In the case above, there are no such ancestors. During AT_TARGET phase the interactive object that was directly clicked will respond, if it has a listener attached. Again, it is not the case here. In the BUBBLING phase, all ancestors are notified once again (from 'youngest' to 'oldest') and those which have listeners with the parameter useCapture set to false will respond. In our case, these are BigBoard and stage.

This is what happens, if you click on the blue rectangle:

Here is the Timeline code in the first example:

var board:MovieClip = new BigBoard();

this.addChild(board);

board.x = 320;

board.y = 40;

var boardWidth:Number=board.width;

var boardHeight:Number=board.height;

var blueChild:MovieClip=new BlueChild();

board.addChild(blueChild);

blueChild.x=boardWidth;

blueChild.y=boardHeight;

var redChild:MovieClip=new RedChild();

board.addChild(redChild);

redChild.x=5;

redChild.y=boardHeight-redChild.height-5;

 

board.addEventListener(MouseEvent.CLICK,clickBoard);

 

function clickBoard(e:MouseEvent):void {

var ph:String;

if(e.eventPhase==EventPhase.CAPTURING_PHASE){

ph="CAPTURING_PHASE";

}

else if(e.eventPhase==EventPhase.AT_TARGET)

{

ph="AT_TARGET";

}

else if(e.eventPhase==EventPhase.BUBBLING_PHASE) {

ph="BUBBLING_PHASE";

}

else {

ph="";

}

txtOutput.appendText("\n");

txtOutput.appendText("\nboard-CLICK"+"\ntarget: " +String(e.target)+"\ncurrentTarget: " +String(e.currentTarget)+"\nlocalX, localY: " +String(e.localX)+ ", "+String(e.localY)+"\neventPhase: "+ ph);

verScrollBar.update();

verScrollBar.scrollPosition=verScrollBar.maxScrollPosition;

}

 

blueChild.addEventListener(MouseEvent.CLICK,clickBlue);

 

function clickBlue(e:MouseEvent):void {

var ph:String;

if(e.eventPhase==EventPhase.CAPTURING_PHASE){

ph="CAPTURING_PHASE";

}

else if(e.eventPhase==EventPhase.AT_TARGET)

{

ph="AT_TARGET";

}

else if(e.eventPhase==EventPhase.BUBBLING_PHASE) {

ph="BUBBLING_PHASE";

}

else {

ph="";

}

txtOutput.appendText("\n");

txtOutput.appendText("\nblue-CLICK"+"\ntarget: " +String(e.target)+"\ncurrentTarget: " +String(e.currentTarget)+"\nlocalX, localY: " +String(e.localX)+ ", "+String(e.localY)+"\neventPhase: "+ ph);

verScrollBar.update();

verScrollBar.scrollPosition=verScrollBar.maxScrollPosition;

}

 

stage.addEventListener(MouseEvent.CLICK,clickStage);

 

function clickStage(e:MouseEvent):void {

var ph:String;

if(e.eventPhase==EventPhase.CAPTURING_PHASE){

ph="CAPTURING_PHASE";

}

else if(e.eventPhase==EventPhase.AT_TARGET)

{

ph="AT_TARGET";

}

else if(e.eventPhase==EventPhase.BUBBLING_PHASE) {

ph="BUBBLING_PHASE";

}

else {

ph="";

}

txtOutput.appendText("\n");

txtOutput.appendText("\nstage-CLICK"+"\ntarget: " +String(e.target)+"\ncurrentTarget: " +String(e.currentTarget)+"\nlocalX, localY: " +String(e.localX)+ ", "+String(e.localY)+"\neventPhase: "+ ph);

verScrollBar.update();

verScrollBar.scrollPosition=verScrollBar.maxScrollPosition;

}

 

btnClear.addEventListener(MouseEvent.CLICK, clearText);

 

function clearText(e:MouseEvent):void {

txtOutput.text = "";

verScrollBar.update();

e.stopPropagation();

}

The button 'btnClear' clears the output text field. In order for the listener attached to 'stage' not to put text in the text field after the button is clicked, we stop propagation of the event, using e.stopPropagation() so the event does not bubble any further and the stage never hears it again.

Example 2

In Example 2, ev_example2.fla, we illustrate the CAPTURING phase by adding a second listener to stage with useCapture set to true:

stage.addEventListener(MouseEvent.CLICK,clickStageCapture,true);

 

function clickStageCapture(e:MouseEvent):void {

...........................

}

We also add a listener to the MainTimeline:

this.addEventListener(MouseEvent.CLICK,clickMainTimeline);

 

function clickMainTimeline(e:MouseEvent):void {

...........................

}

This is what happens, if you click on the red rectangle:

In Example 2, it is worth noticing that if you click on an empty (or non-ineractive) part of the Stage, stage responds but the MainTimeline does not.

Related Flash and Math Tutorials

For the analysis of stage versus MainTimeline, see The Display List, The Stage, and "addChild" in Flash CS3

For other mouse events, see AS3 MOUSE_OVER versus ROLL_OVER, MOUSE_LEAVE and Other Events

This tutorial was written by Barbara Kaskosz of flashandmath.com.

Back to Intermediate Tutorials              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.