How to Reference Objects Dynamically
Sometimes it’s useful to reference a movie clip (or any object) by combining individual pieces of its instance name dynamically. In coding up a version of Space Invaders, for example, you might employ a dozen instances of the same movie clip symbol to represent a dozen alien space ships. Each clip will have its own instance name, of course, which might be alien0, alien1, alien2, and so on. Rather than create an array to hold each instance name or reference, you might rather combine the string “alien” with the numbers 0, 1, 2, etc., to formulate your reference. So, you might try something like this …
var alienShip;
for (var n=0; n<12; n++) {
alienShip = "alien" + n;
alienShip.gotoAndPlay("attack mode");
}
… because this should allow the variable alienShip to increment through each instance name — when n is 0, its value will be “alien0”; when n is 1, “alien1”; and so on — but it doesn’t work. Why?
Well, this is where a good grasp on datatypes comes in handy and why I prefer the strongly typed syntax provided by ActionScript 2.0. In the above example, the variable alienShip isn’t a movie clip reference at all: it’s a string. As the value of n increments, n concatenates with “alien” to form the string “alien0,” the string “alien1,” and so on. Strings, of course, are not instances of the MovieClip class. Look up the String class entry in the ActionScript Language Reference … you won’t find a String.gotoAndPlay() method.
We need a way to resolve a string to an object reference, and ActionScript provides two solutions: the global function eval() and the array access operator.
eval() function
The eval() function accepts a string or series of strings and returns an actual object reference based on that expression.
If the actual instance name is alien0, then eval("alien0") will return the reference you need. Same goes for eval("alien" + 0), eval("ali" + "en0"), and any other variation on that string, including eval("alien" + n) …
var alienShip:MovieClip;
for (var n=0; n<12; n++) {
alienShip = eval("alien" + n);
alienShip.gotoAndPlay("attack mode");
}
Notice my strongly typed variable, established by the :MovieClip suffix. ActionScript 2.0 is required for this syntax and provides a handful of benefits, one of them being improved error messages at compile time. If, somewhere down the line, we attempt to set alienShip to something other than a MovieClip instance, the compiler will complain. If nothing else, it’s a reminder that alienShip must refer to an actual MovieClip instance (not a string!) in order for the line alienShip.gotoAndPlay() to succeed.
Note: From Flash 5 on, you cannot use eval() on the left side of an equation, such as …
eval("varString" + varNumber) = 55;
eval("varString") = "Tabasco® sauce";
If you find yourself in the above situation, you can either use the Flash 4-era set variable statement …
set("varString" + varNumber, 55);
… or the array access operator (see below). Remember, this only matters if you’re trying to resolve an object reference on the left side of an equation.
array access operator
The array access operator, [], is primarily used to set and retrieve elements in an array; however, it can also be used to resolve object references on either side of an equation. Rather than standard dot notation, where an object’s members are accessed via the dot operator …
myMovieClip._x
… the array access operator allows for the use of strings …
myMovieClip["_x"]
… just remove the dot and wrap the desired member in square brackets. Since a MovieClip instance is nothing more than a property of its parent, you can use the global this property to access the movie clip itself …
var alienShip;
for (var n=0; n<12; n++) {
alienShip = this["alien" + n];
alienShip.gotoAndPlay("attack mode");
}
July 18th, 2006 at 8:31 am
Dude, thank you so much, I was trying to get a mouseover hittest to work and it wasn’t doing it by assigning a string with the arguments, but using eval(); worked like a charm, I bookmarked your site for future reference! thanX again!
July 18th, 2006 at 11:05 am
KidNiki,
Hey, I’m always glad to hear that! My personal preference is the array access operator, but eval() works just as well in most situations. Enjoy!
July 24th, 2006 at 12:44 pm
Hi David,
Thank for a really useful tutorial. I apologize if this is a silly follow-up question: How would you use the array access operator to dynamically assign instance names to Objects? (for instance, [”person_”+i]) I am new to actionscripting and am finding it difficult to make the leap…
July 24th, 2006 at 3:14 pm
meerkat,
Not a silly question at all.
I’m betting you tried something like this:
The reason the above fails is because, coincidentally, the array access operator puts us in “object reference” mode. In other words, we’re looking at
obj0,obj1, andobj2in light of another object (happens to bethis), rather than looking at these objects on their own. Thevarstatement and post-colon suffixes are only possible when the object in question is not preceeded by another.The correct format for the above example is this:
… which simply means you cannot strongly type variables declared in this way. See Is Strong Typing Possible with the _global Object? for details.
July 25th, 2006 at 8:06 am
Hi David,
You guessed right about where I had gone wrong. Thank you so much for replying so quickly and for the very helpful explanations.
July 25th, 2006 at 10:10 am
Glad to help, meerkat.
July 29th, 2006 at 2:35 am
now i know the meaning of []
i’m not good in english but ur explaination clear and sound to me.
bless u, David. u are so good in explaining.
July 29th, 2006 at 7:29 am
z. mahrus,
Thanks! Just keep in mind,
[]is also used for setting and retrieving elements in an array — probably more often.Both are correct uses of the array access operator.
July 30th, 2006 at 1:39 pm
Thanks, this is just what I was looking for… clear and precise. I spent about 2 hours trying to refrence an attached object on the stage through a string. Although instead of :MovieClip I had to use :Object in order to reference my attached movieClip instance. You made my day and my deadline. Thanks again.
July 30th, 2006 at 2:40 pm
Jack,
Glad to hear it.
Can you add a bit more about your datatype issue? I’m not sure what you mean by having to use
:Objectinstead of:MovieClip.July 30th, 2006 at 9:43 pm
Hi David,
As it turns out, I must have had a typo. I went back into the code and replaced the datatype back to :MovieClip. It does work with the :MovieClip datatype as well as the :Object datatype. Sorry about my hasty comment. Thanks again.
Jack
October 5th, 2006 at 2:15 pm
Hey David,
eval()actually can be used on the left side of the equation as long as you don’t try to set its result. For example,eval("my_mc")._x = 5is perfectly valid.October 5th, 2006 at 3:20 pm
matthew,
Interesting. Thanks for pointing that out.
October 23rd, 2006 at 7:20 am
Heys, thanks for the help!!! Was fumbling with how to make AS understand that it is a variable name…THX!!! =D
October 23rd, 2006 at 11:34 am
Happy to help, Toiletfreak!
October 30th, 2006 at 3:47 pm
Hi Dave,
I came across this tutorial, and I think it may be just what I need. It’s very informative and has helped clear up a few confusing concepts for. However, I can’t get it to work with my current code. I’m trying to make a photo gallery that has thumbnails, prev/next buttons and also has the option of going through as a slideshow. I’ve got everything almost working.
The thumbnails that I’m using are gray, outline boxes that are actually movieclips labeled in sequential order and will highlight onRollover/onRollout, turn to a black outline onRelease, and return to gray outlines when another thumbnail is clicked . They work fine when individually clicked/rolled over. Now what I’m left with is that I want each thumbnail to highlight to a black outline (the onRelease state) when the corresponding picture is loaded during the slideshow or when pressing the prev/next buttons.
Any idea how I could acheive this? I tried all sorts of combinations using the concept in this tutorial without success. I can post my code or send you my .fla, if you’d like. Thanks in advance for any help you can give.
Jen
October 31st, 2006 at 8:37 am
Jen,
Depending on the complexity of your slideshow, you might benefit from using listeners to handle custom events. I could see, for example, having your prev/next buttons dispatch
onPrevandonNextevents, respectively. Your thumbnails could “listen” for these events and react accordingly. You might include in your dispatch the numbered index of the current thumbnail. See “How to Raise Custom Events (AsBroadster)” and “How to Raise Custom Events (EventDispatcher“) for some ideas to get started. Write back if you still have questions.November 2nd, 2006 at 3:49 pm
Thanks for the response, Dave. I think you may be right with your suggestion. I’m in the process now of reading through the articles you mentioned. If you don’t mind, I’ll definitely let you know when I need help.
Jen
November 5th, 2006 at 8:15 pm
Hi,
I took some time to read through your articles on custom events and also a few articles from the internet. The concept behind the custom events and using listeners seem like the way to go with my situation.
Would it be possible to have the thumbnails “listen” for a particular array element (from the XML doc) to be present on the stage using a listener/AsBroadcaster/EventDispatcher? However, I have no idea how to apply a listener to a movieclip and how to listen for an element from an array.
If you could help me out here, I would be so grateful.
November 6th, 2006 at 1:43 pm
Jen,
It may help you to think of the listener as its own entity. The listener is just a generic
Objectinstance that will tell other objects, such as your movie clips, what to do.Assuming your movie clips already have
onRollOverandonRollOutevent handlers — you said they currently behave as expected when individually rolled over and out — all you have to do is trigger those events “manually” from elsewhere. As a matter of fact, you may not even need a custom event.For example, if your thumbnails are named
thumb0,thumb1,thumb2, and so on, you could trigger the onRollOut event handler for thumb2 by using this:That would execute the function assigned to
tumb2originally. Thanks to the array access operator, you could use a string and a number, rather than thethumb2as such, to refer to this movie clip:That — no more, no less — is what this dynamic referencing is all about.
The array access operator lets you refer to an object with a string or concatenated string. So, in your case, you might have your “Next” button do two things instead of the one thing it’s currently doing. Currently, it’s choosing an element from your array of images and displaying that image. In addition, you could have it trigger the
onRollOverevent of the relevant thumb.So, what do I mean with this example? Presumably, you’re “keeping score” on what image is currently the chosen one. In my little snippet, the variable
xrepresents the number of the currently chosen image. I’m usingdisplay()as the name of an arbitrary custom function that displays the large version of this image. Each individual thumb could call this same functiononReleaseand refer to itself. Here, with the “Next” button, we’re calling that function and referring to an element in an array. Presumably, the array contains actual references to movie clips, so ifxis 2, we’re calling the third movie clip reference in the array —thumb2. If the “Next” button’s parent timeline is the same timeline that holds the thumbs, thenthis._parentmakes sense of a path, but that would be up to how you’ve arranged things.Does this make sense?
Understandably, it may not, because there are usually dozens of ways to accomplish any given goal in Flash.
An approach that uses a custom event might listen for the (for example)
onNextevent and use the same array access operator to tell a given thumb to perform the function assigned to its onRollOver event.At this point, your “Next” button would merely need to dispatch an
onNextevent and populate that event with, say, animageproperty and athumbproperty so that the listener could, in turn, invokedisplay()and the thumbnail’sonRollOverevent.The more I type, the more I begin to think this is a) either really helping, or b) really muddying the waters. I certainly don’t want to do the latter.
Look again carefully at the sample files in my event broadcasting articles. Notice that nothing is really “attached” anywhere. Any object (such as a button or movie clip) can invoke the
dispatchEvent()method of yourbroadcasterobject. It’s up to thelistenerobject to interpret and do something with the dispatched event.I’ll write a full article on this topic, Jen, because the question gets asked often enough. Keep your eyes peeled, and I hope I haven’t confused the matter any.
November 6th, 2006 at 10:43 pm
Whoa, that’s quite a response, and I get MOST of it. The first part about using the array access operator totally makes sense and seems to fit the situation. I have to admit that the concept of listeners has me completely lost. I read and read through articles/code, and I still can’t wrap my brain around it. So, I’m thinking I’d like to stick with your first scenario.
Now I’ve tried it using the example you gave, but it’s not working for me. Here’s the code for my previous/next buttons:
prevb.onRelease = function() {
cur–;
if (curpArray.length-1) {
containerMC.loadPic(0);
} else {
containerMC.loadPic(cur);
}
this._parent[”buttMC” + cur].onRelease();
};
/////////////////////////////////////////////////////////
Notice how I popped that last line in at end of the code outside of the if/else statement (maybe it’s not the place to go). The instance names of my thumbnail movieclips are buttMC0, buttMC1, etc. The original code was not written by me, so the use of “cur” is not my idea. I’m assuming that’s what I would use as the variable for the array access operator. I did, however, try “x” just to see what would happen. Nothing.
One quick question, can the terms onRelease and on(release) be used interchangably? I ask this because on(release) is what is used within each thumbnail movieclip, and then I’m using onRelease in the previous/next code.
Just to give a little background info, here’s the code within my thumbnail movieclips (this is buttMC0):
on (rollOver) {
gotoAndPlay(2);
overtxt.text = this._parent.tArray[0];
}
on (rollOut) {
gotoAndPlay(8);
overtxt.text = “”;
}
on (release) {
this._parent.containerMC.loadPic(0);
overtxt.text = this._parent.tArray[0];
gotoAndStop(16);
if (_root.buttMC1._currentFrame == “16″) {
_root.buttMC1.gotoAndPlay(8);
}
//the above if statement are given for every other thumbnail
//movieclip other than itself
Sorry if I’m bombarding you with too much info here. I’m so close to finishing this up, and it’s driving me mad. Thanks so much for walking me through this. I’ve searched hi and lo for weeks on this matter, and it wasn’t until I came across your above article that something clicked.
I hope you can give me a pinch more assistance to Git-R-Done! Ugh…sorry…couldn’t help myself.
November 6th, 2006 at 10:48 pm
Just in case you’re interested and to give you a better idea of what I’m trying to do, the link to my current test proofing gallery is here: http://www.snappychic.com/clients/smith/index2.htm
Sorry about the music, there is a pause button.;)
November 7th, 2006 at 10:20 am
Jen,
The above potentially makes sense. Assuming
curis a counter (a number), it looks like this code loads a numbered file via the customloadPic()method — which means it could also be used to trigger theonRelease()event (function) assigned to thebuttMC[number here]movie clip.Note: the path
this._parentonly makes sense in this context if the buttMC movie clips are located in the same parent timeline that houses thisprevbbutton. If those movie clips reside elsewhere, you’ll have to adjust the path appropriately. You’re essentially havingprevbsay, “Okay, from my point of view, I’m looking at my parent timeline. Do I see abuttMC0(orbuttMC1, etc.) from here?”A good tip you might try here is to
trace()out your various objects to see if you’re hitting anything.See my debugging article for details and additional approaches.
And that’s no surprise. In my earlier snippet,
xwas just a stand-in. The variable doesn’t mean anything unless it’s in use. In your code,curhas been declared somewhere and actually means something. Does that make sense? On its own,xdoesn’t have any inherent meaning in ActionScript.Heh, no worries.
I’m always happy to help when I have the time. Given my schedule this week, I really think the best I’ll be able to do is to write an article on a general approach that approximates what you’re dealing with.
Conceptually, they’re the same, but in practical terms, they’re very different. See my Museum Pieces entry.
March 8th, 2007 at 1:03 pm
in the last half an hour i’ve searched for answers to 2 very different actionscript questions and both times the most useful response was from your website. Amazing - thank you for taking the time to write all this.
One question - i’ve got both methods working, which is best. The examples i’m using are below:
March 8th, 2007 at 7:12 pm
ali,
I would personally use the first approach (the array access operator
[ ... ]) becauseeval()is said to carry something of a performance hit. It actually invokes a function, while the other approach does not. Mainly, though, the other approach requires less typing.April 24th, 2007 at 4:39 pm
Hi David,
This is EXACTLY what I was looking for!! Thanks so much for the tutorial it really really really helped me with my project.
=) Happy trails.
April 25th, 2007 at 11:51 pm
Aida,
Nice! Glad to help.
August 9th, 2007 at 7:10 pm
Hi David,
Great tutorials you have! I’ve been looking around for a way to dynamically reference functions but can’t quite get a handle on it. Is this possible using eval or should I venture down Events/Listeners? Or maybe you have a more elegant solution?
Right now I have a class with a lot of functions and I want to have one function (also in that class) that passes a function name as a string along with its arguments. Then I want to evaluate the function name and call it as a normal function:
function doCommand(commandName:String, arg1) {var cmd:String = commandName + "(" + arg1 + ");";
eval(cmd);
trace(cmd);
}
I have a function within the class called setText and it takes one Number argument. When I call
doCommand("setText", 4);it traces
setText(4);but the eval doesn’t do anything. I have tried sticking “this” in there but am not sure exactly what to do with it.[Also, I know that since my functions have a varying number of arguments, I’m going to have to use eval to get those straight, but I just want to get the one-argument case working first!]
Any help would be appreciated! Oh and FYI the reasoning behind all of this is I want just one externalCallback function between my HTML and Flash.
August 10th, 2007 at 9:41 am
annie,
Ultimately, functions are objects, too — instances of the
Functionclass) — so all you need to do, in theory, is use the array access operator as shown above and append the function call operator,()to the end of your expression.But in this case, you’re wanting to call this from inside another function, which means the
thisI just typed would be scoped to the other function, rather than the timeline/object that contains the function referenced by a string.So … the
Function.apply()method comes to the rescue. Check it out:For some reason, the extra little
argsvariable is needed in thedoCommand()function (I tried replacingargsin the next line with the expression it refers to, but no go). You certainly don’t need thetrace()call in the second line, but that quickly proves this approach works, both for a static method call, such asMath.max, and a simple named function, such as the customshowBigger.Note my use of
Array.splice(). That’s the way to get whatever number of arguments are passed in. TheFunction.argumentsproperty returns an array of the arguments, if any, passed to a function. In the above, even thoughdoCommand()’s signature only accounts for a single (String) argument, anything else passed is added toargumentsanyway. Sinceargumentsis anArrayinstance, we can invokesplice()to snip off the first argument (the string) and pass along the rest.August 10th, 2007 at 12:36 pm
Thanks so much for the response David! I actually found out about the function.apply in a thread last night and saw you contributing to it, haha.
I got it working for the static Math.max call but not for showBigger (which I added) or any other function I placed in the class…so I figure I have some sort of scoping issue. I’m calling doCommand within an initialize function and all of the functions I call are also within the class:
public function myClassConstructor() {initialize();
stop();
}
function initialize() {
doCommand("setPos", 0, 4);
doCommand("getPos");
doCommand("Math.max", 5, 10);
doCommand("showBigger", 5, 10);
}
public function doCommand(commandName:String):Void {
var args:Array = arguments.splice(1);
trace("args are: " + args);
trace(eval(commandName).apply(null, args));
}
I understand that the trace isn’t necessary but I just wanted to see what gets returned. The output I get indicates it’s receiving the arguments just fine but only calling the Math.max properly:
args are: 0,4undefined
args are:
undefined
args are: 5,10
10
args are: 5,10
undefined
The first one I expect to have an undefined output because it’s a void function, but the getPos and getBigger return a number so they should output the result. And every one of them should output whatever trace statements I have in the functions but they’re not - so it looks like they’re not being called at all. I tried making all the functions public but that’s not doing anything.
I also get the same problem when I call myClassInstantiation.doCommand [outside of the class].
Any idea what’s going on? Thanks again!!
August 14th, 2007 at 5:36 pm
Figured it out — in a class you should include “this”.
So this worked for me:
public function doCommand(commandName:String):Void {var args:Array = arguments.splice(1);
trace("args are: " + args);
trace(eval("this." + commandName).apply(null, args));
}
August 14th, 2007 at 6:27 pm
annie,
Ah, you beat me to it! Glad to hear you found a solution!
August 17th, 2007 at 3:23 pm
Okay - here’s a new one - how about trying to reference a class instance’s function? So instead of using “this.” in my doCommand that’s WITHIN a class, I’ve moved my doCommand OUTSIDE the class and want to apply a function that’s within the class:
trace(eval(”classInstance.” + commandName).apply(null, args));
^ doesn’t seem to work for me! Any ideas? Thanks
August 22nd, 2007 at 12:01 pm
annie,
Because
doCommand()is a public function, you should be able to invoke it like any method; for example:Or maybe I’ve misunderstood what you’re after? If
doCommand()is no longer in the class, then you should be able to do this:… assuming the
myClassConstructorclass has ashowBigger()method.September 25th, 2007 at 5:47 pm
David,
Thanks for that follow-up a little while ago. I got your AS3 book and can’t wait to dive into it — once I have time to get away from my AS2 responsibilities!
I have a question mildly related to the problem I was trying to solve before - external callbacks. I have a class of all my handlers for external callback functions. I’m extending that class to create the object that takes in those callbacks and defines the Flash-side functions. Because it’s a class it’s not on the top-level of the .fla, so when I try to call a Flash function from my html, it’s not finding it. How can I link the two?
I’m importing that class down the line (.fla -> .as -> instance of the external callback extension class). I have it set up this way because I’m essentially making templates that are utilizing calls in different ways, so for example the “showBigger” function passed from the HTML does x in one template and y in another. So I want the HTML to pass “showBigger()” into the swf and have my external callback class read it then pass it on to the template.
I had this working before when I was just including the external callback class from the .fla and had the Flash-side function definitions in the main .fla (but that was for a single template and of course I’m trying to do things the right way, more modular, etc now!)…is function.apply() in my future again? Any insight would be great.
September 25th, 2007 at 7:45 pm
annie,
I’m not sure I see 100% what you’re aiming for, but I’ll do my best to help.
The scope of the classes you instantiate in Flash are dependent on where you instantiate them. Of course, you can purposefully write a class to act differently, but generally speaking, if you create a class instance in the main timeline, it will be accessible as an object of the main timeline. Since you mention HTML, it sounds like you’re communicating beyond the bounds of the SWF itself. (Are you using the
ExternalInterfaceclass, I wonder? That would be a good choice, because it makes the easiest bridge I can think of between ActionScript and, say, JavaScript.)In ActionScript 2.0 — this is a kind of behind-the-scenes tip, by the way — custom classes end up being referenceable as properties of the
_globalobject. In an ideal, best-practices frame of mind, the developer should probably ignore this little factoid: it’s practically a hack in the implementation of classes in AS2, but there it is. Instantiate a custom class in any timeline you want, then use the Debugger panel to check the_globalobject; you’ll see your class.That shouldn’t make any difference, because ultimately your ActionScript 2.0 — all of it — gets “baked” into the SWF at compile time. My hunch is that your callbacks aren’t getting scoped properly, which sounds like the same hunch as yours …
… so something in this new step is throwing you off, but it’s not (or shouldn’t be) the fact that this code is now stored in an external file. Again, by the time it’s instantiated, it belongs to the timeline in which it appears.
Your best bet may be to sprinkle around a number of
trace()statements withthisas the parameter. The globalthisproperty will tell you the object or timeline you’re in, and that may bring to light the cause for some of your scoping issues.Are you comfortable with the Debugger panel? You may want to check out my “Debugging ActionScript 2.0 Code” article on the Adobe Dev Center to see if that helps you see under the hood a bit more clearly.
I’m enjoying our conversation across these blog comments, but because of the length of time between each turn (which means I’m likely forgetting details from talk to talk), I’m a bit worried I may be steering you down a more complicated path than your endeavor merits. I sure hope not! The fact that you had it working before is actually a comfort, in that regard, so I think all you have to do is solve this one issue ( … the issue of how the scope is changing when your code is in the external ActionScript).
September 25th, 2007 at 8:06 pm
Thanks for the quick response!
I am indeed using the External Interface class.
I guess what my question boils down to is this -
When my HTML calls a function in the Flash, does my ExternalInterface.addCallback(theFunctionName) only look at the main level for theFunctionName? Because my theFunctionName is within a class now, no longer right in the .fla.
I have used the debugger before and tonight I’ll trace through things as you suggested
September 25th, 2007 at 8:14 pm
annie,
Ah, now we’re getting somewhere!
ExternalInterface, as you’re already aware, allows JavaScript to call ActionScript functions or methods (and vice versa). The way it does this is to give each of your ActionScript functions or methods a kind of nick name. JavaScript calls those nick names, and the nick names call their associated ActionScript functions/methods. Those functions and methods can exist in whatever scope you like, because you can route to them as needed inside the nick name handler. So they don’t have to be in the main timeline, but they do have to be instantiated somewhere if they’re custom class methods.ActionScript written into class files doesn’t really “come to life” (read, isn’t accessible) until the relevant class is instantiated. Classes are effectively data types, so for example … imagine trying to access the
Date.getMinutes()method if you hadn’t yet instantiated aDateobject. Wouldn’t work. Does that make sense?There is an exception, actually, and that’s static methods. The
Mathclass doesn’t get instantiated, of course, but in that case you have to at least invoke the name of the class to get to the method. You’d still be okay if your methods were static, but your nick name handlers would have to invoke the class name. My guess, however, is that your methods are not static, but you haven’t instantiated your class anywhere. Until instantiation occurs (unless we’re talking static), the code doesn’t really exist in the SWF.September 25th, 2007 at 8:54 pm
Yes - I am instantiating the class…otherwise nothing in my Flash would show up
When I make the call from HTML, my Firebug is saying the function does not exist (”theFunctionName is not a function”). Previously the function definition for a template was on the top level, so I suppose my handler that pointed to the Flash function definition was pointing to the top level/_level0/_global/the .fla file’s ActionScript. Now, that top-level function is buried within my template class, so I need the callback to point to the function within the class. BUT the template class is an extension of the class of external interface handlers so I assumed it would look around its scope first.
Does this mean from my HTML I have to specifically call “instanceName.theFunctionName()”? Do I specify it within the external interface class?
It just doesn’t seem right that I would have to use the instance name.
Haven’t gotten to testing it out yet. Maybe a Flash Firebug debugger would help me (http://foobr.co.uk/2007/02/debug_flash_with_firebug/)
September 27th, 2007 at 3:59 pm
annie,
If your function,
theFunctionNameis a method of some class, then you betcha, you will indeed have to use that class’s instance name — that is, the variable name that stores a reference to the instance of the class that defines that method.In the static
addCallback()method of theExternalInterfaceclass, you would reference your function something like this:October 2nd, 2007 at 5:08 pm
Hi David!
I finally got things working. I figured my problem was with the ExternalInterface in my superclass calling the function in its subclass, but it turns out that works fine if you just call the function name without an instance name (even if the superclass has that same function definition, the subclass definition will override it).
My problem had to do with figuring out eval and apply function…just like the original problem that brought me to your page
Plenty of my movie’s attributes need to be set if they get sent when the swf is created, so after I set up my callbacks, I look to see if my _level0 vars that came in with flashVars have been created, and if they did, I call the functions that use them (e.g. if myColor has been sent through flashVars when the movie was created, I want to call setMyColor(_level0.myColor). Kind of mimicking the JS command to do some initialization.
So here is my super dynamic way of creating multiple callbacks for Javascript that have varying numbers of arguments. Hope I format this right..
//function definitions [mine are named the same for JS and Flash calls]
var defs:Array = [["doThis","arg1"],
["doThat","myArg1"],
["doSomethingElse","argument1", "argument2"]];
for (var i=0; i
I know I could probably get away with saving the defs[i][0] as a function name and splicing it off to just send the rest of the array in the apply function, but I didn't feel like wrapping the _level0[] around the argument names in my defs Array (it looks simpler with just the argument names I think). Plus none of my functions have more than two arguments so it's not too tough to just create a new array.
So anyways, thanks for your patience with me!
October 2nd, 2007 at 5:12 pm
Eek, eaten by wordpress!
January 4th, 2008 at 12:46 pm
Hi Dave!
Thanks so much for the explanations and tutorials, it has been essential in helping me better understand actionscript. However, I am trying to get a better understanding on the use of Arrays, and I was wondering how would you code a series(++) of buttons that are dynamically loaded images into an attached MC, where each button(MC) has a unique action or event?
I found a good example with the info I am looking for here:
http://flash-creations.com/notes/dynamic_slidingviewer.php
Unfortunately, I am having trouble grasping it… Perhaps you can simplify?
Here is what I have so far:
January 9th, 2008 at 10:56 am
Jack,
Actually, what you’ve got so far looks fine. I tested it on a new AS2 FLA on this end and changed the
trace()statements from “frame 2″ and “frame One” to simplythis, so that each button would mention its instance name when interacting with the mouse. Everything traced as expected.I noticed in the flash-creations tutorial, the
openPic()function uses the instance name in the same way:Of course, that means your JPGs (in this case) need to follow a strict naming format, which may or may not suit your taste. To answer your specific question, you could indeed use an array to attach images — or, in the least, lend a bit more flexibility to how your images are named.
In the code you posted, while it doesn’t hurt to have the
myThumbs_arrayarray, you’re not actually using it for anything (not yet, anyway). You can (re)use thatimgThumbvariable as often as you like and omit the array:And then, if you want to load specific images, or attach specifically named (that is, non-sequentially named) assets from the Library, you might do something like this:
… in which the thumbHolder linkage name is replaced by a name from the new
clipsarray (note that thecountImagesvariable now takes its value from the length of the array). Does that help?January 12th, 2008 at 3:38 am
Thanks, I was trying to group dynamically created movie clips from an XML file so that I could manipulate them as a group without just attaching them into some other movie clip.
So I went along the lines of using an array and pushing the names into the array but couldn’t figure out how to get the names in the array to affect the actual movie clips until I find this post, again thanks for the write up.
January 14th, 2008 at 9:15 pm
Billy,
Glad to help!
March 23rd, 2008 at 5:50 am
I don’t seem to have any luck getting variables to work. I have six identical movieclips on the stage and I would like to include them all in certain functions/statements. Right now, I had to settle for writing out an identical statement for each instance and that works fine. But it’s very time consuming, especially for more complex if/else statements, and the resulting code is very unwieldy to say the least.
So if the movieclips are named tkn1 through tkn6 and I want to execute a certain code whenever any of these clips are intersecting with a movieclip named jv_mc, I tried the following and it did nothing.
April 7th, 2008 at 7:46 pm
P.J.,
This is an issue of scope. You’re declaring a variable named
tokeninside the scope of this function,notify(), yet in the condition of yourifstatement, you’re referencing_root.tokenwhich, contrary to your expectations, is trying to reference a completely differenttokenvariable; namely, the non-existent one scoped to the main timeline (_root). Does that make sense? You’ve got twotokenreferences going, one of which doesn’t exist. The one you’re referencing in the condition doesn’t exist.If you want to reference
_rootas your container object, I recommend you go with the array access operator instead:April 9th, 2008 at 8:37 pm
Incredible… I’ve been stuck for over two hours now on the dynamic creation of movieclips. For some reason
for (var i:Number = 0; i[code snipped by WordPress]inside a onKeyUp event really doesn’t want to work. Outside the onKeyUp, it does.
It’s driving me crazy…
April 10th, 2008 at 5:31 am
Next day I had this solved. I still don’t understand how this works exactly, as there seem many roads that lead to Rome. The one I used in this case with the createEmptyMovieClip was:
reference = this.createEmptyMovieClip(i +"_mc", this.getNextHighestDepth());reference._x = something_crazy;But this one has no (obvious) affiliation with any of the methods you mentioned! I couldn’t get a
this[]oreval()notation to work within a Key. event anyway…?!April 29th, 2008 at 6:31 pm
Hmm here’s me again with a small silly question.
Why won’t this lazy code work?
Clicking on any of the 8 buttons traces “9″, which pretty much baffles me.
April 29th, 2008 at 6:33 pm
well, trust me that the for loop is correct, for i iterates over 8.
May 7th, 2008 at 11:11 pm
Tiemen,
I’m going through my notes, man, and I honestly can’t find (i.e., can’t remember) if I replied to you about the
Keyevent listener. I hope I did! I’ve been going insane lately with ridiculous schedule conflicts.As for the “lazy code” question, I think it’s an issue of scope. Check out this revision:
May 8th, 2008 at 10:04 am
Thanks for the reply. I have been doing a LOT of flash lately, making comforting jumps in level, but though I understand what you’re doing, it does not actually make sense. For this example, the variable I want to set is a semi-global one, defined in the main timeline. Flash doesn’t convert the i in the onRelease handler to a static number, which I thought it should when it’s used inside a for loop.
So it writes a handler function like this, which finds when invoked, the out-serviced i variable lying around at 9
d3_mc.onRelease = function() {
var_num = i;
trace(i); // traces 9, which makes sense
}
It should’v been this though:
d3_mc.onRelease = function() {
var_num = 3;
trace(3);
}
So what you mean by scope, is that “i” cannot be used on the right side of the equation inside a function declaration?