How to get all images from HTML control in Flex? - html

I have a HTML control in Flex that succefully loads a page.
Is there someway that i can extract or get all the images from that HTML control and show them?

You can actually use the HTML document DOM and ask about all img tags. It's a lot cleaner this way.
Once you get the DOM it's all standard so you can check HTML DOM documentation if you're unsure about something.
Here's quick example. I'll just write the onComplete function, as it would be called in Taurayi's example
var _imagesSrc:Array= [];
private function onComplete(e:Event):void
{
var htmlLoader:HTMLLoader = e.target as HTMLLoader;
var doc:* = htmlLoader.window.document; //use void (*) type for DOM objects
var imgTags:* = doc.getElementsByTagName("img");
if(imgTags)
{
for(var i:int=0;i<imgTags.length;i++)
{
var src:* = imgTags[i].getAttribute("src"); //not sure about return type here, could also be a String
if(src)
_imagesSrc.push(src.toString());
}
}
}

Well an idea would be that you load the html page using HTMLLoader and then when it has loaded you get the source. Then using a parser or regex you would extract the values of the src attributes of the <img /> tags. The values of the src attributes will be the urls to the images on the page you loaded. Then using Loader and said urls, you would load them into your flash application.
Here's an example:
Main.as(document class):
package
{
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.html.HTMLLoader;
import flash.net.URLRequest;
public class Main extends Sprite
{
public function Main():void
{
var htmlLoader:HTMLLoader = new HTMLLoader();
htmlLoader.addEventListener(Event.COMPLETE, onComplete);
htmlLoader.width = stage.stageWidth;
htmlLoader.height = stage.stageHeight;
htmlLoader.load(new URLRequest("http://www.wampserver.com/"));
}// end function
private function onComplete(e:Event):void
{
var htmlLoader:HTMLLoader = e.target as HTMLLoader;
var body:String = htmlLoader.window.document.body.outerHTML;
var imgTags:Array = getImgTags(body);
var src:String = getSrc(imgTags[1]);
trace(src); // output: http://www.wampserver.com/wp-content/themes/wampserver/img/home-title.png
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
loader.load(new URLRequest(src));
}// end function
private function onLoaderComplete(e:Event):void
{
var loader:Loader = (e.target as LoaderInfo).loader;
addChild(loader);
}// end function
private function getImgTags(source:String):Array
{
return source.match(/(<img.*?>)/g);
}// end function
private function getSrc(imgTag:String):String
{
return imgTag.match(/src="(.*?)"/)[1];
}// end function
}// end class
}// end package
Keep in mind this is just an idea, there are some obvious flaws.

Related

Creating inline function after loading an image causes memory leak

I was analyzing an unexpected memory leak in our game project and found some strange results. I am profiling using Adobe Scout and eliminated all other factors like starling, texture or our loading library. I reduced the code to simply load a png and immediately allocate an empty inline function on its complete event.
Loading a png allocates image on default and if you do nothing after loading gc clears that image. But creating an inline function seems to prevent that image to be garbage collected somehow. My test code is;
public class Main extends Sprite
{
private var _callbacks:Array = new Array();
public function Main()
{
load("map.png", onPngLoaded);
}
private function onPngLoaded(bitmap:Bitmap):void
{
_callbacks.push(function():void { });
}
public function load(url:String, onLoaded:Function):void
{
var loader:Loader = new Loader;
var completeHandler:Function = function(e:Event):void {
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
onLoaded(loader.content);
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.load(new URLRequest(url));
}
}
If you remove the code which creates an inline function;
private function onPngLoaded(bitmap:Bitmap):void
{
// removed the code here!
}
gc works and clears the image from memory.
Since having no logical explanation for this, I suspect of a flash / as3 bug. I will be glad to hear any comments who tests my code and gets the same results.
Note: To test, replace the main class of an empty as3 project with my code and import packages. You can load any png. I am using flashdevelop, flex-sdk 4.6.0 and flash player 14.
When you create an inline function, all local variables get stored with it in the global scope. So in this case, that would include the bitmap parameter.
For more information, see this:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f54.html
Here is the relevant part:
Any time a function begins execution, a number of objects and properties are created. First, a special object called an activation object is created that stores the parameters and any local variables or functions declared in the function body....Second, a scope chain is created that contains an ordered list of objects that Flash Player or Adobe AIR checks for identifier declarations. Every function that executes has a scope chain that is stored in an internal property. For a nested function, the scope chain starts with its own activation object, followed by its parent function’s activation object. The chain continues in this manner until it reaches the global object.
This is another reason why inline/anonymous functions are best avoided in most situations.
So using asc2, Flash/Air 19 : Yes I get the same results that you are seeing, but due to the anonymous function holding global references I expected that (like my original comment stated).
I rewrote it in my style based upon Adobe's GC technical articles and bulletins and no leaks are seen as all the global references are removed.
A cut/paste AIR example:
package {
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.System;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Main extends Sprite {
var timer:Timer;
var button:CustomSimpleButton;
var currentMemory:TextField;
var highMemory:TextField;
var hi:Number;
var _callbacks:Array = new Array();
public function Main() {
button = new CustomSimpleButton();
button.addEventListener(MouseEvent.CLICK, onClickButton);
addChild(button);
currentMemory = new TextField();
hi = System.privateMemory;
currentMemory.text = "c: " + hi.toString();
currentMemory.x = 100;
addChild(currentMemory);
highMemory = new TextField();
highMemory.text = "h: " + hi.toString();
highMemory.x = 200;
addChild(highMemory);
timer = new Timer(100, 1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerHandler);
timer.start();
}
function timerHandler(e:TimerEvent):void{
System.pauseForGCIfCollectionImminent(.25);
currentMemory.text = "c: " + System.privateMemory.toString();
hi = System.privateMemory > hi ? System.privateMemory : hi;
highMemory.text = "h: " + hi.toString();
timer.start();
}
function onClickButton(event:MouseEvent):void {
for (var i:uint = 0; i<100; i++) {
//load("foobar.png", onPngLoaded);
load2("foobar.png");
}
}
private function onPngLoaded2(bitmap:Bitmap):void {
var foobarBitMap:Bitmap = bitmap; // assuming you are doing something
foobarBitMap.smoothing = false; // with the bitmap...
callBacks(); // not sure what you are actually doing with this
}
private function callBacks():void {
_callbacks.push(function ():void {
});
}
public function completeHandler2(e:Event):void {
var target:Loader = e.currentTarget.loader as Loader;
// create a new bitmap based what is in the loader so the loader has not refs after method exits
var localBitmap:Bitmap = new Bitmap((target.content as Bitmap).bitmapData);
onPngLoaded2(localBitmap);
}
public function load2(url:String):void {
var loader2:Loader = new Loader;
loader2.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler2, false, 0, true);
loader2.load(new URLRequest(url));
}
}
}
import flash.display.Shape;
import flash.display.SimpleButton;
class CustomSimpleButton extends SimpleButton {
private var upColor:uint = 0xFFCC00;
private var overColor:uint = 0xCCFF00;
private var downColor:uint = 0x00CCFF;
private var size:uint = 80;
public function CustomSimpleButton() {
downState = new ButtonDisplayState(downColor, size);
overState = new ButtonDisplayState(overColor, size);
upState = new ButtonDisplayState(upColor, size);
hitTestState = new ButtonDisplayState(upColor, size * 2);
hitTestState.x = -(size / 4);
hitTestState.y = hitTestState.x;
useHandCursor = true;
}
}
class ButtonDisplayState extends Shape {
private var bgColor:uint;
private var size:uint;
public function ButtonDisplayState(bgColor:uint, size:uint) {
this.bgColor = bgColor;
this.size = size;
draw();
}
private function draw():void {
graphics.beginFill(bgColor);
graphics.drawRect(0, 0, size, size);
graphics.endFill();
}
}

URLLoader loads multi files and the result order is the same as call load()

Since URLLoader is async, how to make sure the order of data from server side is the same as the loader.load() call? In other words, the data order in totalResults is the same order of url-related content?
Following is code snippet:
1.for each(var url in urls) {
loadData(url);
}
2.private function loadData(url:String):void {
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
var request:URLRequest = new URLRequest(url);
urlLoader.load(request);
}
3.private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var result:Object = loader.data;
totalResults.push(result);// suppose totalResults is Array and a property in the class.
}
You can extend URLLoader class functionality.
dynamic class DynamicURLLoader extends URLLoader { }
Then store data ( in your case probably index ) in loader object, before requesting:
var urlLoader:DynamicURLLoader = new DynamicURLLoader();
urlLoader.index = ...
After response, retrieve that data ( in your case index ):
var loader:DynamicURLLoader = DynamicURLLoader(event.target);
totalResults[ loader.index ] = loader.data;
you could either use BulkLoader - it got this build-in. or you have to build your own queue, where one file is loaded after the other.
code snippet:
0.var queue:Array, totalResults:Array = [];
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
1.for each(var url in urls) {
loadData(url);
}
2.private function loadData(url:String):void {
var request:URLRequest = new URLRequest(url);
queue.push(request);
}
3.private function doQueue() {
if (queue.length > 0) {
var arr:Array = queue.splice(0,1);
var req:URLRequest = arr[0] as URLRequest;
urlLoader.load(req);
}
else {
// queue done !
trace(totalResults);
}
}
4.private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var result:Object = loader.data;
totalResults.push(result);// suppose totalResults is Array and a property in the class.
doQueue();
}
You can load each url sequentially one after the other in order like in the following example:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class Main extends Sprite
{
private var _urls:Vector.<String>;
private var _counter:int;
private var _data:Array;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_urls = Vector.<String>(["text1.txt", "text2.txt", "text3.txt" ]);
_counter = 0;
_data = [];
loadNext();
}// end function
private function loadNext():void
{
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.load(new URLRequest(_urls[_counter]));
}// end function
private function onComplete(event:Event):void
{
_data.push((event.target as URLLoader).data);
if (_counter++ == (_urls.length - 1)) trace("complete");
else loadNext();
}// end function
}// end class
}// end package
The methods loadNext() and onComplete() act as a loop. When loadNext() is called, an URLLoader object is instantiated and loads an url in the Vector.<String> object _urls. It uses the _counter object as a counter that is increment upon each UrlLoader object's "complete" event.
When the onComplete() event handler is called, it pushes the data loaded by the URLLoader object into an array called _data. Finally an if statement checks to see if all the urls have been loaded, if not, it increments the counter, if so, it executes the rest of the code in the application, in this case trace("complete");.
Why not just use HTTPService, which allows you to use AsyncToken to determine which initial call resulted in which initial result? That way, you don't have to wait between calls (with the performance degradation that implies.) Here is some documentation about how it works with Remoting, which is similar http://flexdiary.blogspot.com/2008/11/more-thoughts-on-remoting.html . With HttpService, you get back the token as a result of the send() method.

AS3 > Starting class on certain frame?

I created an AS file and used it as a class, inside it I called buttons and slideshow images.
After that I decided to create an intro by moving the timeline. My problem is that all the objects are displayed from the very first frame, is there a way to make the entire class start after certain frame?
Code for reference:
package {
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.display.MovieClip;
public class play extends MovieClip {
private var loader:Loader = new Loader();
private var images:Array = ["img/Layer_1.jpg", "img/Layer_2.jpg", "img/Layer_3.jpg", "img/Layer_4.jpg", "img/Layer_5.jpg", "img/Layer_6.jpg", "img/Layer_7.jpg", "img/Layer_9.jpg", "img/Layer_10.jpg", "img/Layer_11.jpg", "img/Layer_12.jpg", "img/Layer_13.jpg", "img/Layer_14.jpg"];
private var triangleButton:triangle = new triangle;
private var squareButton:square = new square;
private var crossButton:cross = new cross;
private var circleButton:circle = new circle;
public function play() {
loadNextImage();
addChild(loader);
loader.x = 137;
loader.y = 65;
//Buttons
addChild(triangleButton);
triangleButton.width = 28;
triangleButton.scaleY = triangleButton.scaleX;
triangleButton.x = 804;
triangleButton.y = 107;
triangleButton.addEventListener(MouseEvent.CLICK, slideGames);
addChild(circleButton);
circleButton.width = 28;
circleButton.scaleY = circleButton.scaleX;
circleButton.x = 825;
circleButton.y = 130;
circleButton.addEventListener(MouseEvent.CLICK, slideGames);
addChild(crossButton);
crossButton.width = 28;
crossButton.scaleY = crossButton.scaleX;
crossButton.x = 804;
crossButton.y = 155;
crossButton.addEventListener(MouseEvent.CLICK, slideGames);
addChild(squareButton);
squareButton.width = 28;
squareButton.scaleY = squareButton.scaleX;
squareButton.x = 780;
squareButton.y = 130;
squareButton.addEventListener(MouseEvent.CLICK, slideGames);
}
public function slideGames(event:MouseEvent):void {
loadNextImage();
}
public function loadNextImage() : void {
// Increment the image
_imageIndex++;
// If we've reached the end of the array, start over
if (_imageIndex >= images.length) {
_imageIndex = 0;
}
// Now get the image source from the array and tell the loader to load it
var imageSource : String = images[_imageIndex] as String;
loader.load(new URLRequest(imageSource));
}
// Next image to display
protected var _imageIndex : int = -1;
}
}
Yes, instead of initializing everything in the constructor of your class (play()), you can move it to another function, and call that from the timeline. I am assuming you are using the play class as the document class.
So instead of
public function play() {
you would rename it to
public function play_start() {
Create an empty constructor named play() at this point if you want to.
In the flash IDE, select the frame where you want the items to appear, then create a keyframe there.
Select the keyframe and go to the Actions panel (F9) and enter the following code:
this.play_start();
once the playhead is at the keyframe, your code should be executed.

How to merge two bitmaps into one bitmap and save it to local drive

I've searched a lot but nothing seems working for me. Assistance of somebody is very much appreciated in this regard. Thanks a lot. I'm new to AS3. I'm using FlashDevelop. Below is the code I used,
package
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.net.URLRequest;
import flash.events.MouseEvent;
import flash.utils.ByteArray;
import flash.net.FileReference;
import com.adobe.images.JPGEncoder;
import flash.geom.Rectangle;
public class Main extends Sprite
{
private var modelBmp : BitmapData;
private var alphaBmp : BitmapData;
private var destPoint : Point = new Point(0, 0);
private var mask1:Loader = new Loader();
private var mask2:Loader = new Loader();
private var f:Bitmap;
private var fileReference:FileReference = new FileReference();
private var movie:MovieClip = new MovieClip();
private var loadedimage:Bitmap;
private var loadedimage1:Bitmap;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
if (loadAssets()) {
trace('merge loaded');
modelBmp = new BitmapData(loadedimage.width, loadedimage.height);
modelBmp.draw(loadedimage);
alphaBmp = new BitmapData(loadedimage1.width, loadedimage1.height);
alphaBmp.draw(loadedimage1);
var rect:Rectangle = new Rectangle(0, 0, 200, 200);
var pt:Point = new Point(20, 20);
var mult:uint = 0x80; // 50%
modelBmp.merge(alphaBmp, rect, pt, mult, mult, mult, mult);
var bm1:Bitmap = new Bitmap(modelBmp);
addChild(bm1);
bm1.x = 400;
var bm2:Bitmap = new Bitmap(alphaBmp);
addChild(bm2);
bm2.x = 200;}
}
private function loadAssets():void
{
mask2.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete1);
mask1.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
mask2.load(new URLRequest("Photo.png"));
mask1.load(new URLRequest("back.png"));
trace('asset loaded');
}
private function loadComplete(event:Event):void
{
loadedimage = Bitmap(mask1.content)
var bitmap:BitmapData = new BitmapData(loadedimage.width, loadedimage.height, false, 0xffffffff);
bitmap.draw(loadedimage, new Matrix())
var image:Bitmap = new Bitmap(bitmap);
//addChild(image);
trace('image1 loaded');
}
private function loadComplete1(event:Event):void
{
loadedimage1 = Bitmap(mask2.content)
var bitmap:BitmapData = new BitmapData(loadedimage1.width, loadedimage1.height, false, 0xffffffff);
bitmap.draw(loadedimage1, new Matrix())
var image:Bitmap = new Bitmap(bitmap);
//addChild(image);
trace('image2 loaded');
}
}
}
How to use Bitmap.merge():
var bitMapData1:BitmapData = new BitmapData(100,100); //or embedded item
var bitMapData2:BitmapData = new BitmapData(100,100); // "
var bitmap:Bitmap = new Bitmap(bitMapData1);
this.addChild(bitmap);
bitmap.merge(bitMapData2, new Rectangle(0, 0, 100, 100), new Point(0, 0), 128, 128, 128, 128);
As others have noted, Flash is forbidden from creating, altering, modifying, saving or otherwise manipulating files. There are several ways of getting this data out of flash and into a technology that has these abilities (such as PHP), or you can use the flash.filesystem package in Air (as previously noted).
Hope that helps =
= update =
Your code is problematic in that you are writing your urlRequest and then acting upon the loaded content in one function. The URL request simply hasn't had time to fire, and the rest of your function fails, because Mask2.content == undefined or null... I'm surprised it doesn't throw an error.
Other than that, it looks like it should work.
Try this:
private var _mask1:Loader; // _lowerCase naming convention
//constructor... call init()
//init.. call loadAssets()
private function loadAssets():void
{
_mask1 = new Loader(); //generally not a good idea to create objects when declaring variable
_mask1.addEventListener(Event.COMPLETE, onCompleteFunction);
_mask1.load(new URLRequest("Dress04.png"));
private function onCompleteFunction(e:Event):void
{ ...
Note that since you are doing multiple loads, you will need to check if both are loaded before acting upon the loaded content. You can do this with a simple boolean check or... whatever. You might also check out something like LoaderMax, which has built in load queueing like this.
Note also that good asset loading usually involves a try...catch statement and the handling of several events - IOErrorEvent.IO_ERROR , for example.
= update 2 =
Okay - we're just getting into programming logic now.
This is a problem:
private function init(e:Event = null):void
{
if (loadAssets()) {
trace('merge loaded');
//...
//...
private function loadAssets():void
{...
You're essentially asking loadAssets() to a return a value, but its return type is void, and so will absolutely fail. Besides that, the loadAssets() is only instigating the loader, and not tracking whether the load was successful.
Lets break it into a few more steps, and set up a really simple loading queue:
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
public class Main extends Sprite
{
private var modelBmp : BitmapData;
private var alphaBmp : BitmapData;
private var destPoint : Point;
private var mask : Loader;
private var f : Bitmap;
private var movie : MovieClip;
private var loadedImages: Array;
private var imageQueue : Array;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
//initialize variables
private function init(e:Event = null):void
{
//just set up a simple queue of images to load
imageQueue = ['Photo.png', 'back.png'];
loadedImages = [];
destPoint = new Point(0, 0);
mask = new Loader();
movie = new MovieClip();
loadAsset( imageQueue[0] );
}
private function loadAsset(target:String):void
{
mask.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
mask.load(new URLRequest(target));
}
private function loadComplete(event:Event):void
{
loadedimage = Bitmap(mask.content);
var bitmap:BitmapData = new BitmapData(loadedimage.width, loadedimage.height, false, 0xffffffff);
bitmap.draw(loadedimage, new Matrix())
var image:Bitmap = new Bitmap(bitmap);
loadedImages.push(image);
mask.unload();
trace(imageQueue[0] + " loaded");
imageQueue.splice( 0, 1); //remove the first index
if (imageQueue.length > 0){
loadAsset(imageQueue[0]);
}else{
mergeImages(); //if the queue is empty, then merge
}
}
private function mergeImages():void
{
modelBmp = new BitmapData(Bitmap(loadedImages[0]).width, Bitmap(loadedImages[0]).height);
modelBmp.draw(loadedimage);
alphaBmp = new BitmapData(Bitmap(loadedImages[1]).width, Bitmap(loadedImages[1]).height);
alphaBmp.draw(loadedimage1);
var rect:Rectangle = new Rectangle(0, 0, 200, 200);
var pt:Point = new Point(20, 20);
var mult:uint = 0x80; // 50%
modelBmp.merge(alphaBmp, rect, pt, mult, mult, mult, mult);
var bm1:Bitmap = new Bitmap(load);
addChild(bm1);
bm1.x = 400;
var bm2:Bitmap = new Bitmap(alphaBmp);
addChild(bm2);
bm2.x = 200;}
}
}
I haven't checked to see if this works, so it might take a little messing with, the but basic idea should work for you. There are a bunch of ways to deal with chained conditional asset loading, this is a simple example.
Hope that helps -
This might seem a bit on the nose, but you can use the merge() method of the BitmapData class to merge two bitmaps images into one. There's an example using the merge() method at those links.
As far as saving to a local disk goes, Flash Player allows access to the file system using the FileReference class. The FileReference class has the save() method, which prompts the user to browse for a location on their file system.
For Air applications, you can access the file system by using the classes in the flash.filesystem package.

Access a function inside a loaded .swf file?

Is there a way to call a function inside a loaded SWF file?
Basically, I have a .swf file (A) that loads another .swf file (B)...I would just like to treat B as if it was any other instance added to my class .swf "A"...
Have to recast "Loader" with the name of your .swf file class:
Loaded .swf class:
package src {
import flash.display.MovieClip;
public class LoadedSWF extends MovieClip {
public function LoadedSWF() {
}
public function helloWorld():void
{
trace("hello world from loaded swf!");
}
}
}
Main class:
package src {
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip {
private var loader:Loader;
public function Main() {
loadSWF("LoadedSWF.swf")
}
private function loadSWF(url:String):void {
var urlRequest:URLRequest = new URLRequest(url);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded, false, 0, true);
loader.load(urlRequest);
addChild(loader);
}
private function onLoaded(e:Event):void {
var target:LoadedSWF = e.currentTarget.loader.content as LoadedSWF;
trace(target);
target.helloWorld();
addChild(target);
}
}
}
There are two cases i.e
Child swf(B) calls function of Parent swf(A) or
Parent swf(A) calls function of loaded swf(B)
Firstly, in both cases, You must make sure that loaded swf(B) has been loaded and added to Loader swf(A) using Event.COMPLETE. Then communication between two swf is possible. The Loaded swf is just like any other child.
Here is the sample code for case 2
var mLoader:Loader = new Loader();
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.load(new URLRequest("B.swf"));
public function onCompleteHandler(evt:Event)
{
var embedSWF:MovieClip = MovieClip(evt.target.content);
addChild(embedSWF);
embedSWF.function_OF_B();
}
embedSWF.function_OF_B() statement will call the function of child swf B i.e function_OF_B()
In Adobe Flex, you can use the flash.display.Loader class to load another SWF, and add an event listener to it.
This example is taken from the Adobe Documentation:
var url:String = "http://www.helpexamples.com/flash/images/image2.jpg";
var urlRequest:URLRequest = new URLRequest(url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete);
loader.load(urlRequest);
addChild(loader);
function loader_complete(evt:Event):void {
var target_mc:Loader = evt.currentTarget.loader as Loader;
target_mc.x = (stage.stageWidth - target_mc.width) / 2;
target_mc.y = (stage.stageHeight - target_mc.height) / 2;
}
Because contentLoaderInfo is a subclass of EventDispatcher, you can also dispatch events to the loaded SWF.
This is basically like calling a function from the SWF, just a little more complicated.