It has been a while since i’ve written about Flex development so I figured i would post up some useful code for anyone interested. Recently I have been dealing with a lot of 3rd party code which relies on a huge amount of external SWF assets which load into Flex using SWFLoader. The issue i ran into is that the developer getting access to <mx:Application /> from external SWF using the MovieClip(root) approach. This approach is a slight change to the old _root of the gloomy AS2 days. This created an extremely tightly coupled app, with mysterious methods scattered around the Flex project. There was no way of knowing who was calling these methods, if they where deprecated, or if it was actually being used by some external SWF. Did I mention that there are 60 SWFs all with code in the timeline. It is like finding a needle in a haystack. Unfortunately for me, I wasn’t aware how tightly coupled these external swfs where and quickly proceeded to break the application whenever I attempted to refactor any code.
Obviously, calling <mx:Application /> to fake the old _root method of communicating with nested SWFs is not exactly the best way to go about this. Instead I favor using and Event driven approach.
This the code to create a simple external SWF with 5 textfields. Each textfield is clickable and will dispatch a custom event which broadcast the value of the textfield.
SWF Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package { import com.events.ExternalSwfEvents; import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; public class SampleSWF extends Sprite { public function SampleSWF() { for(var i:int=0; i<5; i++){ var tf:TextField = new TextField(); tf.autoSize = "left"; tf.text = "Click me from External SWF " + i; tf.y = tf.height * i; tf.selectable = false; tf.addEventListener(MouseEvent.CLICK, handleClick); this.addChild(tf) } } private function handleClick(event:MouseEvent):void { var tf:TextField = event.target as TextField; //Make sure you set bubbles & cancelable to true this.dispatchEvent(new ExternalSwfEvents(ExternalSwfEvents.TEXT_CLICKED, tf.text, true, true)); } } } |
Take notice of the comment that states “Make sure you set bubbles & cancelable to true”. It is necessary to bubble this event because it may be nested several layers deep inside of the SWF.
Custom Event named ExternalSwfEvents.as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.events { import flash.events.Event; public class ExternalSwfEvents extends Event { public static const TEXT_CLICKED:String = "textClicked"; private var value:String; public function ExternalSwfEvents(type:String, value:String, bubbles:Boolean=false, cancelable:Boolean=false) { super(type, bubbles, cancelable); this.value = value; } } } |
So at this moment, the external SWF has no idea that it is an external app, nor does it know who or where the Flex application is. All it knows is that it has some data stored in “value” that it would like to share with the world. If someone decided to listen for it, then they will be able to know what the contents of “value” are. If not then no worries, it’s there if I ever decide I want to know what “value” is.
In my example I am going to load this file in Flex using SWFLoader.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" encoding="utf-8"?> <mx:Application backgroundColor="#FF0000" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import com.events.ExternalSwfEvents; import mx.controls.Alert; private function swfReady(event:Event):void { trace("COMPLETE"); mySWF.content.addEventListener(ExternalSwfEvents.TEXT_CLICKED, handleEvent); } private function handleEvent(event:ExternalSwfEvents):void { Alert.show("You Clicked: " + event.value); } ]]> </mx:Script> <mx:SWFLoader id="mySWF" complete="swfReady(event)" source="assets/SampleSWF.swf" /> </mx:Application> |
Using this approach I know exactly what handleEvent is doing. I also know exactly what it will be receiving and when it will be receiving it. A much nicer and cleaner approach to the
Popularity: 17% [?]
actionscript, AS3, flash, Flex










nice article, keep the posts coming
What about security?
This code works perfectly on my local machine, but when the external swf is loaded from a remote domain, the events are blocked by the flash player. I could not get it to work no matter what.
Any Ideas?
Are both SWF in the same domain? Silly me didn’t test on my web server so you may need to adjust the loaderContext. Once I wrap some stuff up here I will take a look.
In the mean time here is some info
Across the web:
< mx:SWFLoaderid="swfLoader"
trustContent="true"
/>
< mx:SWFLoader
id="swfLoader"
loadForCompatibility="true"
trustContent="true"
/>
Same Web domain:
< mx:SWFLoaderid="swfLoader"
loadForCompatibility="true"
/>
Let me know if any of those combinations work for your scenario.
That’s a useful post
Thanks.
Hey Alex,
thank you very much for the useful Example. I have some some problems placing the as-files in the right folders. Could you tell me in witch folders to put the files within the flex project and how to name the folders correct (I’m working with flex 4.5)?
Thanks al lot
Martin