How to Retrieve FlashVars Data in ActionScript 3.0
Last year around this time, I described how to pass variables into a SWF by way of something called FlashVars. This was discussed in “How to Tell a SWF What File(s) to Load — From the Outside” which works for pretty much any sort of simple data you may want to pass in, as long as you’re talking about relatively small groups of name/value pairs. Complex data is more likely to be suited to XML. In that earlier blog entry, the purpose was to re-use a single SWF numerous times to load a variety of MP3 files, by specifying which audio in the HTML. Pretty flexible solution! You could use the same technique for loading JPGs or FLVs, to populate dynamic text fields, or whatever you like. The article has been fairly popular and continues to be useful — as long as your SWF is published for ActionScript 2.0 (or even 1.0 if you drop the post colon suffixes — :String, :Number, and the like). In ActionScript 3.0, things are different.
The updated code
There are two halves to getting this sort variable into Flash: the HTML side and the ActionScript side. Fortunately, the HTML side hasn’t changed at all. Even with an ActionScript 3.0 SWF, you can read the existing “From the Outside” article and continue to follow the instructions as stated, even for the SWFObject (JavaScript embedded SWF) section at the end. The difference comes within the first few paragraphs on ActionScript 2.0. And even so, the code as shown in that article …
But clearly, this approach is hard coded. In order to open up the possibilities, replace the path reference with a variable — let’s just call it
audio.var s:Sound = new Sound(); iconButton.onRelease = function():Void { s.loadAudio(audio, true); }
… comes fairly close to the updated syntax.
In ActionScript 3.0, incoming FlashVars variables are no longer available as a loose collection in the main timeline. In the above AS2 code, the audio variable is passed in to the SWF from the HTML document and is therefore not declared in the movie. In AS3, such variables have been moved to the parameters property of a LoaderInfo instance associated with the main timeline. The LoaderInfo class “provides information about a loaded SWF file or a loaded image file (JPEG, GIF, or PNG). LoaderInfo objects are available for any display object [this means instances of the DisplayObject class, which includes movie clips]. The information provided includes load progress, the URLs of the loader and loaded content, the number of bytes total for the media, and the nominal height and width of the media.” source
To get to the LoaderInfo instance associated with the main timeline, you may refer to the DisplayObject.loaderInfo property of the main timeline. Remember, the main timeline is a descendent of the DisplayObject class; it can be treated as a movie clip (an instance of the MovieClip class) or a sprite (an instance of the new Sprite class) — but we don’t need to worry about that here. The punch line is simply that instances of DisplayObject have a loaderInfo property that points to their own private instance of LoaderInfo, and LoaderInfo instances have a parameters property. To update the above AS2 code, then, swap out the solitary audio variable with the expression root.loaderInfo.parameters.audio. The name of the variable is the same, assuming FlashVars specifies it as “audio.” Here it is in context:
var s:Sound = new Sound();
iconButton.onRelease = function():Void {
s.loadAudio(root.loaderInfo.parameters.audio, true);
}
Now, even with that change, the above code would fail in ActionScript 3.0. Why? Because AS3’s event handler model is completely overhauled. Button instances, like the above iconButton, no longer use onRelease as shown, plus the Sound class behaves differently. Here’s the same brief code in AS3:
var s:Sound = new Sound();
iconButton.addEventListener(
MouseEvent.MOUSE_UP,
function(evt:MouseEvent):void {
s.load(new URLRequest(root.loaderInfo.parameters.audio));
s.play();
}
);
But that isn’t the important part, because ultimately, what you do with passed-in variables is up to you. The key is how to access them, and the solution is root.loaderInfo.parameters, followed by a dot and the name of whatever variable you’re after. This variable will have been passed into Flash by way of the FlashVars attribute of your HTML’s <object> and/or <embed> tag(s).
September 27th, 2007 at 10:27 am
Nice article - I’m jumping into Flash starting at v.9, so the ActionScript 3.0 updates are appreciated.
I looked at the earlier article as well, and I’m wondering if it’s possible to get the “value”(s) of the standard “param” tags passed in the HTML object/embed tag (or a Javascript call like AC_FL_RunContent/SWFObject), i.e. for
<object [attributes] >
<param name=”movie” value=”movie.swf” />
<param name=”loop” value=”true” />
…
in my .swf I’d see “movie” and its value “movie.swf”, “loop”/”true”, etc.
I’ve run the following code:
for ( var theName:String in root.loaderInfo.parameters ) {
var theValue:String = root.loaderInfo.parameters [theName];
trace( “Param: ” + theName + ” = ” + theValue );
}
and it echoes all my FlashVars name/values as you say, but I don’t see parameters passed to the Flash player itself. Thanks!
September 27th, 2007 at 10:46 am
Mikep,
The result of your
for..inloop makes sense, but I can hear what you’re saying. The thing is, those other attributes aren’t actually passed into the SWF. They’re attributes that affect Flash Player and the way it appears in the browser — the most important of which, arguably, is the name of which SWF to load. Keep in mind, too, that the<param>tags are specifically children of the<object>and interpreted as such. The<embed>tag, while usually a child of<object>, does stand on its own. The<object>/<param>entity and the<embed>entity each carries its own unique information, though most overlaps.Some of the information you’re after can be gleaned from other objects in the API. For example, the name of the SWF file itself could be derived from the
MovieClip._url. property in AS2 when invoked on the main timeline. In AS3, this has been moved to theLoaderInfo.urlproperty, which you can reach via the sameroot.loaderInfoproperty shown above. While not especially related to the HTML attributes in discussion, you’ll also find plenty about the environment in which Flash Player is spawned via theCapabilitiesclass (wasSystem.capabilitiesin AS2).October 5th, 2007 at 7:38 am
David, I’ve just found your blog and I like your easy-to-read articles
Keep up the good work, man!
BTW, would you mind if I translate some articles to my language ( Indonesian ) and post them to my blog ? I’ll provide a link back to your original article.
October 8th, 2007 at 3:21 pm
anggie,
I value variety in language and, in fact, speak only German with my daughter. I’d love to see these articles translated into Indonesian!
Make sure to send me the links to your work and I’ll update each article on this end with a reciprocal link to your translation.
October 13th, 2007 at 3:05 pm
David,
Once again, thanks so much for posting this for people like me who are just trying to get this particular thing to work.
I was able to get this running on my WordPress blog with Kimili’s SWFObject plugin and one line of code in my flash swf of “flvControl.source = root.loaderInfo.parameters.flvSource;”.
Thanks again!
Craig
October 13th, 2007 at 6:53 pm
Craig,
Sure thing. Glad to help!
October 16th, 2007 at 10:52 am
Thanks TONS for mentioning the root.loaderInfo.parameters
My movie wasn’t returning any of the flashVars I passed it until I simply assigned the root’s loaderInfo to the one I had declared:
objLoaderInfo = root.loaderInfo
After that, everything using my declared LoaderInfo worked as intended and I didn’t have to make any more code changes.
October 16th, 2007 at 10:57 am
Ben,
Glad to hear it.
October 17th, 2007 at 11:12 am
[…] In actionScript 3.0 FlashVars have changed. In actionScript 2.0 you can simply access the variables from the root time line. In actionScript 3.0 you now have to access the LoaderInfo Class. David Stiller has a great article on all the changes. […]
November 1st, 2007 at 4:01 pm
So how do you stop the sound, because a new button with s.stop(); doesn’t seem to be working
November 1st, 2007 at 8:48 pm
Nicole,
In ActionScript 3.0, the
Soundclass doesn’t feature astop()method like it does in AS2. To stop sound in AS3, you have to instantiate aSoundChannelinstance and associate yourSoundinstance with that. Like this:January 30th, 2008 at 10:09 pm
Is there any way to read in the value of the width and height parameters in the embed code?
In AS 2.0 you could set the values in the embed code and then use Stage.height and Stage.width to read them in…. this has changed in AS 3.0 and I have tried desperately to find a solution.
Know of anything? Cheers.
January 30th, 2008 at 10:37 pm
Adam,
FlashVars data (or query string data) enters the SWF via name/value pairs fed separately from the actual embed code. I think you’re asking if it’s possible to read the height and width attributes of the
<object>and<embed>tags, right? If so, that isn’t possible in any version of ActionScript — again, unless you pass it in as a FlashVars variable.AS2’s
Stage.widthandStage.heightproperties are nowstage.stageWidthandstage.stageHeightin AS3. You can reference anyDisplayObjectinstance, including the main timeline, to get yourstagereference, and from there, check the properties mentioned. Does that help?January 30th, 2008 at 11:04 pm
You’re right, what Im asking is only similar in fashion to your original post, but you write intelligently so I thought I’d ask.
Specifically, yes I do want to know if I can read the width and height attributes and until this afternoon, I’d agree with you that It was not possible to read them in any version of AS. Contrary to that a co-worker and I came up with an incredibly simple example that shows the swf being aware of those values in AS 2.0. Of course Im home now and the example is at work.
Regardless, what I’m after is a way to resize my swf before runtime. I’ve created a widget that will be part of an online library where clients can customize and embed their widgets for their own use. I’d like to allow them to create a widget of any size.
Do you know of any routes that will make this possible?
January 31st, 2008 at 8:59 am
Adam,
Definitely, let me know about the example you put together with your co-worker!
I’m curious to see what you found. My hunch is that you’re referencing the read-only
Stage.widthandStage.heightproperties, which indeed return the width and height values of the Stage at the current moment. If you used pixel values in the width and height attributes of your<object>and<embed>tags, then thoseStageproperties will reflect the values of those attributes. On the other hand, it’s just as possible to use percentage values, which will allow the SWF to resize at runtime in response to the user resizing the browser. In that sort of scenario, thoseStageproperties (and their AS3 equivalents) will give you different numbers, depending on the current size of the SWF. In that way, you can tell the size of the Stage (i.e., the SWF), but it may or may not match the numbers specified in the HTML.Check out the
Stageclass in either version of ActionScript to see about using theonResizeevent. That will allow you to adjust the SWF’s width and height as you please — with pixels or percents — and then respond to those values at runtime.January 31st, 2008 at 9:34 am
I think you are exactly correct in you explanation for the changes.
The example was incredibly simple, but if you altered the values in the tags and set the width of a MovieClip to be equal to Stage.width, then when you opened the page in the browser, the MovieClip was resized appropriately.
In fact that is exactly what I’d like to accomplish with AS3 because I have already written a function that resizes my UI on a FullScreenEvent so in essence all the code required is already there, I just need to figure out how (or where) to get the correct values from.
I am going to begin playing with the AS3 equivalents right now. If you’d like a copy of that (incredibly rudimentary) example, feel free to e-mail me and I will send it over.
Thanks for the input though, I’ve been racking my brain for a week now and as of yet, no one else on the net has been able to provide any input at all.
January 31st, 2008 at 9:54 am
Adam,
Assuming you have a movie clip with the instance name
box, the following would adjust the width and height of that movie clip to half the width and height of the Stage:February 18th, 2008 at 2:09 pm
THANK YOU THANK YOU THANK YOU THANK YOU!!!!!!!!!!!!!!!!!!!!!!!
February 18th, 2008 at 2:23 pm
J,
Haha, you’re welcome! Glad I could help.
July 31st, 2008 at 12:27 pm
Hi David, sorry to bring an old post back to life, but I just wanted to tell you that the only way I have been able to pass an external variable to my SWF was to put them after the name of the swf in the js variable, and in the param and the embed tags. I’ve been searching over the internet for about 2 hours now and it seems it’s the only thing that works for me. I have a rather complex project, but I don’t understand why it doesn’t work using the FlashVars method… When using FlashVars, the variables are simply not passed and I get a “url parameter must be non-null” error.
Here are the 3 var I had to change:
In the AC_FL_RunContent script:
‘movie’, ‘gallery?menuName=xml/MenuAng.xml&pictureName=xml/Pictures.xml’,
In the param tag:
and in the embed tag:
src=”gallery.swf?menuName=xml/MenuAng.xml&pictureName=xml/Pictures.xml”
Hope this might help other people!