Calling a Flex function from javascript

Update: I have updated the content of this entry after it was posted. John Dowdell(JD) pointed out some part of post which were confusing. I hope, it is clear now.

This is quite common question in Flash and Flex world. I had created JSFCommunicator library long back to facilitate JavaScript-Flash-JavaScript communication. But JSFC is supported in applications created via Macromedia Flash authoring tool, it is not straight forward to use it in Macromedia Flex applications. JSFC also has some issues in Firefox browser on MacOS. I am going to update it so that it works well on most of the browsers, operating systems and also in Macromedia Flex applications.

In flexcoders list, someone asked how to call a function in Flex app from Javascript, I wrote a simple example to show the technique. Following example is not a very OO approach, but it can easily be made more reusable by wrapping things into classes or creating a component.

JavaScript Code:

//this function return to Flash ActiveX Object or Plugin depending upon browser
//it takes care for browser type and returns the proper reference.
//Accepts the id or name of <OBJECT> or <EMBED> tag respectively
//source taken from: www.moock.org

function thisMovie(movieName) {
// IE and Netscape refer to the movie object differently.
        // This function returns the appropriate syntax depending on the browser.

if (navigator.appName.indexOf ("Microsoft") !=-1) {
return window[movieName];
} else {
return window.document[movieName];
}
}
//success flag, set by flash/flex app
var bFunctionCallFinished = true;
//param delimiter, kind of unique string
var paramDelimiter =  "-->$$###$$##$$<--";
//this function would call a flash/flex function.
function callFlashFunction(functionName, paramsArray)
{
if(bFunctionCallFinished)
{
//Get the reference so activeX or Plugin. flexApp is id/name of OBJECT/EMBED tags
                var flashObject  = thisMovie("flexApp");
bFunctionCallFinished = false;
flashObject.SetVariable("functionName", functionName);
flashObject.SetVariable("functionParams", paramsArray.join(paramDelimiter));
flashObject.SetVariable("commitFunctionCall", true);
}
else
{
//if previous function call is still being run, you can use setTimeOut etc to call it little later...
        }
}

Flex Code(main.mxml):

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" width="600" height="600" backgroundColor="#FFFFFF" >
<mx:Script>
//the name of the function to be called.
var functionName:String;
//the params delimited by paramDelimiter
var functionParams:String;
//param delemiter, kind of unique string
var paramDelimiter =  "-->$$###$$##$$<--";
//setter, which executes the function and send the success flag back to javascript
public function set commitFunctionCall(flag:Boolean):Void
{
var func:Function = this[functionName];
func.apply(this, functionParams.split(paramDelimiter));
getURL("javascript:bFunctionCallFinished=true;void(0)");
}
function sayHi(name:String)
{
alert("Hi " + name);
_ta.text += name + newline;
}
function setNum()
{
var n = arguments.length;
for(var i=0;i<n;i++)
{
_ta.text += arguments[i] + newline;
}
}
</mx:Script>
<mx:TextArea id="_ta" width="200" height="200"/>
</mx:Application>

HTML Code:

<html>
<head>
<script language="Javascript" >
//above JavaScript code goes here
</script>
</head>
<body>
<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,14,0' width='600' height='600'
id='flexApp'
border='1'
>
<param name='flashvars' value=''>
<param name='src' value='main.mxml.swf'>
<embed pluginspage='http://www.macromedia.com/go/getflashplayer' width='600' height='600'
flashvars=''
src='main.mxml.swf'
name='flexApp'
/>
</object>
<input type="button value="Say Hi" onclick="callFlashFunction('sayHi', ['Abdul']);" />
<input type="button value="Set number" onclick="callFlashFunction('setNum', [1,2,3]);" />
</body>

Download the complete file from: http://www.abdulqabiz.com/blog/Flex_JSCommunication2.zip

Hope it’s useful for someone. Stay tuned, for new version JSFC library.
See complete post in flexcoder’s archive:
http://www.mail-archive.com/[email protected]/msg06106.html