Flash > Listeners and AsBroadcaster

Introduction

In this section, briefly explain what the tutorial will explain/accomplish. If you want, you can include something “dramatic” that gets readers interested in your topic. Try to enjoy writing tutorials and follow the basic guidelines found below. Before I forget, feel free to modify this document as much as needed.

from http://www.senocular.com/flash/tutorials/listenersasbroadcaster/

Download files

Extending What Was

Buttons are a good example to start with. The entire concept of a button revolves around user interaction, typically that of pressing. When you press a button, you expect certain results to follow, and when properly coded, they do. What determines when these events occur is the button’s ability to detect or listen for the user interaction. When the pressing of the button is detected or broadcasted by the flash player, the on(press) event in that button is handled and the containing code executed. Other events buttons listen for are release, rollOver, etc., while Flash movieclips similarly listener for events such as enterFrame, mouseMove, keyDown, etc.

Prior to Flash MX, these listener objects (buttons and movieclips) were pre-defined by Flash and could not be altered, nor new ones created, by the author of the movie. MX has changed all that with the new object model. Buttons and movieclips are still pre-defined, but now you can have your very own custom objects listen for certain events like those recognized by buttons and movieclips as they occur in Flash. Of course these custom objects are not restricted to the predefined events such as keyDown or mouseMove. You have the option of making your own events with the use of AsBroadcaster (ActionScript Broadcaster).

So what kinds of events, or broadcasters, are built into Flash? Well, these are:

Event Broadcaster Handled by (Listeners)
 onDragOut  –  Button, MovieClip
 onDragOver  –  Button, MovieClip
 onKeyDown  Key  Button, MovieClip
 onKeyUp  Key  Button, MovieClip
 onKillFocus  –  Button, MovieClip, TextField
 onPress  –  Button, MovieClip
 onRelease  –  Button, MovieClip
 onReleaseOutside  –  Button, MovieClip
 onRollOut  –  Button, MovieClip
 onRollOver  –  Button, MovieClip
 onSetFocus  Selection  Button, MovieClip, Selection, TextField
 onData  –  MovieClip, LoadVars, XML
 onEnterFrame  –  MovieClip
 onLoad  –  MovieClip, LoadVars, Sound, XML
 onMouseDown  Mouse  MovieClip
 onMouseMove  Mouse  MovieClip
 onMouseUp  Mouse  MovieClip
 onUnload  –  MovieClip
 onResize  Stage  Stage
 onChanged  TextField  TextField
 onScroller  TextField  TextField

You’ll notice that not all of the events, like onDragOut, are associated with a broadcaster object. You can consider these to be broadcasted by the Flash player itself rather than through an actionscript object within Flash. These events are restricted to being used only by whatever objects can handle them, as listed. onDragOut, for example, being only available for use with a Button or MovieClip object. The ones with broadcasters allow you to add your own listeners to these objects allowing those listeners to recognize when an event is initiated. For example, you could make a generic object in actionscipt and have it listen to the Mouse object (a broadcaster) which will then allow that object to run onMouseDown, onMouseMove, and onMouseUp code whenever the mouse is pressed, moves or is released.

There are two different ways to look at listeners and broadcasters.to really understand how they work. The more literal sense revolves around focusing on the individual listeners themselves and how they can become “aware” and listen for events occuring in Flash. The other is based more on how listeners and AsBroadcaster works internally in Flash.

Listeners Listen

One of my first usages of listeners was getting a movieclip in MX to recognize an onKeyUp event. If an onClipEvent(keyUp) is placed on the movieclip itself, the keyUp event is recognised and my inserted code would run appropriately. Trying to define the event through instance_mc.onKeyUp = function(){…} yielded no result. It wasn’t until later I realized that I had to make my movieclip a listener of the Key object so it would know when the key was pressed and would recognise to run the onKeyUp event when a key on the keyboard was released. To do that:

 

Key.addListener(instance_mc);
instance_mc.onKeyUp= function(){
	// key up code
}

Why is a movieclip not automatically a listener of the Key object as it is as an onClipEvent? To be honest, I’m not sure and am too lazy to look it up for the purposes of this article. Its registered as a listener of the Mouse object by default (though thats not entirely true since its not really being handled by the Mouse broadcaster but the Flash player itself, but…) for example instance_mc.onMouseUp = function(){...} works, but not Key.

Nonetheless, once any object, such as my movieclip object, becomes a listener of a broadcasting object, it can then recognize events sent out by that broadcasting object and perform the appropriate actions. From the list we see Flash’s broadcasting objects are

  • Key
  • Selection
  • Mouse
  • Stage
  • TextField

Each one of these can have listeners added to them using the addListener() method, making the passed object aware of its events. The Selection object, for example, has one event, onSetFocus which is run whenever the focus in Flash changes. When an object is added to the Selection object as a listener (and this can be any object, a generic object, a movieclip, or even a button) it then becomes aware of whenever the Selection object broadcasts that event and runs whatever onSetFocus function assigned to that object.

Example 1

So lets make an object and have it be a listener to the Mouse object. This train of thought is the first I mentioned, the “literal” way of thinking meaning we’ll follow the metaphors set aside by Macromedia in understanding how listeners work. That metaphor being that of a listener. A listener is an object that listens for an event to occur and then executes a given script based on what event it was.

// make a new generic object
aBigEar = new Object();

// define a function to perform a task
Flicked = function(){
	trace("Ouch, you just flicked me!");
}

// make aBigEar a listener for events from the Mouse object
Mouse.addListener(aBigEar);

// assign an onMouseDown event to aBigEar
// since aBigEar is a listener of the Mouse object, it will
// recognise mouse events just as a movieclip would
aBigEar.onMouseDown = Flicked;

You can throw this code right into a new movie and test it out. When you click the mouse, the output window will display “Ouch, you just flicked me!” aBigEar, once made a listener of the Mouse object, runs whatever is assigned to its onMouseDown whenever the mouse is pressed. In this case, the function Flicked is run and the contained trace message is displayed.

onMouseDown itself, to the aBigEar object, is nothing more than just an ordinary function. There’s really nothing special about it despite the pretty color-coding given to it by Flash. You could call this function just as easily by sayingaBigEar.onMouseDown(). The Mouse object though, has the event onMouseDown associated with it. Because of this, when the aBigEar object is set to listen to the Mouse object, it will hear when that onMouseDown event is triggered and run its own onMouseDown function. AsBroadcaster lets you define your own events, letting you call whatever function you want in your listener object(s).

 

AsBroadcaster

We’ll get into more usage with Listeners, but not before dipping a little into the AsBroadcaster object and seeing what it really accomplishes. This object is closely tied to listeners, more than you may think. Each one of those event broadcasting objects listed before (Key, Mouse, Selection, Stage, TextField) was initialized behind the scenes by Flash using AsBroadcaster. This is what enabled them to broadcast that event for listeners to handle.

The AsBroadcaster object itself, despite its presumed intimidation, is simply a generic object with one method, initialize. This is used on other objects to transform those objects into broadcasting capable objects. In doing so, it adds three new methods and a new property to the transformed object. These methods are addListener, removeListener, broadcastMessage and the property, _listeners. addListener lets you add a listener to your new broadcasting object. removeListener lets you remove one. broadcastMessage is the command that the initialized object runs to generate an event to be sent out to the listeners (like onMouseDown) while _listeners is a list of all the listeners associated with the broadcast object. So, for the usage of AsBroadcaster, we get:

AsBroadcaster.initialize(objToBroadcast);
objToBroadcast.addListener(listenObj);
objToBroadcast.removeListener(listenObj);
objToBroadcast.broadcastMessage("event");
objToBroadcast._listeners;

Note that you do not create instances of the AsBroadcaster object as you would with other objects using the new keyword. It is simply a container object for the initialize function, which could just have easily been a stand alone function.. The only time AsBroadcaster is actually written in code is when an object is initialized to become an object capable of generating an event.

The Mouse object, for example, is automatically initialized with the AsBroadcaster object in Flash. It adds the addListener and removeListener methods to the Mouse object allowing you to add your own listeners and also runs broadcastMessage whenever you press, move, and/or release your mouse button. So if you click your mouse, Flash runs an internal

Mouse.broadcastMessage("onMouseDown");

and any listeners of the mouse object, like any movieclip for example (which is automatically made a listener of the Mouse object), will recognize the onMouseDown event and run any code they have associated with it.

Example 2

Now that we have a basic understanding of what AsBroadcaster does, ew can now use it to generate custom events from custom broadcaster objects for custom listeners to respond to. This example will still use the literal way of thinking as in Example 1, that being thinking of your listener objects as objects which are aware and listen for events to occur.

For this example I’m going to have to ask you step back in time a couple thousand years to the time of old where kings ruled and court jesters fooled. What we’ll do here is make some new objects; a king and a royal subject, and use AsBroadcaster to control how they interact. The king, being a king, is going to give orders and our royal subject will listen for these orders and carry out a certain action when received. So in this example we have to first create our objects and assign them their traits/abilities. The king, for example, when we define him in actionscript as an object, will just be like every other object so we’ll have to also make him a leader (using ASBroadcast.initialize) while our subject will have to be hired (using addListener) as a servant of the king and be given a job to do based on the commands given. Here’s the code:

// a King is born!
King = {};
// our King is declared a leader
AsBroadcaster.initialize(King);

// a royal subject is born!
subject = {};
// our subject is now hired to listen to the king
King.addListener(subject);

// now we tell our subject his job
subject.onKingScream = function(){
	trace("brings grapes");
}

// here we just make the King scream twice
// just for the heck of it ;)
King.broadcastMessage("onKingScream");
King.broadcastMessage("onKingScream");

When the King broadcasts his screams, the royal subject, as a listener, hears the screams and runs the onKingScream function its been assigned. This is the same thing which happens if you defined an onMouseDown event for a movieclip. When the mouse broadcasts the onMouseDown event, the movieclip runs its onMouseDown function. Here we are just using our King to broadcast the event and the subject object to listen and respond to that event. Any object you make can be used as a broadcaster broadcasting any event you want it to. You can even make predefined objects broadcast new custom methods as well, which brings us to Example 3.

Example 3

This quick example adds broadcaster functionality to a predefined actionscript object. This uses the Math object and a movieclip called ball_mc. Lets take a look:

// initialize Math object to be a broadcaster
AsBroadcaster.initialize(Math); 

// create a new function for the Math object which
// returns the sum of two numbers. Included is the
// broadcasted onSum event
Math.sum = function(a,b){ this.broadcastMessage("onSum");
	return a + b;
} 

// make the ball_mc movieclip a listener of the Math object
Math.addListener(ball_mc);
// sets the ball_mc to to goto and play frame 2 whenever
// the onSum event occurs (called when ever Math.sum is run)
ball_mc.onSum = function(){
	this.gotoAndPlay(2);
}

Now, whenever Math.sum is used on anything, anywhere in Flash, the ball_mc goes to and plays its frame 2.

How AsBroadcaster Really Works

How exactly does this generic object AsBroadcaster add this wonderful functionality to another object anyway? Its no secret. Its not even that hard to understand or even do without the AsBroadcaster object itself. All AsBroadcaster.intialize does to an object is add to it an array called _listeners and gives it some new methods to control the objects placed in this array. addListener adds an object in the array, removeListener removes one, and broadcastMessage runs, for each object in the _listeners array, a function with the same name as the passed string. In fact, though AsBroadcaster is a Flash MX object, its functionality can be implemented in Flash 5 all the same. The following code can be added to a Flash 5 movie to add custom AsBroadcaster functionality:

AsBroadcaster = new Object();
AsBroadcaster.addListener = function(listener){
	this.removeListener(listener);
	this._listeners.push(listener);
	return true;
}
AsBroadcaster.removeListener = function(listener){
	var i = this._listeners.length;
	while(--i >= 0){
		if(this._listeners[i] == listener){
			this._listeners.splice(i,1);
			return true;
		}
	}
	return false;
}
AsBroadcaster.broadcastMessage = function(theEvent){
	var i = this._listeners.length;
	while(--i >= 0){
		this._listeners[i][theEvent]();
	}
}
AsBroadcaster.initialize = function(obj){
	obj.addListener = this.addListener;
	obj.removeListener = this.removeListener;
	obj.broadcastMessage = this.broadcastMessage;
	obj._listeners = [];
}

This creates the AsBroadcaster object and gives it the addListener, removeListener and broadcastMessage functions, which when initialize is called, gets passed down and copied to the initialized object. The object passed also gets the _listeners array which is used to hold all the listeners. The internal code use in Flash MX to define the AsBroadcaster object is very similar.

I said it adds “custom” AsBroadcaster functionality because using this in Flash 5 doesnt give you the full functionality of Flash MX. Yes you can create your own broadcaster objects and your own broadcast events, but it does not mean that your Mouse object will automatically start broadcasting the onMouseDown event when the mouse is pressed because, as it exists in Flash 5, the Mouse object doesnt know when that happens. Because of this, our Example 1 will not work in Flash 5, though Example 2 and 3 will.

Another difference with this example is that, here, for this Flash 5 version, you can’t pass arguments into broadcastMessage to be received by your listeners. In MX you are able to pass any number of arguments after the event parameter in a broadcastMessage call to have those arguments passed to the listeners’ call of that event. An example of this is in the Appendix below. Flash 5 just doesn’t have the capability to make this possible because it cant parse the arguments followed by the event passed into the broadcastMessage call. In MX this would be achieved with the Function.apply method.

Broadcaster as List Holder

With this new attained knowledge of how AsBroadcaster really works, you can see that listener objects are, themselves, not altered in any way when they become a listener. This kind of contradicts the whole perception of these objects having gained this new ability of listening. In fact, all that happens is the broadcaster object is given a reference to that listener object and then is able to run any method of that listener it desires whenever it wants to (assuming the method exists). Alone, the listener object has no way of losing its listening ability unless the broadcaster itself is told to delete the listener out of the _listeners array using removeListener.

With that in mind, try instead not to think of listeners as listeners but just plain ordinary objects out off in the world somewhere. They mind their own business and you dont have to worry about them, what they can do or what they know, just that they exist. Now consider the broadcast object. This guy really is the head object in charge. He controls the commands and holds the list that says which one of those ordinary objects out there he can give these commands to. Any object on that list he can give commands to, an those objects, as long as they can recognize the command given, will have to do whatever the broadcaster object says; just because that’s just the way it is. And that is how it is in Flash.

Example 4

This example I think embodies that train of thinking with the broadcaster being in charge. Here, the broadcaster will be the all mighty Santa Clause, because, after all, he has the power to control the happiness of all the children (and even many of the adults) of this world. Santa, as we all know, has his naughty and nice lists and depending on who is naughty and who is nice, Santa shall decide the fate of their happiness. What we’ll do here is add people to the nice list and give anyone on it a present!

The example itself is structured much like Example 2, though there are some added elements and the AsBroadcaster object is renamed to cohere more to the Santa Clause metaphor. Here it is (note: some OOP used but the code sample is more to get an idea of how AsBroadcaster operates and a totally complete understanding isn’t necessary)

// metaphor definitions - just to make things sound right
// person class to make Person objects
Person = function(name){
	this.name = name;
}

// important person class to make ImportantPerson objects
ImportantPerson = function(name){
	super(name);
}
// important person is a subclass of person
ImportantPerson.prototype = new Person();
// rename addListener
ImportantPerson.prototype.addToNiceList = function(n){
	this.addListener(n);
}
// rename broadcastMessage
ImportantPerson.prototype.ForAllOnList = function(n){
	this.broadcastMessage(n);

}
// traces the _listeners array
ImportantPerson.prototype.ReadNiceList = function(){
	for(all in this._listeners){
		trace(this._listeners[all].name);
	}
}

// rename AsBroadcaster object
NiceList = AsBroadcaster;
// rename initialize object
AsBroadcaster.giveTo = AsBroadcaster.initialize;
// end definitions

// make Santa do his thing
SantaClause = new ImportantPerson("Santa Clause");
NiceList.giveTo(SantaClause);

Tommy = new Person("Tommy");
Tommy.givePresent = function(){
	trace(this.name + " jumps for joy!");
};
Sarah = new Person("Sarah");
Sarah.givePresent = function(){
	trace(this.name + " says, 'Thanky Santy!'");
};
Trevor = new Person("Trevor");
Trevor.givePresent = function(){
	trace(this.name + " thinks, 'But Ive been naughty!?!'");
};

SantaClause.addToNiceList(Tommy);
SantaClause.addToNiceList(Sarah);

trace("Who's on the Nice List?\n-------------------");
SantaClause.ReadNiceList();

trace("\nGive Nice People Presents!\n-------------------");
SantaClause.ForAllOnList("givePresent");

When run, this code traces both Tommy’s and Sarah’s givePresent functions, but poor little Trevor, because he was naughty and not added to the nice list, recieved no present.

Advantages

It’s important to note why you would want to use AsBroadcaster. At first it may seem overly complicated, but it does add an ‘easier’ method of interfacing with multiple class instances. More importantly, however, is that, despite the fact that AsBroadcaster really isn’t anything completely new (as you saw a Flash 5 implementation was created and as I have mentioned, you have probably done something similar in the past), broadcastMessage is a great deal faster in looping through listeners than a normal actionscripted loop is. In fact, using AsBroadcaster can cut loop time by about half! This is because broadcastMessage uses an internal loop mechanism, ASnative(101, 12), to loop through the listeners array which is much faster than the loops produced by Actionscript.

Conclusion

As you can see, the AsBroadcaster object and the use of listeners adds a whole new perspective in how you can program your Flash applications. Though maybe not a new function of Flash it may change the way you’ll want to handle and recognize events as they occur within Actionscript. Now you can have multiple objects in a scene all react to a broadcasted “onEarthquake” event with little effort and much speed.

Leave a comment