12 June 2006
Familiarity with JavaScript and the Document Object Model (DOM).
Intermediate
Getting the functionality you want out of your Flash application often requires communicating with code outside of Flash Player, such as JavaScript in an HTML page. In cases like this, you need to get ActionScript to invoke JavaScript, or vice versa, in order to enable communication.
In Flash Player 7 and earlier, ActionScript-to-JavaScript communication relied on getURL() or fscommand(), while JavaScript was able to communicate with ActionScript by using SetVariable(), callFrame(), and callLabel().
The ExternalInterface class introduced in Flash Player 8—more generally known as the External API (application programming interface)—enables straightforward communication between Flash and external programs. This article explains the ExternalInterface class in detail.
Here are the security-related limitations in Flash Player 8 compared to the previous version:
allowScriptAccess parameter is "sameDomain" rather than "always". This does not affect SWFs of Flash Player 7 or earlier. The allowScriptAccess parameter controls whether SWFs may call out to JavaScript in HTML pages.Among these four restrictions, allowScriptAccess is closely related to communicating with JavaScript. You can find more details about these changes in Deneb Meketa's article, Security Changes in Flash Player 8.
The settings for allowScriptAccess are as follows:
allowScriptAccess is "never", outbound scripting always failsallowScriptAccess is "always", outbound scripting always succeedsallowScriptAccess is "sameDomain" (it is supported in SWFs from Flash Player 8), outbound scripting is allowed only if the SWF file resides in the same domain as the hosting web pageallowScriptAccess is not explicitly specified by an HTML page, the default value for the embedded SWF file is set to "sameDomain" in Flash Player 8 and to "always" in earlier versionsJavaScript functions can be called only from the same domain in a web page. However, when you test it locally and from another domain, the SWF file is set to allowScriptAccess = "always".
The following code is generated if you publish to HTML from Flash:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>allowScriptAccess</title>
</head>
<body bgcolor="#ffffff">
<!--url's used in the movie-->
<!--text used in the movie-->
<!-- saved from url=(0013)about:internet -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="550" height="400" id="allowScriptAccess" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="allowScriptAccess.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="allowScriptAccess.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="allowScriptAccess" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
</body>
</html>
You will need to change the code highlighted in the previous listing from allowScriptAccess="sameDomain" to allowScriptAccess = "always".
Note: About letting your local Flash content communicate with the Internet, read Security changes in Flash Player 8.
Earlier versions of Flash Player 8 relied on getURL() and fscommand() to communicate from Flash to JavaScript, and on SetVariable() to communicate from JavaScript to Flash.
The easiest way to call JavaScript from Flash is by using getURL(). To call callJavascript() from Flash, use the following ActionScript:
var msg:String = "''Hello. ^^'";
var callJas:String = 'javascript:callJavascript('+msg+')';
getURL(callJas);
In HTML, type the following JavaScript function between the <head> and <body> tags
<script language="JavaScript">
function callJavascript(str){
alert(str)
}
</script>
In Flash, call the callJavascript() function and send the message string "Hello. ^^" as the parameter. The result appears in Figure 1.
Note: If your SWFs throw security errors when tested locally in Flash Player 8, change allowScriptAccess="sameDomain" to allowScriptAccess="always". In addition, you may need to allow access to the SWF file in the Global Security Settings panel.
The fscommand() command lets the SWF file communicate with either Flash Player or the program that is hosting Flash Player, such as a web browser. For example, the following ActionScript would call the JavaScript function callJavascript():
var msg:String = "'Hello. ^^'";
var callJas:String = "callJavascript";
fscommand(callJas, msg);
Open the Publish Settings dialog box (press Control+Shift+F12) in Flash. On the HTML tab, select Flash with FSCommand in the Template pop-up menu (see Figure 2) and click the Publish button.
If you look at the HTML page that is published, the following JavaScript has been automatically included:
<script language="JavaScript">
<!--
var isInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;
// Handle all the FSCommand messages in a Flash movie.
function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
// Place your code here.
//
}
// Hook for Internet Explorer.
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
document.write('<script language=\"VBScript\"\>\n');
document.write('On Error Resume Next\n');
document.write('Sub fscommand_FSCommand(ByVal command, ByVal args)\n');
document.write(' Call fscommand_DoFSCommand(command, args)\n');
document.write('End Sub\n');
document.write('</script\>\n');
}
//-->
</script>
Your custom code goes in the section "Place your code here." Specifically, this code needs to receive and process the command and args parameters sent from Flash using fscommand().
For example, the following code creates an alert window by handling command and args:
function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
if(command=="callJavascript") {
alert(args)
}
//
}
Because fscommand() uses VBScript under the hood to communicate, it may cause conflicts with other VBScript on the page. Also, because fscommand() passes only one args string parameter, you must use the split() function in JavaScript to pass two or more parameters.
The following code is an example of using fscommand() to pass two arguments. In Flash, type the following code:
var msg:String = "'Hello. ^^'#Glad to see you.*^^*";
var callJas:String = "callJavascript";
fscommand(callJas, msg);
Here, # serves as a separator between the arguments you want to pass. The JavaScript code is as follows:
function fscommand2_DoFSCommand(command, args) {
var fscommand2Obj = isInternetExplorer ? document.all.fscommand2 : document.fscommand2;
//
if(command=="callJavascript") {
arg = args.split("#")
alert(arg[0]+'\n'+arg[1])
}
//
}
In the code above, I separated the string on the # separator and used \n to wrap text onto a new line in the alert window. The result appears in Figure 3.
Note: As in the previous examples, to prevent security errors from being thrown in Flash Player 8 when you test locally, change allowScriptAccess="sameDomain" to allowScriptAccess="always".
The only way to communicate with Flash in JavaScript is by using one of a few predefined methods. SetVariable() is one of the most common methods to use. It can send string values from JavaScript to a SWF that is embedded on the page. Then, in ActionScript, you can use the watch() method to invoke a callback function whenever new values are passed in. Let's look at an example.
Type the following code in Flash:
// An empty string variable
var testValue:String = "";
// The callback function to be executed when the variable changes
watchCallback = function (id, oldval, newval):String {
// Here you place the new value in a text field for display
result_txt.text = newval;
return newval;
};
_root.watch("testValue", watchCallback);
The above code invokes watchCallback() whenever the testValue value changes. When watchCallback() is invoked, the new value is assigned to result_txt.text on _root.
Insert the following code in the HTML <body> section:
<input type=button value="Pass the variable to Flash" onClick="callJavascript()">
<form name="inputValue">
Value <input type="text" name="vars" size="10" >
</form>
The value entered in the input text in HTML is saved in the vars property of the form inputValue. Clicking the "Pass the variable to Flash" button invokes the callJavascript() function.
The following is the JavaScript code:
<script language="JavaScript">
function callJavascript(){
var sendText = inputValue.vars.value
window.document.myMovie.SetVariable("testValue", sendText);
}
</script>
In the code above, window.document.FlashID gives you a reference to your Flash object (which I haven't shown here). You then call SetVariable(variable, value) on the reference to pass the value of sendText in a variable named testValue:
window.document.setVariable.SetVariable("testValue", sendText);
The ExternalInterface class introduced in Flash Player 8 enables straightforward communication between ActionScript and the Flash Player container—for example, an HTML page with JavaScript or even a desktop application with Flash Player embedded.
ExternalInterface is similar in functionality to the fscommand(), CallFrame(), and CallLabel() methods but is more flexible and more generally applicable. ExternalInterface is the preferred method for JavaScript–ActionScript communication in Flash Player 8 and later.
From ActionScript you can directly call any JavaScript function on the HTML page, passing any number of arguments of any data type, and receive a return value from the call. Similarly, from JavaScript on the HTML page you can call an ActionScript function in Flash Player and get a return value. Table 1 lists the browser and operating system combinations supported by ExternalInterface.
| Browser | Operating Systems | |
|---|---|---|
| Internet Explorer 5.0 and higher | Windows | |
| Netscape 8.0 and higher | Windows | Mac OS |
| Mozilla 1.7.5 and higher | Windows | Mac OS |
| Firefox 1.0 and higher | Windows | Mac OS |
| Safari 1.3 and higher | Mac OS | |
ExternalInterface.call() can invoke a JavaScript function and handle a return value. In the past, you had to use one method to invoke a JavaScript function and then a different method to receive a return value. Now you can receive a return value immediately by invoking just one function. So much easier!
The ExternalInterface.call() method uses the following basic format:
ExternalInterface.call(methodName:String, [parameter1:Object])
The parameters have the following meanings:
Type the following code in Flash:
import flash.external.*;
// The name of a JavaScript function to call
var callJasFunction:String = "callJavascript";
//parameter
var msg:String = "Hello. ^^";
// The return value after calling JavaScript
var returnValue:String = ExternalInterface.call(callJasFunction, msg).toString();
return_txt.text = returnValue;
Type the following JavaScript code:
<script language="JavaScript">
function callJavascript(str) {
alert(str)
return "ExternalInterface is a new Flash Player 8 API."
}
</script>
When callJavascript() is invoked, an alert window pops up indicating that the value has been received by your JavaScript function. When you click the OK button, a return value is sent to Flash Player, which receives the return value and displays it in return_txt.text (see Figure 5).
Note: As usual, when testing locally, change allowScriptAccess="sameDomain" to allowScriptAccess="always" in Flash Player 8. Also, to let your local Flash content communicate with the Internet, read this Flash Player TechNote.
The ExternalInterface.addCallback() method registers custom ActionScript methods so that they can be called from JavaScript. Previously, you could call only a limited number of built-in Flash Player functions, but now by using ExternalInterface.addCallback(), you can directly call custom functions that are defined in your SWF. In addition, you can pass any number of parameters of any supported data type.
The ExternalInterface.addCallback() method takes the following basic format:
ExternalInterface.addCallback (methodName:String, instance:Object,method:Function)
The parameters have the following meaning:
this resolves in the method; this object does not necessarily have to be the object on which the method can be found, because you can specify any object (or null)Type the following code in Flash:
import flash.external.*;
// The name of the Flash variable to be called in JavaScript
var flashFunction:String = "callPlayBall";
var instance:Object = null;
// Callback function executed by the name of variable
var realFunction:Function = playBall;
ExternalInterface.addCallback(flashFunction, null, realFunction);
function playBall(tgX:Number, tgY:Number, spd:Number):Void {
moveMC(ball_mc, tgX, tgY, spd);
}
// Decelerating movement
function moveMC(tgMC:MovieClip, tgX:Number, tgY:Number, spd:Number):Void {
var mc:MovieClip = tgMC.createEmptyMovieClip("tp_chProp", 98765);
mc.onEnterFrame = function() {
this._parent._x += spd*(tgX-this._parent._x);
this._parent._y += spd*(tgY-this._parent._y);
var diffX:Number = Math.abs(tgX-this._parent._x);
var diffY:Number = Math.abs(tgY-this._parent._y);
if (diffX<0.5 && diffY<0.5) {
this._parent._x = tgX;
this._parent._y = tgY;
this.removeMovieClip();
}
};
}
Type the following JavaScript code:
<script language="JavaScript">
function callExternalInterface() {
/* Call a function registered as callPlayBall in the SWF named myMovie. */
getMovieName("myMovie").callPlayBall(inputValue.x.value, inputValue.y.value, inputValue.spd.value);
}
/* This utility function resolves the string movieName to a Flash object reference based on browser type. */
function getMovieName(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName]
}
else {
return document[movieName]
}
}
</script>
The following code goes in the HTML <body>:
<!-- Click the button to call "callExternalInterface()".-->
<input type="button" onClick="callExternalInterface()" value="Call Flash Function" />
</form>
<!-- Save the values of x, y and spd variables for each input text in inputValue.-->
<form name="inputValue">
Positon X <input type="text" name="x" size="10" >
Position Y <input type="text" name="y" size="10" >
Speed <input type="text" name="spd" size="10" >
</form>
Figure 6 shows what happens when you move the ball by sending the values for x, y, and the speed from HTML to Flash.
Note: When you test locally, of course, change allowScriptAccess="sameDomain" to allowScriptAccess="always" in Flash Player 8. Also, to let your local Flash content communicate with the Internet, read this Flash Player TechNote.
For more information about the topics mentioned in this article, please visit the following resources:
| 04/23/2012 | Auto-Save and Auto-Recovery |
|---|---|
| 04/23/2012 | Open hyperlinks in new window/tab/pop-up ? |
| 04/21/2012 | PNG transparencies glitched |
| 04/01/2010 | Workaround for JSFL shape selection bug? |
| 02/13/2012 | Randomize an array |
|---|---|
| 02/11/2012 | How to create a Facebook fan page with Flash |
| 02/08/2012 | Digital Clock |
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |