To recap, we now have a display list and an event flow. We've seen how to add event listeners for any point in the event flow that we want. But so far, all our listener did was to trace out the message "clicked." We will now see how we can make use of the event object and the information it carries along with it.

The event parameter

When we write an event handler function (also known as the listener), we have to give it one parameter: a variable to store the event object that gets passed. What we name this variable is totally arbitrary. I like to always use the full word "event," but other people might prefer shorter forms like "evt" or even just "e." You could also call it "foo" if you want. Whatever name makes sense to you. But whatever name you choose, you have to make sure you also use that name in the body of the function too.  So, don't use "evt" in the parameter list but then use "event" in the function body--the names must be the same:

function listener(foo:MouseEvent):void {
    //make sure you use the same name from the parentheses above:
    trace(foo.target);
}

target and currentTarget

The event object is wonderfully useful, because of the information that it stores. It "knows" what object triggered it, and also what object the listener was originally added to:

  1. The object that triggered the event, that is, the object that the event happened to (in our case, the object that was clicked on with the mouse), is known as the target.
  2. The object that the listener was originally added to with addEventListener is known as the currentTarget.

Remember these two rules, and refer back to them if you ever get confused about target and currentTarget.

I touched briefly on target and currentTarget earlier, on the previous page. These are properties of the event object. When the event object is passed to our handler function, the parameter we provided in the parentheses takes on the value of the event object. So inside the handler function, we can make use of all the properties of the event object, including the target and currentTarget properties. So, to refer to the object that was clicked, we would use event.target, and to refer to the object that the listener was added to, we would use event.currentTarget. Sometimes target and currentTarget refer to the same object. When they do, it's  because the object being acted upon is the same object the listener was added to. Let's give this a real example.

In the starter file, find and delete this block of code that we added earlier:

stage.addEventListener(MouseEvent.CLICK, clickHandler, true);
function clickHandler(event:MouseEvent):void {
    trace("clicked");
}
menu.addEventListener(MouseEvent.CLICK, clickHandler, true);
button1.addEventListener(MouseEvent.CLICK, clickHandler, false);
menu.addEventListener(MouseEvent.CLICK, clickHandler, false);
stage.addEventListener(MouseEvent.CLICK, clickHandler, false);

We're going to start fresh, and just add one event listener, to the menu. So copy and paste these lines at the end:

menu.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    trace(event.target);
}

Notice that there is no third parameter supplied to the addEventListener function, so we are saying that we want to use the target and bubbling phases. (To tell you the truth, the capture phase is worth knowing about, and it has its uses, but you probably won't find it nearly as useful as the target and bubbling phases, which is no doubt why the architects of the event model decided that the useCapture parameter should be set to false by default). When you run this, you will get the listener being called if you click on the menu or any of the menu's children. Whatever you click on is the target. So when you click on the menu, the menu is the target, and your event handler function is notified during the target phase. If you click on one of the buttons, the button you clicked on is the target, and the event handler function is notified in the bubbling phase.

Press CTRL-ENTER to run this, and try clicking on the menu and the buttons. You will get a trace message to the output window that tells you what object is being clicked on. Pretty cool! Let's refine this a bit:

menu.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    trace(event.target);
    trace(event.currentTarget);
}

When you run this, whatever you click on is the target, like before. But now we've refined it to also tell us what is the currentTarget. In all cases, the currentTarget will be the menu. Why? Because it was the object that the listener was added to. Remember those two rules I told you about earlier! So the one case where target and currentTarget are the same is when the menu is being clicked on. When you run this, the output window will inform you of the following:

  1. When the menu is clicked on, the target is the menu, the currentTarget is the menu.
  2. When button1 is clicked on, the target is button1, the currentTarget is the menu.
  3. When button2 is clicked on, the target is button2, the currentTarget is the menu.

No matter what child is clicked on, or even if the menu itself is clicked on, the currentTarget is the menu, because that's the object the event listener was added to. When the menu is clicked on, it is both the target and the currentTarget. If it seems like I'm belaboring this point, it's because I want to make sure you fully understand target and currentTarget, as they are the most useful properties of the event object (for events that "bubble," anyway).

Next, replace the clickHandler function with this version instead:

menu.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    if(event.target == menu) {
        trace("menu clicked");
    }
    if(event.target == button1) {
        trace("button1 clicked");
    }
    if(event.target == button2) {
        trace("button2 clicked");
    }
}

Try running this. You can see that you now have complete control over handling a click on the menu, or any of its display object children. Now you can detect exactly what object was clicked on, and take whatever appropriate action you want. Naturally, you are going to want to replace those trace commands with something more useful. How about a menu of links, where the buttons take you to other web pages?

menu.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    if(event.target == menu) {
        trace("menu clicked");
    }
    if(event.target == button1) {
        navigateToURL(new URLRequest("http://www.google.com"), "_blank");
    }
    if(event.target == button2) {
        navigateToURL(new URLRequest("http://www.amazon.com"), "_blank");
    }
}

Okay, that's quite a bit more useful! You'll just have to use your imagination here as to what you want the buttons to do. Notice that so far, nothing much special happens when you click the menu. Let's fix that. Using our imagination, how about a menu that we can drag around the screen if the menu is being clicked, but take another action if one of the buttons is being clicked? Now that you understand the event flow for a mouse CLICK, here it becomes necessary to make use of another mouse event, too: MOUSE_DOWN. For the menu to start dragging, we will add an event listener for the MOUSE_DOWN event. MOUSE_DOWN represents the first half of a click. Try the following code:

menu.addEventListener(MouseEvent.CLICK, clickHandler);
menu.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
function clickHandler(event:MouseEvent):void {
    if(event.target == menu) {
        event.target.stopDrag();
    }
    if(event.target == button1) {
        navigateToURL(new URLRequest("http://www.google.com"), "_blank");
    }
    if(event.target == button2) {
        navigateToURL(new URLRequest("http://www.amazon.com"), "_blank");
    }
}
function downHandler(event:MouseEvent):void {
    if(event.target == menu) {
        event.target.startDrag();
    }
}

Notice that now the actions for a click on the menu have been changed. If the menu was CLICKED, we tell it to stop dragging. But we've also added an event listener to the menu for the MOUSE_DOWN event, with code to make the menu start dragging. But remember that the menu is a display object container. Similar to the CLICK event, the MOUSE_DOWN event will also fire when you MOUSE_DOWN on the container's children. So inside of that event handler function, we need to use an if statement to make sure that it's the menu that's being MOUSE_DOWN-ed on.

We could have alternatively used the following test in the if statement:

function downHandler(event:MouseEvent):void {
    if(event.target == event.currentTarget) {
        event.target.startDrag();
    }
}

If the event's target and the currentTarget are the same, then the object receiving the MOUSE_DOWN event is the same one that the event listener was added to, so it must be the menu. I just point this out to drive home the concept of target and currentTarget, and what they represent.

The Working Application

Anyway, here's the working application from the above code. You can actually click the buttons and actually drag the menu in this one. It's not just an illustration, it's a working program. So when you click the buttons and go to other web pages, be sure and come back, okay?


Download the finished fla file

When to use currentTarget instead of target

When should you use target and when should you use currentTarget in your event handler functions?

It's safe to just use target when the object you are adding the listener to is a display object but not a display object container. Or, if the object is a display object container, and you are sure that it doesn't contain other display objects. Remember that MovieClips are display object containers. So if you are programming a MovieClip instance by adding an event listener, and that MovieClip contains or might contain any other display objects (children), remember that the event you are adding a listener for will be active for those children, too.  Because of the event flow, of course.

So, for example, suppose I have a MovieClip instance I'm using for a button, with an instance name of button_mc, and it contains other display objects (even a dynamic textfield used as a label will qualify here), I would want to always refer to button_mc inside the handler function using currentTarget instead of target:

button_mc.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    event.currentTarget.x += 5;
}

This little bit of code (unrelated to our example fla file, by the way) will cause the button_mc object to move five pixels to the right when it is clicked. Since currentTarget was used instead of target, there is no danger of the code acting on the wrong object. If target were to have been used instead, and a click had been received by anything contained in mc_button, that other object would have moved instead of mc_button itself.

I'm sure that by now you should understand target and currentTarget completely. Hopefully this is also starting to spark some ideas of your own (a drop-down menu, perhaps?). It's certainly easier to add one event listener to a display object container than to add event listeners to every object inside of it, and that's the whole idea of events that "bubble."