One of the questions about ActionScript 3 that I am most often asked is how to send arguments to a listener function along with an event.
To provide some background for this question, you could send argument data to a standard function like this?
function showMsg(msg:String):void {
trace(msg);
}
showMsg("Claire");
However, in an event listener, only one argument is allowed in the listener function: the argument responsible for receiving the event data. Using a standard mouse click listener as an example…
stage.addEventListener(MouseEvent.CLICK, showMsg, false, 0, true);
function showMsg(evt:MouseEvent):void {
trace("hello");
}
…the kind of question asked is, can you do something like this:
stage.addEventListener(MouseEvent.CLICK, showMsg, "hello",
false, 0, true);
function showMsg(evt:MouseEvent, msg:String):void {
trace(msg);
}
The answer is, not out of the box. The existing AS3 events do not provide for this capability. However, to answer Jim’s question, the best way to pass arguments with an event is to create your own event class by extending AS3′s Event class.
No-Class Alternatives
Before we get to the custom class, let’s look at a few lesser approaches for using dynamic data with events. In the following examples, I’ll take advantage of properties from an event, along with dynamic data, to show the use of both kinds of information. A MouseEvent instance includes a Boolean called shiftKey that indicates whether or not the shift key is pressed at the time the event is dispatched.
Note: Any time a trace() method is used to trace an empty string or new line, it is only used to visually differentiate one trace from another in the Output panel.
The first approach is to populate a variable and then use that variable inside the listener function. This is straightforward, but not very dynamic:
var msg:String = "Shift key was down:";
stage.addEventListener(MouseEvent.CLICK, doIt, false, 0, true);
function doIt(evt:MouseEvent) {
trace(msg, evt.shiftKey);
trace("");
trace(evt);
}
The second approach is to use a standard event to call an interim function that then calls the desired function, passing along any relevant information. In my opinion, this is the best out-of-the-box solution, but it is also more verbose:
stage.addEventListener(MouseEvent.CLICK, doIt, false, 0, true);
function doIt(evt:MouseEvent) {
doIt2("Shift key was down:", evt);
}
function doIt2(msg:String, evt:*) {
trace(msg, evt.shiftKey);
trace("");
trace(evt);
}
The last approach I’ll discuss in this post is to use an anonymous function within the addEventListener() method under the guise of elminating the interim function in the previous example. This is a bit ugly and problematic:
stage.addEventListener(MouseEvent.CLICK,
function(evt:MouseEvent){doIt(evt, "Shift key was down:")},
false, 0, true);
function doIt(evt:MouseEvent, msg:String) {
trace(msg, evt.shiftKey);
trace("");
trace(evt);
}
Looking at this format objectively, it’s not really any less verbose, it’s just crammed into one line. It’s also harder to read—particularly when the anonymous function requires more than one line to execute the desired functionality. Most importantly, however, anonymous functions can be a pain to work with and are hard (impossible?) to clean up after. With AS3′s memory management requirements, this is a headache you just don’t need.
Creating a Custom Event Class
For our needs, we’ll create a custom event class by extending Event. This gives us all the advantages of the parent class, including dispatching. Here is a basic example that I’ll explain bit by bit:
}
The class begins with the package declaration, and an import statement to tell the compiler where to find the Event class. The class declaration follows, extending Event.
The next line declares a public static constant, CUSTOM. This is the constant that will allow a scripter to specify this event, the same way you use CLICK to declare a click event of the MouseEvent class. These constants are strings and it’s best to specify something that will not conflict with another event string assignment (and, therefore, possibly trigger another event listener).
Next is a public property for any data you want to send with the event, such as the aforementioned shiftKey property found in the MouseEvent class. In this simple case, the value is typed using the asterisk, which will prevent type checking allowing any data type to be used.
It is largely a matter of preference whether you prefer to use public variables or getters and setters for accessing properties from outside a class. Many OOP advocates will insist that getters and setters are the only way to go. Others maintain that “headless/brainless” getters and setters (functions that don’t add any functionality, such as error checking, casting, or other manipulation) offer little value.
I leave it to you to decide. In the downloadable source files, I’ve provided two versions of the next custom event class discussed in this post (‘a practical example’) with which you can experiment. You need only swap the classes and everything will work the same way, regardless of which approach you prefer.
If this doesn’t mean anything to you, just stick with the version used in the examples (that uses public properties) until you learn more about getters and setters and determine your own personal preference on the issue. You can start looking into the idea with Chapter 6 of the book (OOP), which briefly demonstrates getters and setters in the Encapsulation and Composition sections.
The class constructor begins on line 11 and is very simple. It accepts as parameters, the event type, the custom argument, and the ability to bubble or cancel the event (the latter two, false by default). Only the custom argument is different from a standard event. It is placed second in the list of parameters so you can omit the last few parameters from the event dispatch. Their default values will be used if they are omitted. Similarly, if no new custom data is provided, it’s default value of null will be used. If the custom argument was placed at the end of the list (a logical place for new information), you would have to include values for all the optional parameters in the correct order, just to change the custom data argument.
The next line calls the super class to reap all of its benefits, passing along the type, bubbles and cancelable setting. Note that the argument is not passed on here because it’s not a feature of the extended Event
Additional Features
Theoretically, you can stop here but there are two important features that you should also include to make your class feature-complete.
clone()
On Line 21, our custom class overrides the clone() method of the parent class. This is necessary to insure that your event will behave properly if you ever need to redispatch it. The clone() method is called automatically for a built-in class but, when extending a class, you must account for the new features of your class and override the original method. Without including this override, none of the event attributes will carry through and you will receive an error. The source code that accompanies this post includes an example of redispatching the event. You can try the file with and without the function override to see how this might impact your project.
toString()
Finally, an “undersung” hero of the Event class appears on line 25. If you override the toString() method as well, including your class name, custom argument, and original event attributes (type, bubbles, and cancelable), your custom class info will appear in any trace of the event. This is handy for quick references to property names. For example, if you don’t override the method, and trace the event with a custom argument like this:
trace(new CustomEvent(CustomEvent.CUSTOM, “Claire”));
…you’ll get the following:
[Event type="custom" bubbles=false cancelable=false eventPhase=2]
All you know is that an Event of type “custom” was dispatched. However, if you override the method as shown, you get this:
[CustomEvent type="custom" arg="Claire" bubbles=false cancelable=false
eventPhase=2]
Not only do you know that you’re working with a CustomEvent, you also see the custom value you’ve added (arg=”Claire”).
Using the Custom Event
You can use the custom event like this, which will trace both the event and the custom argument that you send with the event:
this.addEventListener(CustomEvent.CUSTOM, onCustom, false, 0, true);
function onCustom(evt:CustomEvent):void {
trace(evt);
trace(evt.arg);
}
dispatchEvent(new CustomEvent(CustomEvent.CUSTOM, "Claire"));
A Practical Example
Now let’s look at a custom class at work. The following application is a very basic simulation of registering a user for something. We’ll be using a custom event class, UserRegistrationEvent. The interface requires a user name and age, and an optional employment status can also be provided. Upon an attempt to register, basic error-checking is performed. If the name field is empty, or the age provided is less than 18, a custom error event USER_REGISTRATION_ERROR, is dispatched, and a warning string is placed into the Result field. Otherwise, a custom complete event, USER_REGISTRATION_COMPLETE, is dispatched and each of the custom values carried with the event is placed into the field. For demo purposes, the full event is added to the field in each case.
Here is the custom event class used. The only significant differences between this example and the earlier custom event class are the fact that UserRegistrationEvent has two event constants (instead of one), and three custom values (instead of one).
}
And here is the relevant code that checks the form input and dispatches the appropriate event (with explanations to follow the script):
}
Lines 2 through 13 make up the listener for the Registration button in the form. The function converts the age text submission to an integer and checks to see if the age is over 18 and the name field is not empty. If these two tests pass, a registration complete event is dispatched, sending the name, age, and employment status with the event. If the tests fail, a registration error event is dispatched.
Lines 16 through 25 comprise the listener for the registration complete event. It places four pieces of information into the text field: the user’s name, age, and employment status, followed by the entire event for illustration purposes. (Line feeds are added along the way for clarity.)
Lines 28 through 36 contain the listener for the registration error event. It replaces the contents of the Result field with an error message and the complete event.
Note: The source code places the data in the text field but traces the event to the Output panel for additional separation of functionality. It also includes additional code to control the checkbox, which is irrelevant to this tutorial.
Example Source Code
Download Passing Arguments with Events (40.8 KB, 780 hits)
The source code that accompanies this post contains several files. Flash users should start with a set of FLA files (saved in CS3 format for maximum compatibility), including the example shown herein. In this set are a simple proof of concept, the basic UI example above, and a UI example that shows the importance of using the clone() method when redispatching events.
I’ve also included a set of class-only files, moving the FLA-based material to a class so users of other coding environments can take advantage of the examples. Furthermore, the classes can be used as document classes by Flash users, if preferred. Both the single dispatch and redispatch examples are included.
Finally, two versions of the custom event have been included, as explained earlier in the post. The version used with the example uses public properties for simplicity, but another version using getters and setters has also been provided. If you are a fan of the latter, you can simply swap out the class and everything will work the same way.
You might also like
| Sending Data from AVM2 (AS3) to AVM1 (AS2/AS1) In Chapter 13, we showed how to use a LocalConnection to communicate between an AS3-based movie in Flash Player's... | Molehill FAQ! Today, Lee Brimelow came to the office and wanted to shoot a video about common questions regarding Molehill, here... | EventDispatcher in AS3 ActionScript 3 uses the EventDispatcher (flash.events.EventDispatcher) class for all event handling. This class... | Event Handing in AS3 Event handling is the process by which any sort of interactivity is created in ActionScript 3.0. This tutorial... |







Good explanation of custom event handling. I have always caught the currentTarget from the event listener and used a switch statement to process a function.
function clickHandler(event:MouseEvent):void{
switch(event.currentTarget.name){
case “btn1″ :
trace(“btn1 clicked”);
break;
case “btn2″ :
trace(“btn2 clicked”);
break;
}
}
Hello there! Quick question that’s entirely off topic. Do you know how to make your site mobile friendly? My blog looks weird when viewing from my apple iphone. I’m trying to find a theme or plugin that might be able to resolve this problem. If you have any suggestions, please share. Thank you!
hello you can use this FREE form http://crowdfavorite.com/wordpress/
be successful.