Can I call a function in a swf from JavaScript?
This question comes in from a client who wanted to know if he could run a function in a swf movie when the browser was closed. This week I'm actually working on JavaScript Flex integration for a project, so I can kill two birds with one stone. This is his actual [edited] question:
The application in question was integrating with Omniture's Flash tracking suite to track video playback. The Omniture server was being pinged for tracking purposes when the user performed various actions. When the browser was shut down they wanted to trigger the "Stopped watching video" event so they would know how much of the video the user watches.
I know this use case rather well, because DotComIt has done a lot of Omniture Flex integration for this client.
The questions, can we do this? And how?
JavaScript can run a function when the browser closes using the "onunload" event of the HTML body tag. If you Google it you can find plenty of examples.
So, from JavaScript how do we execute a Flex function? Adobe has some
So without further adieu, here is the modified Adobe doc example:
<!-- wrapper/AddCallbackExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp()">
<mx:Script><![CDATA[
import flash.external.*;
public function initApp():void {
ExternalInterface.addCallback("myFlexFunction",myFunc);
}
public function myFunc(s:String):void {
l1.text = s;
}
]]></mx:Script>
<mx:Label id="l1"/>
</mx:Application>
This Flex code is not much different than the Adobe doc example. In the Script I added the "" ( although the compiler was compiling w/o those in there). When you type a
Anyway, the point is that there were no problems with the Flex side of things. The problem with the JavaScript side:
<title>wrapper/AddCallbackWrapper.html</title>
</head>
<body scroll='no'>
<SCRIPT LANGUAGE="JavaScript">
function callApp() {
window.document.title = document.getElementById("newTitle").value;
mySwf.myFlexFunction(window.document.title);
}
</SCRIPT>
<h1>AddCallback Wrapper</h1>
<form id="f1">
Enter a new title: <input type="text" size="30" id="newTitle" onchange="callApp()">
</form>
<table width='100%' height='100%' cellspacing='0' cellpadding='0'>
<tr><td valign='top'>
<object id='mySwf' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' height='200' width='400'>
<param name='src' value='JavaScriptFlex.swf'/>
<param name='flashVars' value=''/>
<embed name='mySwf' src='JavaScriptFlex.swf' pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' height='100%' width='100%' flashVars=''/>
</object>
</td></tr>
</table>
</body></html>
The code to drop the swf into the page is fine.
The text input and the onchange is fine. However, when the onChange method is called I get this error in Firebug:
mySwf.myFlexFunction is not a function
Rather frustrating. JavaScript cannot find the Flex Function. Paranoid Ferret had the answer with this JavaScript function:
// depending on the browser. function getFlexApp(appName) {
if (navigator.appName.indexOf ("Microsoft") !=-1) {
return window[appName];
} else {
return document[appName];
}
}
This function is used to get a reference to the swf. And we'll change the callApp function too:
window.document.title = document.getElementById("newTitle").value;
getFlexApp('mySwf').myFlexFunction(window.document.title);
}
And bammo, everything starts working in both IE6 and FireFox 2.
Now, can you call the function in the unload event when the browser closes? Yes you can! The new body tag:
And the new JavaScript block:
// This function returns the appropriate reference, // depending on the browser. function getFlexApp(appName) {
if (navigator.appName.indexOf ("Microsoft") !=-1) {
return window[appName];
} else {
return document[appName];
}
}
function callApp() {
window.document.title = document.getElementById("newTitle").value;
getFlexApp('mySwf').myFlexFunction(window.document.title);
}
function callApp2(){
getFlexApp('mySwf').myFlexFunction('closing');
alert('closing');
}
</SCRIPT>
In the callApp2 function, I added an alert. When you close the browser the alert window pops up. This pauses the browser close so we can actually see that the swf has changed (for a split second).
Could there be timing issues with the swf making a call while the browser is closing? Possibly, it would need more testing with a remote call of some sort. But, the possibilities of this are intriguing for the use case in question (AKA tracking when a user stops watching a video).



