Adobe Flex 3 Help

Accessing JavaScript functions from Flex

You can call JavaScript functions in the enclosing HTML page from your Flex application. By allowing Flex to communicate with the browser, you can change style settings, invoke remote processes, or perform any other action that you can normally do from within the page's scripts.

You can even pass data from the Flex application to the enclosing HTML page, process it, and then pass it back to the Flex application. You do this by using the ExternalInterface API or the navigateToURL() method. For more information, see Using the ExternalInterface API to access JavaScript from Flex and Using the navigateToURL() method in Flex.

Whenever you communicate with the enclosing page, you must determine if the browser can handle the kinds of actions that you want to perform. Therefore, you should first determine if the browser supports the objects that you want to use. For some general guidelines for determining browser support, see Using the ExternalInterface API to access JavaScript from Flex.

Using the ExternalInterface API to access JavaScript from Flex

The easiest way to call JavaScript functions from your Flex application is to use the ExternalInterface API. You can use this API to call any JavaScript method on the wrapper, pass parameters, and get a return value. If the method call fails, Flex returns an exception.

The ExternalInterface API encapsulates checks for browser support, so you are not required to do that when using its methods. However, you can check whether the browser supports the interface by using its available property. For more information, see About the ExternalInterface API.

The ExternalInterface API consists of a single class, flash.external.ExternalInterface. This class has the call() static method that you use to facilitate the JavaScript to Flash communication. You can also call methods in your Flex application from the wrapper by using the ExternalInterface API's addCallback() method. For more information, see About the addCallback() method.

To use the ExternalInterface, you must make the id and name properties in the HTML page callable. For more information, see Editing the Flex application's id and name properties.

Calling JavaScript methods from Flex applications

The ExternalInterface API makes it very simple to call methods in the enclosing wrapper. You use the static call() method, which has the following signature:

flash.external.ExternalInterface.call(function_name:String[, arg1, ...]):Object;

The function_name is the name of the function in the HTML page's JavaScript. The arguments are the arguments that you pass to the JavaScript function. You can pass one or more arguments in the traditional way of separating them with commas, or you can pass an object that is deserialized by the browser. The arguments are optional.

The following example script block calls the JavaScript changeDocumentTitle() function in the enclosing wrapper by using the call() method:

<?xml version="1.0"?>
<!-- wrapper/WrapperCaller.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
     import flash.external.*;
  
     public function callWrapper():void {
        var s:String;
        if (ExternalInterface.available) {
           var wrapperFunction:String = "changeDocumentTitle";
           s = ExternalInterface.call(wrapperFunction,ti1.text);
        } else {
           s = "Wrapper not available";
        }
        trace(s); 
     }
  </mx:Script>
  
  <mx:Form>
     <mx:FormItem label="New Title:">
        <mx:TextInput id="ti1"/>
     </mx:FormItem>
  </mx:Form>
  
  <mx:Button label="Change Document Title" click="callWrapper()"/>
</mx:Application>

On your HTML page, you define a function as you would any other JavaScript function. You can return a value, as the following example shows:

<html><head>
<title>wrapper/WrapperBeingCalled.html</title>
</head>
<body scroll='no'>

<SCRIPT LANGUAGE="JavaScript">
    function changeDocumentTitle(a) {
        window.document.title=a;
        alert(a);
        return "successful";
    }
</SCRIPT>

<h1>Wrapper Being Called</h1>
<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://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab' height='200' width='400'>
                <param name='src' value='WrapperCaller.swf'/>
                <param name='flashVars' value=''/>
                <embed name='mySwf' src='WrapperCaller.swf' pluginspage='http://www.adobe.com/go/getflashplayer' height='100%' width='100%' flashVars=''/>
            </object>
        </td>
    </tr>
</table>
</body></html>

Using the ExternalInterface's call() method requires that the embedded Flex application have a name in the wrapper; you must define an id attribute on the <object> tag and a name attribute on the <embed> tag. Without these, no call to or from your Flex application will succeed.

The call() method accepts zero or more arguments, which can be ActionScript types. Flex serializes the ActionScript types as JavaScript numbers and strings. If you pass an object, you can access the properties of that deserialized object in the JavaScript, as the following example shows:

<?xml version="1.0"?>
<!-- wrapper/DataTypeSender.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import flash.external.*;
  
     public function callWrapper():void {
        var s:String;
        if (ExternalInterface.available) {
           var o:Object = new Object();
           o.fname = "Nick";
           o.lname = "Danger";
           var wrapperFunction:String = "receiveComplexDataTypes";
           s = ExternalInterface.call(wrapperFunction, o);
        } else {
           s = "Wrapper not available";
        }
        trace(s); 
     }
  ]]></mx:Script>
  
  <mx:Button label="Send" click="callWrapper()"/>

</mx:Application>

Flex only serializes public, nonstatic variables and read-write properties of ActionScript objects. You can pass numbers and strings as properties on objects, simple objects such as primitive types and arrays, or arrays of simple objects.

The JavaScript code can then access properties of the object, as the following example shows:

<html><head>
<title>wrapper/DataTypeWrapper.html</title>
</head>
<body scroll='no'>

<SCRIPT LANGUAGE="JavaScript">
    function receiveComplexDataTypes(o) {
        alert("Welcome " + o.fname + " " + o.lname + "!");
        return "successful";
    }
</SCRIPT>

<h1>Data Type Wrapper</h1>

<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://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab' height='200' width='400'>
                <param name='src' value='DataTypeSender.swf'/>
                <param name='flashVars' value=''/>
                <embed name='mySwf' src='DataTypeSender.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>

You can also embed objects within objects, such as an Array within an Object, as the following example shows. Add the following code in your Flex application's <mx:Script> block:

<?xml version="1.0"?>
<!-- wrapper/ComplexDataTypeSender.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import flash.external.*;
  
     public function callWrapper():void {
        var s:String;
        if (ExternalInterface.available) {
           var o:Object = new Object();
           o.fname = "Nick";
           o.lname = "Danger";
           o.b = new Array("DdW","E&T","LotR:TS");
           var wrapperFunction:String = "receiveComplexDataTypes";
           s = ExternalInterface.call(wrapperFunction, o);
        } else {
           s = "Wrapper not available";
        }
        trace(s); 
     }
  ]]></mx:Script>
  
  <mx:Button label="Send" click="callWrapper()"/>

</mx:Application>

The code triggers the JavaScript function in the following wrapper:

<html><head>
<title>wrapper/ComplexDataTypeWrapper.html</title>
</head>
<body scroll='no'>

<SCRIPT LANGUAGE="JavaScript">
    function receiveComplexDataTypes(o) {
        // Get value of fname and lname properties.
        var s = ("Welcome " + o.fname + " " + o.lname + "!\n");
        // Iterate over embedded object's properties.
        for (i=0; i<o.b.length; i++) {
            s +=  o.b[i] + "\n";
        }
        alert(s);
    }
</SCRIPT>

<h1>Complex Data Type Wrapper</h1>

<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://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab' height='200' width='400'>
                <param name='src' value='ComplexDataTypeSender.swf'/>
                <param name='flashVars' value=''/>
                <embed name='mySwf' src='ComplexDataTypeSender.swf' pluginspage='http://www.adobe.com/go/getflashplayer' height='100%' width='100%' flashVars=''/>
            </object>
        </td>
    </tr>
</table>

</body></html>

Flex and Flash Player have strict security in place to prevent cross-site scripting. By default, you cannot call script on an HTML page if the HTML page is not in the same domain as the Flex application. However, you can expand the sources from which scripts can be called. For more information, see About ExternalInterface API security in Flex.

You cannot pass objects or arrays that contain circular references. For example, you cannot pass the following object:

var obj = new Object();
obj.prop = obj; // Circular reference.

Circular references cause infinite loops in both ActionScript and JavaScript.

Using the navigateToURL() method in Flex

The navigateToURL() method loads a document from a specific URL into a window or passes variables to another application at a defined URL. You can use this method to call JavaScript functions in the HTML page that encloses a Flex application.

You should not confuse the functionality of the navigateToURL() method with the load() method of the URLLoader class. The URLLoader class loads a specified URL into an object for manipulation with ActionScript. The navigateToURL() method navigates to the specified URL with a browser.

In most cases, you should use the ExternalInterface API to perform Flex-to-wrapper communication. However, the navigateToURL() method is not part of the ExternalInterface API and, therefore, does not have as stringent a set of requirements for which browsers support it. These requirements are described in About the ExternalInterface API.

The navigateToURL() method is restricted by the security sandbox in which the SWF file is running. Its use relies on the domain-based security restrictions that the allowScriptAccess and allowNetworking parameters define. You set the values of the allowScriptAccess and allowNetworking parameters in the SWF file's wrapper.

For more information on these parameters, see Creating a Wrapper. For more information on security restrictions, see Applying Flex Security.

The navigateToURL() method syntax

The navigateToURL() method is in the flash.net package. It has the following signature:

navigateToURL(request:URLRequest, window:String):void

The request argument is a URLRequest object that specifies the destination. The window argument specifies whether to launch a new browser window or load the new URL into the current window. The following table describes the valid values for the window argument:

Value

Description

_self

Specifies the current frame in the current window.

_blank

Specifies a new window. This new window acts as a pop-up window in the client's browser, so you must be aware that a pop-up blocker could prevent it from loading.

_parent

Specifies the parent of the current frame.

_top

Specifies the top-level frame in the current window.

You pass a URLRequest object to the navigateToURL() method. This object defines the URL target, variables, method (POST or GET), window, and headers for the request. The following example defines a simple URL to navigate to:

<?xml version="1.0"?>
<!-- wrapper/SimplestNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import flash.net.*;
     public function openNewWindow(event:MouseEvent):void {
        var u:URLRequest = new URLRequest("http://www.adobe.com/flex");
        navigateToURL(u,"_blank");
     }
  ]]></mx:Script>
  <mx:Button label="Open New Window" click="openNewWindow(event)"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

The navigateToURL() method URL encodes the value of the url argument.

To send data with a URLRequest object, you can append variables to the request string. The following example launches a new window and passes a search term to the URL:

<?xml version="1.0"?>
<!-- wrapper/SimpleNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import flash.net.*;
     public function executeSearch(event:MouseEvent):void {
        var u:URLRequest = new URLRequest("http://www.google.com/search?hl=en&q=" + ta1.text);
        navigateToURL(u,"_blank");
     }
  ]]></mx:Script>
  <mx:TextArea id="ta1"/>
  <mx:Button label="Search" click="executeSearch(event)"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

In addition to appending strings, you can also use the data property of the URLRequest to add URL variables to a GET or POST request. The query string parameters are of type URLVariables. Flex adds ampersand delimiters for you in the URL request string. The following example adds name=fred to the URLRequest:

<?xml version="1.0"?>
<!-- wrapper/NavigateWithGetMethod.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import flash.net.*;
     public function openNewWindow(event:MouseEvent):void {
        var url:URLRequest = new URLRequest("http://mysite.com/index.jsp");
        var uv:URLVariables = new URLVariables();
        url.method = "GET";
        uv.name = "fred";
        url.data = uv;
        navigateToURL(url,"_blank");
     }
  ]]></mx:Script>
  <mx:Button label="Open New Window" click="openNewWindow(event)"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

To use POST data with the URLRequest object, set the value of the URLRequest object's method property to POST.

Opening multiple windows with the navigateToURL() method

You can open any number of new browser windows with calls to the navigateToURL() method. However, because ActionScript is asynchronous, if you tried a simple loop over the method, Flash Player would only open the browser window for the last call. To avoid this, you use the callLater() method. This method instructs Flash Player to open a new browser window on each new frame in your application. The following example uses the callLater() method to open multiple browser windows with the navigateToURL() method:

<?xml version="1.0"?>
<!-- wrapper/NavigateToMultipleURLs.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="openWindows(0)">
  <mx:Script><![CDATA[
     import flash.net.navigateToURL;
     private var listingData:Array=[
        "http://www.google.com", 
        "http://www.adobe.com", 
        "http://www.usatoday.com"
     ];

     private function openWindows(n: Number):void {
        if (n < listingData.length) {
           navigateToURL(new URLRequest(listingData[n]), '_blank');
           callLater(callLater, [openWindows, [n+1]]);
        }
     }
  ]]></mx:Script>   
</mx:Application>

Calling JavaScript functions with the URLRequest object

You can use the URLRequest to call a JavaScript function by embedding that function in the first parameter of the method, as the following example shows:

public var u:URLRequest = new URLRequest("javascript:window.close()");

The previous code does not work on all browsers. You should include code that detects the browser type, and closes the window based on the type of browser. Also, some browsers, such as Internet Explorer, behave in unexpected ways when you invoke a URLRequest that contains JavaScript. Here are some examples:

  • Executes the JavaScript URLs asynchronously. This means that it is possible to have multiple calls to the navigateToURL() method that is trying to execute JavaScript methods, and have only the last one occur. Each one overwrites the next.
  • Stops all other navigation, such as loading of images and IFRAMEs when you call a JavaScript URL.
  • Displays a security warning dialog box if the URL contains ampersand (&) or question mark (?) characters.

Invoking JavaScript with the navigateToURL() method

You can use the navigateToURL() method to invoke JavaScript functions on the HTML page in which the Flex application runs. However, when passing parameters by using the navigateToURL() method, you must enclose each parameter in quotation marks, as the following example shows:

<?xml version="1.0"?>
<!-- wrapper/CallingJavaScriptWithNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script><![CDATA[
        import flash.net.*;
        public function callWrapper(e:Event):void {
            var eType:String = String(e.type);
            var eName:String = String(e.currentTarget.id);
            var u:URLRequest = new URLRequest("javascript:catchClick('" 
                + eName + "','" + eType + "')");
            navigateToURL(u,"_self");
        }
    ]]></mx:Script>

    <mx:Button id="b1" click="callWrapper(event)" label="Call Wrapper"/>

</mx:Application>

The enclosing HTML wrapper includes the JavaScript to process this call, as the following example shows:

<html><head>
<title>wrapper/NavigateToURLWrapper.html</title>
</head>
<body scroll='no'>

<SCRIPT LANGUAGE="JavaScript">
    function catchClick(name, type) {
        alert(name + " triggered the " + type + " event.");
    }
</SCRIPT>

<h1>Navigate To URL Wrapper</h1>

<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://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab' height='200' width='400'>
                <param name='src' value='CallingJavaScriptWithNavigateToURL.swf'/>
                <param name='flashVars' value=''/>
                <embed name='mySwf' src='CallingJavaScriptWithNavigateToURL.swf' pluginspage='http://www.adobe.com/go/getflashplayer' height='100%' width='100%' flashVars=''/>
            </object>
        </td>
    </tr>
</table>

</body></html>

You can also use the navigateToURL() method with basic JavaScript functions in the URLRequest itself. For example, you can launch the default e-mail client with a single line of code:

<?xml version="1.0"?>
<!-- wrapper/EmailWithNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
     import flash.net.*;
     public function sendMail(e:Event):void {
        var u:URLRequest = new URLRequest("mailto:" + ti1.text);
        navigateToURL(u,"_self");
     }
  </mx:Script>
  <mx:Button id="b1" click="sendMail(event)" label="Send Mail"/>
  <mx:Form>
     <mx:FormItem>
        <mx:Label text="Email Address: "/>
     </mx:FormItem>
     <mx:FormItem>
        <mx:TextInput id="ti1"/>
     </mx:FormItem>
  </mx:Form>
</mx:Application>

The executing SWF file for the previous example is shown below:

Not all browsers support invoking the javascript protocol with the navigateToURL() method. If possible, you should use the call() method of the ExternalInterface API to invoke JavaScript methods in the enclosing HTML page. For more information, see Using the ExternalInterface API to access JavaScript from Flex.