MovieClip.attachMovie - Clarification

Headerbutton_flash_actionscript_2

Can I attachMovie from a loaded SWF into any other timeline??  No, sorry, it's lame, you can't.  Just like you can't duplicationMovie to another timeline - again, lame lame lame!  But a post on the LiveDocs I posted a while back has some people thinking that I *can* do this or that I found a *way*.  I haven't, I've just had to work around it like everyone else.  I don't know if this is fixed in 8ball or not, but one can only hope.

http://livedocs.macromedia.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001487.html

The work arounds I've done usually include designing my code to build WITHIN the loaded SWF (that has the library assets I wish to attach).
So, IE:

1.  load swf into movie clip _level0.mc_0
2.  AFTER the loaded swf is completely loaded, createEmptyMovieClip INSIDE of _level0.mc_0 called "content_mc"
3.  AttachMovie (from level0) into _level0.mc_0.content_mc
4.  Now, you can attachMovie from _level0.mc_0 into your main content.

So essentially, you're not having your main content out on stage, then loading a SWF to do attachMovie with.  You're creating a movieclip that will be attached AFTER you load the swf that has library items you wish to attach to your main content.

Hope that all makes sense!  I did this with a jigsaw puzzle app where the image/video had to be dynamic on a day-to-day basis - worked great!

hth, - John

The AdminTool

Icon_45_2_1 The AdminTool!  Click here to check it out ;)

localToLocal :: coordinate conversions made easy

Headerbutton_flash_actionscript

You might be interested in this function that I put together, which is REALLY simple, but I use it ALL the time for my conversions and I never have to worry about targeting the right timelines etc, like I do when using globalToLocal/localToGlobal.

First, here is the first example that you should read through to help understand localToGlobal and what it does:

localToGlobal / globalToLocal conversions:
http://www.acmewebworks.com/downloads/localToGlobal_globalToLocal_example.swf

Now for the fun stuff!  This is a _global function you can use called "localToLocal" to convert any clip at any time to any timeline.  And the best part? It totally makes sense when you use it.  It takes the confusion out of using localToGlobal and so forth.

_global.localToLocal(MovieClip_from, MovieClip_to);
from: is the movie clip that you want to map or place.
to: is the movie clip who's coordinates you want to match

IE: 
you have 2 movie clips:
mc_a.mc_aa.mc_aaa
mc_b.mc_ba.mc_baa -
if you want to match mc_aaa's coordinates to mc_baa's coordinates (which lives in mc_ba's timeline), then you send mc_aaa as the "from", and mc_ba (or mc_baa._parent) as the "to"

sample:

////////////////////////////////////////////

var oP:Object = _global.localToLocal(mc_aaa, mc_ba);

trace(oP.x, oP.y);

_global.localToLocal = function(from, to)
{
   var point:Object = {x: 0, y: 0};
   from.localToGlobal(point);
   to.globalToLocal(point);
   return point;
}

/////////////////////////////////////////////

Works every time.

So, if you say to your self "where does this bullet_mc (Which is 3 levels down from the main timeline) hit in the _level0 timeline/stage where my badGuy_mc is located?"

The code would be: 
_global.localToLocal(this.bullet_mc, _level0);

See the important thing to note is that your converting to TIMELINES/containers of movie clips - like the example above, I want to compare my bullet to another movie IN the root timline. So, instead of putting the other movie's instance/path, I put in it's parent's path as to say "Use THOSE coordinates out on root, where my other movie is."

To see it in simple action:
http://www.acmewebworks.com/FLAS/hereToThere_test.swf

FLA:
http://www.acmewebworks.com/FLAS/hereToThere_test.fla

Any questions?  Email me at JohnG@acmewebworks.com

LoadVars Object :: how it works, and then some

Headerbutton_flash_actionscript

The LoadVars Object was introduced with Flash MX in 2002.  Now, instead of using loadVariables or loadVariablesNum, which forced you to send all variable information in your timeline, you could use the LoadVars object and send only what was neccessary.  On top of that, you don't have to define an onData event for a movie clip or timeline.  You simply define a function for the onLoad event of the LoadVars object and bingo, you're done.  Also, the onLoad event carries with it a 'success' flag (onLoad = function(success)).  This flag is a huge improvement over the Flash 5 method of loading variable information.  If success is false, this means that your server or server-side script has returned an error.  This is very helpful in debugging applications and narrowing down where your errors are coming from.  And, like the onData event for a movie clip receiving data, the onLoad only fires when the data is finished returning.

NOTE:  There are compatibility issues with certain browsers and Operating systems.  The issues surrounds using "POST" with certain browsers.  The most prone to have problems is Netscape Navigator on either Windows or Mac platforms.  Certain IE versions on the Mac have the same issue.  Use "GET" if you're experiencing problems.  I don't have specific browser version numbers, but at Zing.com, we don't support Netscape at all, and any IE browser that is 5.5 or higher has tested out just fine.

This example shows you one way to return data and deal with multiple "rows" in a querystring format.  Since we're not dealing with Remoting here, we can't receive a nice array of information, so, we have to return it in a var/val pair like the example below.

we start and end with "&", this is to avoid any confusion as to when the value pair starts and ends:
&Num=3&txtNam0=John&txtName1=Erik&txtName2=Jeff&

If you're using MX to load data from an ASP/PHP/JSP page, here's how you *might* go about it.

// Create a new loadVars object
lv = new LoadVars();

// let's define the onLoad function right here.  you *can* define a separate function
// if you wish, and have the onLoad event call that instead.
// It would look like: lv.onLoad = mySeparateFunction;
// NOTE:  you just need the name, don't include () - this isn't a 'call' its just setting
// a parameter for the returning data

lv.onLoad = function(success){
     if(success){
          // the trip to and back from the server was a success
          if(lv.Num > 0){
               // there are vars to process
               for(x=0;x<lv.Num;x++);
                    // next line assumes that we have textboxes
                    // with instance names of "TextBox1", "TextBox1" etc
                    // and that the returned vars are "text1", "text2" etc
                    _root["TextBox" + x].Text = lv["text" + x];
               }
          }else{
               // no data to return/recordset empty
          }
     }else{
          // the trip to and back from the server was NOT a success
     }
}

// Now, add some variables to send to the server
lv.firstName = "John";
lv.lastName = "Grden";

// sendAndLoad(pageToCall, object to return the data to, [how to send the variables. POST is default

lv.sendAndLoad("myPage.asp",lv, "GET");

NOTE:
If you test in the Flash IDE, you'll have to:
  * hardcode the pages entire address
  * change the receiving pages request to look
     for the variables in the querystring since the Flash
     IDE doesn't send variables using POST - even if you specify
     to do so.  This is because Flash uses the browser to send the
     neccessary header for posting data back to the server.

The beautiful part is that the onLoad function doesn't fire until all data is returned.  So, if you're needing to wait for the data before continuing on in the timeline, just stop() here and in the success part of the 'if' statement, do a play() or goto.  Also, the success flag let's you know if there was a problem in talking to the server.

Now, in this example, I returned a "Num" variable to see how many records are being returned.  You can just as easily do an "if" statement to see if the variable is defined:
for(x=0;x<lv.Num;x++)
{
   if(lv["text" + x] != "undefined")
   {
      // do what you need to
   }
}

One last thing! LoadVars.send and framesets
There is an issue/bug with Flash player 6 whereby if you have a Flash movie embedded in an HTML file that is located in a frameset, you can only send variables using "GET".  If you try to use "POST" it will not work.  The best practice is to always use sendAndLoad.  For more information, check out Muzakdeezign.com.

Any questions?  Send me an email: Johng@acmewebworks.com

Flash Cookies :: Yes my friend, feel the love

Headerbutton_flash_actionscript

Flash cookies, technicaly known as "locally stored Shared Objects" are a very simple way to keep local, persistant data for the client. 

Especially in this day and age of needing to keep track of users on a site, basic browser cookies are good until the user deletes them. The nice thing about the Flash cookies is that they're not widely known about yet.  So, you're MUCH less likely to have your cookies deleted by the end user.  If you have to employ some type of "ban" on a particular user, a Flash cookie will probably go undetected by the would be offender.  But like every technology, the end users WILL find out about it and we'll be back to the same life as a browser based cookie;)

Ok, so how does it work?  Well, you create a variable and assign it the SharedObject reference with the getLocal(cookieName,[path]) method.  You need to provide a name for the cookie you're looking for, and with that said, you can see that you're able to have multiple cookies for a site (I would sure hope so!).  The "path" is optional and a bit confusing at times. The "Path" discussion is lengthy, so, I'll save that for after the example.

The most important method you'll want to remember is flush().  If you want your data persistant (saved), you have to call this method on the shared object:
_root.soVars.flush()
if you don't, your data will only exists for that session. For some applications, this is a good thing, like chat applications.

// Set assign the SharedObject "siteInfo" to _root.soVars
_root.soVars = SharedObject.getLocal("siteInfo");

// You can check for values by accessing the data object in the soVars object
if(_root.soVars.data.firstName == undefined)
{
   _root.soVars.data.firstName = txtFirstName.text;

   // Save your data
   _root.soVars.flush();
}

txtFirstName = _root.soVars.data.firstName;

WOW! That wasn't to bad at all!  I'll bet you rather liked that, eh? Show ain't over son.  Have a seat.

Path fun:
  path: An optional string parameter that specifies the full or partial path to the SWF file that created the shared object, and that determines where the shared object will be stored locally. The default value is the full path.

Now, that may *sound* nice, but it's not a great explanation ;)

First, while we're discussing "path", you'll need to know where they're being stored. On a windows machine, it's:
"C:\Documents and Settings\userAccount\Application Data\Macromedia\Flash Player"
In this folder you'll see all the web sites that have saved Flash cookies as well as programs (IE: FireworksMX, DreamWeaverMX). The actual cookie is an SOL file.

If you don't specify path, Flash assumes the full path (IE: "www.acmewebworks.com/apps/myMovie.swf" OR "/documents and settings/my documents/CookieTest.swf").

Local Drive/CDROM usage:
The path has to go to the SWF level, not just the folder in which it sits (look up at last example).  If you want other SWF's to access THIS SWF's cookies, you can't do it.  Only SWF's loaded from a web server can do this and they have to be on the same domain.

If you're doing a CDROM presentation, you'll want to leave the path blank, as the Flash player will take care of creating a reference for it automatically.  This is perfect because you could never be sure the user's CDROM drive letter/location.

If you have to access the SO with a physical location, for some reason, on the harddrive rather than a web URL, you leave of the drive letter, start with a forward slash and path it out to the exact file name.  If you dont' include the file name, it won't work:
_root.soVars = SharedObject.getLocal("siteInfo", "/Documents and Settings/jgrden/My Documents/CookieTest.swf");

URL usage:
The path can be relative to the folder, unlike the local drive usage.  So, if you have a myMovie.swf sitting in a "movies" folder, it could look like this:
_root.soVars = SharedObject.getLocal("siteInfo", "/movies/" or "http://www.acmewebworks.com/movies/");

If you want other SWF's to use this cookie information, set the path to a relative folder path and don't supply the name of the SWF. 

NOTE: The Flash docs say that this will allow any other SWF on the same domain to get to this cookie - that's not true.  The other SWF's that have to reference that cookie must be in either the same folder OR in a child folder underneath the container folder.  Say what?  like so:

your SWF is in folder "a" and creates a cookie called "userInfo":
soVars = SharedObject.getLocal("userInfo", "/a/");

/a/myMovie.swf

For any other SWF on your site to be able to get to the cookie in "a", they have to either be in the same folder OR in a child folder like so and use the same path parameter in the getLocal method:
soVars = SharedObject.getLocal("userInfo", "/a/");

/a - yes
/a/aa - yes
/a/aa/aaa - yes
/b - no
/b/bb - no
/a/aa/aaa/aaaa - yes

So, if you want your cookie available to the entire site, make sure it's at the root level:
soVars = SharedObject.getLocal("userInfo", "/");

Now, the cool thing is that they've included an onStatus event handler which will return information when you try to write (flush()) to the cookie.  It will return either "error" or "status" based on whether it successfully wrote the data to the cookie or not IF the user has set the local storage settings to zero.

Here is a code snip from a sample file you can download.  It's Flash 2004, so you'll have to have 2004 to open the file.

//---------------------------------------------------------------->
//------------[flash cookies - ActionScript 2.0]-------------------->

// create 2 dynamic textboxes on your stage, call one of them txtFirstName and the other txtInfo
// Make txtInfo a multiline textbox

var soVars:Object = SharedObject.getLocal("testInfo", "/john");

soVars.onStatus = function(infoObj)
{
     // "error" is returned when the user has set the local file storage size to zero
     // "status" is returned when Flash was able to ask permission to save the cookie information
     // and the user said "allow"
     // this event is event invoked if there wasn't any issue with writing to the cookie.
     txtInfo.text += "status: " + infoObj.level + "\n";
}

// soVars will be null if the directory/path cannot be located.
txtInfo.text += "soVars: " + soVars + "\n";

if(soVars.data.firstName == undefined)
{
     // check to see if the data is available.  If not, write it
     soVars.data.firstName = "John";
     soVars.flush();
}

txtFirstName.text = soVars.data.firstName;

for(x in soVars.data)
{
      // loop through all the elements of the object
     txtInfo.text += soVars.data[x] + "\n";
}
//-------------------[end]----------------------------------------->

Download FLA

Well, I hope that helps put Flash cookies in perspective. I have to admit that working in MX, I found that working with cookies was EXTREMELY unpredictable.  One minute the cookies worked, the next, they didn't.  It was like voo doo and once I got it to actually work, I placed a ban on anyone else on the team to touch that code under penalty of a stiffly worded email ;)  With Flash 2004, it worked and acted as though it should work and act.  I did identical tests on MX and 2004 and MX gave me a ton of problems where as 2004 worked the first time around.  I'm assuming that either 1) i was not aware of something obvious that cause MX to have such problems 2) there is a bug in the MX player concerning cookies.

Any questions?  Send me an email: Johng@acmewebworks.com

outdoor furniture | log furniture | home office furniture | furniture row | harlem furniture | badcock furniture | north carolina furniture | gallery furniture | used furniture dealer | furniture store