ActionScript: Setting up ExternalInterface on Linux

I have nearly completed my new portfolio site. I developed the Flash Movie on my Windows machine, but the rest of the development (Joomla, etc) has been done on my Ubuntu box. I’m using ActionScript’s ExternalInterface Class for this project. During integration, I learned that the Javascript code on Linux is a bit different than the code needed for Windows.

The ExternalInterface Class

First I created method in my Document Class that set’s up the ExternalInterface Class:

?View Code ACTIONSCRIPT
private function externalInit():void {
	if (ExternalInterface.available) {
                try {
                    ExternalInterface.addCallback("sendPortfolioType", loadPortfolioType);
                    if (checkJavaScriptReady()) {
                       // trace("JavaScript is ready.\n");
                    } else {
                        trace("JavaScript is not ready, creating timer.\n");
                        var readyTimer:Timer = new Timer(100, 0);
                        readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
                        readyTimer.start();
                    }
                } catch (error:SecurityError) {
                    trace("A SecurityError occurred: " + error.message + "\n");
                } catch (error:Error) {
                    trace("An Error occurred: " + error.message + "\n");
                }
        } else {
                trace("External interface is not available for this container.");
        }
}
 
private function checkJavaScriptReady():Boolean {
        var isReady:Boolean = ExternalInterface.call("isReady");
        return isReady;
}
 
private function timerHandler(event:TimerEvent):void {
        trace("Checking JavaScript status. timerHandler...\n");
        var isReady:Boolean = checkJavaScriptReady();
        if (isReady) {
              //  trace("JavaScript is ready.\n");
                Timer(event.target).stop();
        }
}

This is basically same code as in the Flash IDE Help. The code first checks whether the container (the browser) is able to communicate with a Flash Movie – or rather, does the browser have the capability.

?View Code ACTIONSCRIPT
if (ExternalInterface.available) {
 
}

If so, a callback method is added. This is the method that is called from Javascript.

?View Code ACTIONSCRIPT
 ExternalInterface.addCallback("sendPortfolioType", loadPortfolioType);

The Flash Movie listens for a call to sendPortfolioType. So when Javascript calls “sendPortfolioType“, the Flash Movie will call the method “LoadPortfolioType“.

Next the code checks to see if the document holding the Flash Movie is ready. An ExternalInterface call is made to a Javascript function. In this case the function to be called is simply “isReady“.

?View Code ACTIONSCRIPT
 if (checkJavaScriptReady()) {
 
}
private function checkJavaScriptReady():Boolean {
        var isReady:Boolean = ExternalInterface.call("isReady");
        return isReady;
}

Loading The Flash Movie

I generally use the swfobject to embed my flash movie into an html document.

?View Code JAVASCRIPT
var flashvars = {};
flashvars.gs_url = "assets/portfolio/gsPortfolio.xml";
flashvars.config_url = "assets/portfolio/config.xml";
flashvars.styles_url = "assets/portfolio/gsPortStyles.css";
var params = {};
params.movie = "portfolio";
params.width = "925";
params.height = "280"; 
params.scale = "noScale";
params.allowScriptAccess = "always";
swfobject.embedSWF("assets/portfolio/portfolio.swf", "gsPortfolioCntnr", "925", "280", "9.0.0", "assets/swfobject/expressInstall.swf", flashvars, params);

Note: You must set the allowScriptAccess to always in order for Javascript to be able to talk to the Flash Movie.

In swfObject’s embedSWF method, we are embedding the Flash Movie in the div gsPortfolioCntnr.

<div id="gsPortfolioCntnr"></div>

The div container’s id is important with other OS’s, but needed for Linux. More on this later.

Setting the Javascript functions

I need to code the functions needed for communication between Javascript and the Flash Movie (and vice versa). First I setup two variables that will be used later in the code:

?View Code JAVASCRIPT
var jsReady = false;
var myPort = null;

Next I create the isReady function that is called by the FlashMovie.

?View Code JAVASCRIPT
function isReady() {
	setID("gsPortfolioCntnr");
	return jsReady;
}

Remember, the checkJavaScriptReady method in the Flash Movie calls the isReady function to ensure that document is ready for communication. Within the isReady function, I call a setID, passing it the id of the Flash Movie. This function is needed to enable Javascript to talk to the Flash Movie.

?View Code JAVASCRIPT
function setID(movieName) {
	if (navigator.appName.indexOf("Microsoft") != -1) {
		myPort = window[movieName];
	} else {
		myPort = document.getElementById(movieName);
	}
}

You also have to set jsReady to true.

<body onload="docReady();">
?View Code JAVASCRIPT
function doReady() {
jsReady = true;
}

Now that communication is established, I can send data to the Flash Movie:

?View Code JAVASCRIPT
myPort.sendPortfolioType('logos');

Remember, the Flash Movie is listening for a call to sendPortfolioType.

Linux

If you attempted this setup under Linux, you will receive an error:

?View Code JAVASCRIPT
sendPortfolioType is not a function

Linux is looking for the function in the document, not in the Flash Movie. To make this work in Linux, the first thing I had to do was add a flashvars id. We will also add an attributes object using the same values as the flashvars id.

$(document).ready(function() {
jsReady = true;

var flashvars = {};
flashvars.gs_url = “assets/portfolio/gsPortfolio.xml”;
flashvars.config_url = “assets/portfolio/config.xml”;
flashvars.styles_url = “assets/portfolio/gsPortStyles.css”;
// add an id
flashvars.id = “gpPortfolio”;
var params = {};
params.movie = “portfolio”;
params.width = “925”;
params.height = “280”;
params.scale = “noScale”;
params.allowScriptAccess = “always”;
//set up the attributes
var attributes = {};
attributes.id = “gpPortfolio”;
attributes.name = “gpPortfolio”;
swfobject.embedSWF(“assets/portfolio/portfolio.swf”, “gsPortfolioCntnr”, “925”, “280”, “9.0.0”, “assets/swfobject/expressInstall.swf”, flashvars, params, attributes);
});

I’m using jQuery, so I got rid of the body onload function and wrapped the loading of my Flash Movie in jQuery’s document.ready method.

The next change needed for Linux is changing the id in the isReady function.

?View Code JAVASCRIPT
function isReady() {
	setID("gpPortfolio");
	return jsReady;
}

Instead of passing the id div’s container, you must pass the id of the Flash Movie. Fortunately, this does not appear to be a problem for other OS’s (I have tested this on Windows, but have not yet tested on my mac).

Here’s the code in it’s entirety.

?View Code JAVASCRIPT
var jsReady = false;
var myPort = null;
 
function isReady() {
	setID("gpPortfolio");
	return jsReady;
}
function setID(movieName) {
	if (navigator.appName.indexOf("Microsoft") != -1) {
		myPort = window[movieName];
	} else {
		myPort = document.getElementById(movieName);
	}
	$('#mid_menu a').click(function() {
		var gsType = $(this).attr('id');
		console.log(gsType);
		gsType = gsType.substr(2, gsType.length);
		myPort.sendPortfolioType(gsType);
	});
}
$(document).ready(function() {
	jsReady = true;
 
	var flashvars = {};
	flashvars.gs_url = "assets/portfolio/gsPortfolio.xml";
	flashvars.config_url = "assets/portfolio/config.xml";
	flashvars.styles_url = "assets/portfolio/gsPortStyles.css";
	flashvars.id = "gpPortfolio";
	var params = {};
	params.movie = "portfolio";
	params.width = "925";
	params.height = "280"; 
	params.scale = "noScale";
	params.allowScriptAccess = "always";
	var attributes = {};
	attributes.id = "gpPortfolio";
	attributes.name = "gpPortfolio";
	swfobject.embedSWF("assets/portfolio/portfolio.swf", "gsPortfolioCntnr", "925", "280", "9.0.0", "assets/swfobject/expressInstall.swf", flashvars, params, attributes);
});

Setting up the ExternalInterface Class to work with Linux is not difficult – it took longer for me to find the solution, than to actually code it.

Be Sociable, Share!

Checkout My New Site - T-shirts For Geeks