18 Aug 2010

Handling External SWF Events in Flex using SWFLoader

6 Comments Examples, Flex/Flash, programing, Uncategorized

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% [?]

Tags: , , ,
written by
I am a designer, developer & dad who interested in educational technology and using media for social goodness.
Related Posts

6 Responses to “Handling External SWF Events in Flex using SWFLoader”

  1. Reply fenderbirds says:

    nice article, keep the posts coming

  2. Reply BigAl says:

    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?

    • Reply Alex Britez says:

      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.

  3. Reply Alex Britez says:

    In the mean time here is some info

    Across the web:
    < mx:SWFLoader
    id="swfLoader"
    trustContent="true"
    />

    < mx:SWFLoader
    id="swfLoader"
    loadForCompatibility="true"
    trustContent="true"
    />

    Same Web domain:
    < mx:SWFLoader
    id="swfLoader"
    loadForCompatibility="true"
    />

    Let me know if any of those combinations work for your scenario.

  4. Reply saglikhaberi says:

    That’s a useful post ;) Thanks.

  5. Reply Martin says:

    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

Leave a Reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes