Examples and Discussion

You load an external SWF file at runtime using Loader.load method. You extract the file via Loader.content, cast it to MovieClip, and store in a MovieClip variable. You add a listener to mouse clicks to your loaded MovieClip only to discover that it does not respond to clicks. Isn't Loader.content in the case of loading an SWF file a MovieClip? We discuss the issue below and give examples. To play with the examples, you need to dowload the zip file below with source code files. The screen shot below doesn't tell much.

Download

Download the well-commented source files corresponding to the tutorial.

Example 1

In Example 1 (folder example1 in the zip file), we have two swf files, ext1.swf and ext2.swf. Neither contains any ActionScript code. ext1.swf contains a Shape drawn on the stage and static text, ext2.swf contains a Shape and static text that have been converted to a Symbol, a MovieClip. The file container.fla produces an SWF that loads both files at run time. Here is the Timeline code in container.fla and comments. The case of loading SWFs that do not contain code is particularly important in mobile development for compatability with iOS.

import flash.events.MouseEvent;

import flash.display.Loader;

import flash.events.Event;

import flash.display.MovieClip;

We create two loaders and two MovieClip variables to load and to hold our two external SWFs after loading.

var loader_1=new Loader();

var external_1:MovieClip;

var loader_2=new Loader();

var external_2:MovieClip;

counter_1 and counter_2 variables are only for for demonstration purposes. They will count clicks on each of the loaded clips and display that number in infoBox_1 and infoBox_2 which are text fields created on the stage.

var counter_1:int=0;

var counter_2:int=0;

We proceed to load our two external SWFs.

loader_1.contentLoaderInfo.addEventListener(Event.COMPLETE,clip1Loaded);

loader_1.load(new URLRequest("ext1.swf"));

loader_2.contentLoaderInfo.addEventListener(Event.COMPLETE,clip2Loaded);

loader_2.load(new URLRequest("ext2.swf"));

When loading is complete, we extract content of each loader via Loader.content. Loader.content is, in general, a DisplayObject. To communicate to the compiler that in our case Loader.content is a MovieClip, we cast it to MovieClip. That makes sense as, according to the documentation, in the case of an SWF file being loaded, Loader.content is the root display object of the SWF. Root display object of an SWF file is its MainTimeline which, in turn, is an instance of the SWF's Document Class. (If a Document Class is not specified, one is created automatically.) A Document Class extends MovieClip (or a Sprite). We store the two MovieClips in variables external_1 and external_2. We expect them to behave like MovieClips. Yet, they do not quite do so as the following shows.

We attach listeners to mouse clicks to the extracted content, external_1, external_2. If external_1, external_2 were usual instances of the MovieClip class, they would both respond to clicks. Yet, only external_2, the one containing a MovieClip, responds, the other one does not respond to clicks.

function clip1Loaded(e:Event):void {

external_1=MovieClip(loader_1.content);

this.addChild(external_1);

external_1.x=100;

external_1.y=50;

infoBox_1.text=String(counter_1);

external_1.addEventListener(MouseEvent.CLICK,onClick1);

}

 

function onClick1(e:MouseEvent):void {

counter_1+=1;

infoBox_1.text=String(counter_1);

}

 

function clip2Loaded(e:Event):void {

external_2=MovieClip(loader_2.content);

this.addChild(external_2);

external_2.x=100;

external_2.y=220;

infoBox_2.text=String(counter_2);

external_2.addEventListener(MouseEvent.CLICK,onClick2);

}

 

function onClick2(e:MouseEvent):void {

counter_2+=1;

infoBox_2.text=String(counter_2);

}

Of course, such behavior of loaded SWFs is worth investigating but it does not really present a problem. There is a number of ways to handle it. You can leave the loaded content inside your instance of Loader, say loader_1, add loader_1 to the Display List and add listener to loader_1:

function clip1Loaded(e:Event):void {

this.addChild(loader_1);

loader_1.x=100;

loader_1.y=50;

infoBox_1.text=String(counter_1);

loader_1.addEventListener(MouseEvent.CLICK,onClick1);

}

Or you can put loaded content in a Sprite container and add event listener to that container. Declare the container at the beginning of the script:

var cont_1:Sprite=new Sprite();

Then define event handler as:

function clip1Loaded(e:Event):void {

external_1=MovieClip(loader_1.content);

cont_1.addChild(external_1);

this.addChild(cont_1);

cont_1.x=100;

cont_1.y=50;

infoBox_1.text=String(counter_1);

cont_1.addEventListener(MouseEvent.CLICK,onClick1);

}

Either one of the two ways will make the clip corresponding to ext1.swf respond to clicks.

Example 2

In Example 2 (folder example2 in the zip file), we do not create any content on the stage, and we do not use Timeline code. We use Document Clases for loaded and loading files. The effect is the same. Example 2, however, provides greater clarity about the difference between ordinary instances of classes that extend MovieClip versus instances that serve as the MainTimeline of an SWF file.

The file ext1.swf has the Document class SwfWithShape. That class extends the MovieClip class and draws a rectangular Shape. The file ext2.swf has the Document class SwfWithSprite. That class also extends MovieClip and draws a rectangular Sprite. (The simple code for both classes is shown later below.) Here is the Document Class, LoadingSwf, of the container.fla that will load both SWFs.

LoadingSwf class loads ext1.swf and ext2.swf using Loader.load. As before we extract the content via Loader.content and cast to MovieClip. Loader.content contains the root display object of the loaded SWF file. The root display object is the MainTimeline which, in turn, is an instance of the Document Class (SwfWithShape and SwfWithSprite, respectively). Yet, external_1 containing a Shape does not behave as an ordinary instance of SwfWithShape class would, and does not respond to clicks. To compare, we create an instance of SwfWithShape and store it in testClip. testClip does respond to clicks, as expected.

package {

import flash.display.MovieClip;

import flash.display.Loader;

import flash.net.URLRequest;

import flash.events.MouseEvent;

import flash.events.Event;

 

public class LoadingSwf extends MovieClip {

var loader_1:Loader;

var loader_2:Loader;

var external_1:MovieClip;

var external_2:MovieClip;

var test:MovieClip;

 

public function LoadingSwf() {

initLoaders();

test=new SwfWithShape();

this.addChild(test);

test.x=50;

test.y=50;

test.addEventListener(MouseEvent.CLICK,testClick);

}

 

private function initLoaders():void {

loader_1=new Loader();

loader_2=new Loader();

loader_1.contentLoaderInfo.addEventListener(Event.COMPLETE,clip1Loaded);

loader_1.load(new URLRequest("ext1.swf"));

loader_2.contentLoaderInfo.addEventListener(Event.COMPLETE,clip2Loaded);

loader_2.load(new URLRequest("ext2.swf"));

}

 

private function clip1Loaded(e:Event):void {

external_1=MovieClip(loader_1.content);

this.addChild(external_1);

external_1.x=190;

external_1.y=50;

external_1.addEventListener(MouseEvent.CLICK,onClick1);

}

 

private function onClick1(e:MouseEvent):void {

trace("Shape clip clicked");

}

 

private function clip2Loaded(e:Event):void {

external_2=MovieClip(loader_2.content);

this.addChild(external_2);

external_2.x=330;

external_2.y=50;

external_2.addEventListener(MouseEvent.CLICK,onClick2);

}

 

private function onClick2(e:MouseEvent):void {

trace("Sprite clip clicked");

}

 

private function testClick(e:MouseEvent):void {

trace("Test clip clicked");

}

}

}

Here is the code in SwfWithShape class. SwfWithSprite is the same except that 'rect' is a Sprite.

package {

import flash.display.MovieClip;

import flash.display.Shape;

 

public class SwfWithShape extends MovieClip {

private var rect:Shape;

 

public function SwfWithShape() {

rect=new Shape();

graphRect();

this.addChild(rect);

}

 

private function graphRect():void {

rect.graphics.beginFill(0x660000);

rect.graphics.drawRect(0,0,120,90);

rect.graphics.endFill();

}

}

}

Note: It is not reparenting that is at issue; it is the nature of the MainTimeline of an SWF. The result wouldn't be any different, if you replaced the code within clip1Loaded with the code:

this.addChild(loader_1);

loader_1.x=190;

loader_1.y=50;

loader_1.getChildAt(0).addEventListener(MouseEvent.CLICK,onClick1);

The MainTimeline is an instance of the MovieClip class but it is also its own root unlike any other instance of MovieClip. The behavior of loaded ext1.swf above is not dissimilar to the behavior of the MainTimeline in any SWF file.

Example 3

In timeline.fla file (example2 folder), we create a Shape on the Stage and a MovieClip. We place the following simple code on the Timeline. 'this' in this context represents the MainTimeline.

this.addEventListener(MouseEvent.CLICK,onClick);

 

function onClick(e:MouseEvent): void {

trace("Movie clicked");

}

The only part of the compiled file that responds to clicks is the MovieClip on the stage but not the Shape.

 

This tutorial was written by Barbara Kaskosz of flashandmath.

Back to AS3 How-Tos and Tips              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.