Browse All Articles > Creating a custom event listener in AS3
I come across a lot of question about how to access things in the document class from a movieclip, or accessing something from a movieclip in the document class.
It took me a while to figure this out but once I did it makes life so much easier.
By creating a CustomEvent class and placing it in your own utils folder and setting up your AS3 class path, once you import the Custom Event, this is how you'd go about it.
your class would look something like this ...
package whatever.utils //change your package name as required
{
import flash.events.Event;
public class CustomEvent extends Event
{
public static const NOTIFY:String = "notify";
public var data:*;
public function CustomEvent(type:String, data:*, bubbles:Boolean = false, cancelable:Boolean = false){
super(type, bubbles, cancelable);
this.data = data;
}
}
}
to implement
say you have a nested movieclip that when it hits frame 5 you want to execute a function in the document class called callSomething();
when you add the movieclip in your document class
addChild(nameOfMovieClip);
//add the dispatcher
nameOfMovieClip.addEventListener(CustomEvent.NOTIFY, handleNotifyRoot);
//note the CustomEvent.NOTIFY part - you can add items in your CustomEvent class
Create a handleNotifyRoot method in your document class
function handleNotifyRoot(e:CustomEvent):void
{
trace(e.data.myData.toString());
}
in the movieclip when you want the event to trigger, you must dispatch the event
var varString:String = "clicked ball";
dispatchEvent(new CustomEvent(CustomEvent.NOTIFY, {myData:varString}));
you can pass anything to your custom event.
I hope this all makes sense.
Comments (9)
Author
Commented:Commented:
I just noticed they finish in Johannesburg on the 11th, then open in Cape Town on the 14th. So, if Johannesburg is better for you shoot me that email soon!
AreDubya
Commented:
Thumbs up for addressing custom events - too few know about this.
I have a few comments though.
1) I prefer using whatever.events - this is more aligned with the flash namespace structure
2) I like to use get and set functions - this way you can make data read-only
3) In most cases I would make the data value optional (data:*=null)
4) You should always override the clone and toSrting methods
While 1-3 is my personal likings the 4'th isn't.
// clone example:
var event1:CustomEvent=new CustomEvent(CustomEvent.NO
var event2:CustomEvent=event1.
trace(event1.data); // returns [object Object]
trace(event2.data); // without the override clone this will cause an error
// toString example:
var event:CustomEvent=new CustomEvent(CustomEvent.NO
addEventListener(CustomEve
dispatchEvent(event)
private function customEventHandler(e:Custo
trace(e);
// without: [Event type="notify" bubbles=false cancelable=true eventPhase=2]
// with: [CustomEvent type="notify" data=[object Object] bubbles=false cancelable=true eventPhase=2]
}
// CustomEvent class:
package whatever.events {
import flash.events.Event;
public class CustomEvent extends Event {
public static const NOTIFY:String = "notify";
private var _data:*;
public function CustomEvent(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false){
super(type, bubbles, cancelable);
_data = data;
}
override public function clone():Event {
return new CustomEvent(type, data, bubbles, cancelable);
}
override public function toString():String {
return formatToString("CustomEven
}
public function get data():*{
return _data;
}
}
}
Thanks and keep up the good work :)
Jakob E
Author
Commented:When I first started with AS3 I couldn't figure out how to achieve this and eventually arrived at this solution which worked well for me thus far. I should have mentioned it's how I do it but not necessarily the best way. Usually in the posts I do that but I was repeating myself so many times that I ended up doing this article.
1. explain #1 to me please
2. the get/set option sounds familiar from my Java days. My OOP knowledge and experience is limited.
3. making data null optional would make this much more generic thus better I agree.
4. why?explain.
Commented:
Hi Blue-Genie,
The reason why I like the whatever.events namespace structure
is that it matches the one used by flash - making it easier to remember.
import flash.events.Event
import whatever.events.CustomEvent
About the clone and toString overrides:
Event.clone() is used when re-dispatching an event (dispatchEvent(e)). If you don't add
all the properties then the properties of the re-dispatched event won't have the right values
when listeners handle the re-dispatched event. In our case data will be lost.
An example:
// Add two listeners:
stage.addEventListener(Cus
button.addEventListener(Cu
// Dispatch the CustomEvent on the first
stage.dispatchEvent(new CustomEvent(CustomEvent.NO
private function firstDispatchHandler(e:Cus
trace("First: "+e.data.name) // traces "John Doe"
// Re-dispatch event to the second listener
dispatchEvent(e)
}
private function secondDispatchHandler(e:Cu
trace("Second: "e.data.name)
// Without the clone override you'll get an error:
// TypeError: Error #1034: Type Coercion failed: cannot convert
// flash.events::Event@54122a
}
Event.toString() is not required but I find it useful when unsure about what properties is
passed thru the event.
If you don't override Event.toString() tracing your CustomEvent will show:
[Event type="notify" bubbles=false cancelable=true eventPhase=2]
When overriding you'll get this:
[CustomEvent type="notify" data=[object Object] bubbles=false cancelable=true eventPhase=2]
Now we know that the event is a CustomEvent with a data property (in this case an object).
Tracing events becomes even more useful when dealing with more "advanced" types - like the MouseEvent:
[MouseEvent type="mouseOver" bubbles=true cancelable=false eventPhase=2 localX=38 localY=41 stageX=265.95
stageY=123 relatedObject=null ctrlKey=false altKey=false shiftKey=false buttonDown=false delta=0]
Hope it makes sense :)
Best,
Jakob E
View More