PDA

View Full Version : Loaded movie can't talk to movie that loaded it!


gburks
08-06-2006, 07:19 AM
Hi,
I have a site I am building in AS3. I have a main SWF, site.swf, that loads the subsections as seperate SWF's only when a user clicks on them (to save on initial load time).

For my subsections, I need to be able to communicate with the SWF that loaded it. In AS2, this was simple enough - just say something like _parent._parent.gotoAndPlay("something"), and step up enough levels to speak to movie clips in the main SWF.

Trying to do this in AS3, however, results in errors such as this when trying to compile my subsection SWF:


TypeError: Error #1009: Cannot access a property or method of a null object reference.


... because it thinks I am trying access properties of an object that doesn't exist. The result is that I can't compile my subsection SWF's.

For example, I am unable to reference a variable in the main SWF using this code in my subsection SWF:

myText = this.parent.parent.parent.parent.sectionTitle;

Surely there must be a way to do this? Can I at least tell the Flash 9 Alpha compiler not to stop when it runs across this?

Thanks,
Graham

Tink
08-06-2006, 10:57 AM
have u tried tracing this.parent.parent.parent.parent.sectionTitle;

if thats what its complaining about, i think you'll find its value is null.

astgtciv
08-06-2006, 03:37 PM
gburks, is this a compile-time error? Cuz it does look like a run-time error... but I'm guessing you know what you are talking about :)

I think there's two way to go about this.
#1: (Weak-Typed Solution). To emulate the freedom of AS2, do not compile in "strict mode". Edit > Preferences > ActionScript > ActionScript 3.0 Settings > Uncheck "Strict Mode".
#2: (Strong-Typed Solution). You need to refer explicitly to the Class of your main swf (e.g., MainSWFClass, the one that has the "sectionTitle" property) from your subsection swf. To do that, you have to add the main swf's source path to the source path of the subsection swf. File > Publish Settings > Flash > ActionScript 3.0 Settings > Classpath > +. Once you have done that, you then explicitly cast the reference this.parent.parent.parent.parent into your MainSWFClass:


myText = MainSWFClass(this.parent.parent.parent.parent).sec tionTitle;


Now, I think that the MainSWFClass definition would be included in the subsection swf (thus increasing its size), unless you use either "-external-library-path=pathto/main.swf" or "-externs=mainPackage.MainSWFClass" to explicitly exclude it from compilation. Unfortunately, I don't think Flash 9 Alpha has any place to specify advanced compiler options (someone please correct me on this!) So, you'd have to use the command-line compiler from the free Flex 2 SDK...

hbd
08-06-2006, 06:01 PM
It seems that we can access variables easily from the above level, but little harder from the below level.

this.someMovieClip.someVariable or this.someLoader.content.someVariable worked fine, but this.parent.parent.someVariable didn't work.
So I tried this.parent.parent["someVariable"] and it worked. But I could still access native properties like alpha or x y normaly from the below level.

Does anyone have any better ideas about this?

astgtciv
08-06-2006, 08:06 PM
Oh yeah, forgot you can also do []! Good call, hbd!

gburks
08-08-2006, 01:39 AM
astgtciv,
Your suggestion #2 above has got me on the right track, but it is still not letting me access the main swf that loaded the sub swf.

Here is an example: I have a file, MainSWF (with a Document class specified to have the same name), and that loads another swf, SubSWF (with a Document class of the same name). I updated the Class Path as instructed.

Here is the code in the MainSWF:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.CO MPLETE, completeHandler);
loader.load(new URLRequest("SubSWF.swf"));

function completeHandler(event:Event):void {
addChild(loader);
trace("from MainSWF: ", loader.content.parent); //from MainSWF: [object Loader]
trace("from MainSWF: ", loader.content.parent.parent); //from MainSWF: [object MainSWF]
}
and here is the code from the SubSWF:
trace("from SubSWF: ", parent); // When loaded into MainSWF: from SubSWF: [object Stage]
trace("from SubSWF: ", parent.parent); // When loaded into MainSWF: from SubSWF: null

What I am trying to demonstrate is that, in MainSWF, I can trace loader.content.parent and it returns the Loader. Next, I trace one more parent up, loader.content.parent.parent, and it traces the MainSWF.

However, from within SubSWF running as a loaded movie of MainSWF, I trace parent and again get the Loader. It makes sense then that I could trace one parent up and get MainSWF, but instead I get null.

Any thoughts? Do I need to manually describe my classes in an external .as file that lives in the Class Path? Can you point me to a tutorial to get me started?

astgtciv
08-08-2006, 02:24 AM
from within SubSWF running as a loaded movie of MainSWF, I trace parent and again get the Loader

From your trace it looks like you are not getting the Loader in that case, you are getting the Stage (which is why its parent is null). From you described, though, it seems that you should be getting the Loader, indeed... want to paste the code?

gburks
08-08-2006, 04:19 AM
sorry, in my post above, I need to modify the code that is traced from my SubSWF when the MainSWF runs and loads it and renders its trace:
trace("from SubSWF: ", parent); // When loaded into MainSWF: from SubSWF: [object Loader]
trace("from SubSWF: ", parent.parent); // When loaded into MainSWF: from SubSWF: null

.... the typo was that the first trace, trace(parent), returns the Loader object. From the MainSWF, I am able to get the Loader's parent which is MainSWF, but from the SubSWF, the highest I can walk up is to Loader.

Basically, saying Loader.parent comes back as null. I can't walk up any higher than the Loader object from actionscript within the SubSWF.

I went ahead and attached the files so everyone can see what I mean.

astgtciv
08-08-2006, 06:39 AM
It seems that Loader only adds content as a child (in the DisplayList sense) once Loader itself is added to the display list.

So, if you have


function traceParents() {
trace("from SubSWF: ", parent);
trace("from SubSWF: ", parent.parent);
}


in the SubSWF, and in the MainSWF


var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.CO MPLETE, completeHandler);
loader.load(new URLRequest("SubSWF.swf"));

function completeHandler(event:Event):void {
addChild(loader);
loader.content["traceParents"]();
trace("from MainSWF: ", loader.content.parent); //from MainSWF: [object Loader]
trace("from MainSWF: ", loader.content.parent.parent); //from MainSWF: [object MainSWF]
}


then everything works fine, but if you move loader.content["traceParents"](); above addChild(loader) then you get the null. Before you were tracing stuff basically in the constructor of the SubSWF, so of course nothing was initialized yet in terms the display list.

I am too lazy to go check Loader code, but I bet it listens to its Event.ADDED, and only then does addChild(content).

hbd
08-08-2006, 07:08 AM
Is there a reason you have to write addChild inside the handler?


var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.CO MPLETE, completeHandler);
loader.load(new URLRequest("SubSWF.swf"));
addChild(loader);

function completeHandler(event:Event):void {....}


Coz above code works fine.

astgtciv
08-08-2006, 07:19 AM
Yep, looks like adding it right away works too. But the loader must be in the display list for the loaded content to access it via parent.