Skip to any available Digital Media Help Center chapter of Flex 3 Cookbook:
Chapter 8 | Chapter 20 | Chapter 21

In many cases, you may find it necessary to communicate with the browser that contains your application. Browser communication enables you to build applications that go beyond the Flex application itself; you can link to existing sites, communicate with other applications via JavaScript, and enable interaction with your browser's history, as a start. The ExternalInterface class lets you call out to the browser containing the Flash application, get information about the page, and call JavaScript methods, as well as letting JavaScript methods call into the Flash application. This chapter focuses on the functionality contained within the core Flex Framework, though there are other tools to assist with integration of the browser and the Flash Player—the Adobe Flex Ajax Bridge (FABridge), and Joe Berkovitz's UrlKit among them.

Section 20.1: Link to an External URL

Problem

You need to navigate to a separate URL.

Solution

Use the navigateToURL method to navigate the browser to the new URL.

Discussion

The navigateToURL function enables you to navigate the browser to a new URL in either the same window, a new window, or a specific window frame. This is one of the most common communications with the browser from a Flex application. To invoke the navigateToURL function from within your Flex 3 application, use this approach:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

    <mx:Script>
        <![CDATA[
            import flash.net.navigateToURL;

            private function goToURL() : void
            {
                navigateToURL( new URLRequest( newUrl.text ), target.selectedItem as 
String );
            }
        ]]>
    </mx:Script>

    <mx:TextInput
        id="newUrl"
        top="10" left="10" right="10"
        text="http://www.oreilly.com/" />

    <mx:ComboBox
        id="target"
        top="40" left="10"
        dataProvider="{ [ '_blank', '_self' ] }" />

    <mx:Button
        label="Go"
        left="10" top="70"
        click="goToURL()" />

</mx:Application>

In this example, users can type in any URL and click the Go button to navigate to it. The first parameter of the navigateToURL method is a URLRequest object for the desired URL. The second parameter is the target window where that URL should be displayed. This could be any named window in the browser: _blank for a new window, _self for the current page, _top for the topmost frame container, or _parent for the parent of the current frame container.

Section 20.2: Work with FlashVars

Problem

You need to pass data from your containing HTML page to your Flex 3 application.

Solution

Use FlashVars to add parameters directly into the HTML <embed> tag containing your Flex 3 SWF.

Discussion

You can embed data directly into the HTML that contains your Flex 3 application and easily read that data at runtime by using FlashVars variables. There are two ways to get these values into your Flex application.

You can modify the JavaScript that is used to embed your Flex application in the HTML page, as shown in the following example. Notice the last line in the snippet: It specifies four variables that are used to pass the data into the Flex application through the FlashVars parameter:

AC_FL_RunContent(
    "src", "${swf}",
    "width", "${width}",
    "height", "${height}",
    "align", "middle",
    "id", "${application}",
    "quality", "high",
    "bgcolor", "${bgcolor}",
    "name", "${application}",
    "allowScriptAccess","sameDomain",
    "type", "application/x-shockwave-flash",
    "pluginspage", "http://www.adobe.com/go/getflashplayer",
    "FlashVars", "param1=one&param2=2&param3=3&param4=four"
);

This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.

buy button

You could also modify the <object> and <embed> HTML tags directly if you are not using JavaScript to embed your Flex-compiled SWF file:

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    id="${application}" width="${width}" height="${height}"

    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
    <param name="movie" value="${swf}.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="${bgcolor}" />
    <param name="allowScriptAccess" value="sameDomain" />
    <param name="FlashVars" value="param1=one&param2=2&param3=3&param4=four" />
    <embed src="${swf}.swf" quality="high" bgcolor="${bgcolor}"
        width="${width}" height="${height}" name="${application}" align="middle"
        play="true"
        loop="false"
        quality="high"
        allowScriptAccess="sameDomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.adobe.com/go/getflashplayer"
        FlashVars="param1=one&param2=2&param3=3&param4=four"
    </embed>
</object>

In the Flex application, you can access FlashVars data any time through the object. This ActionScript example shows you how to access each of four FlashVars parameters as strings, as well as display them in a TextArea's text field:

private function onCreationComplete() : void
{
    var parameters : Object = Application.application.parameters;
    var param1 : String = parameters.param1;
    var param2 : int = parseInt( parameters.param2 );
    var param3 : int = parseInt( parameters.param3 );
    var param4 : String = parameters.param4;

    output.text = "param1: " + param1 + "\n" +
                  "param2: " + param2 + "\n" +
                  "param3: " + param3 + "\n" +
                  "param4: " + param4;
}

Section 20.3: Invoke JavaScript Functions from Flex

Problem

You need to invoke JavaScript functions from Flex.

Solution

Use ExternalInterface to invoke JavaScript functions from ActionScript.

Discussion

The ExternalInterface ActionScript class encapsulates everything that you need to communicate with JavaScript at runtime. You simply need to use the method to execute a JavaScript function in the HTML page that contains your Flex application.

To invoke a simple JavaScript function in ActionScript, use the following:

ExternalInterface.call( "simpleJSFunction" );

The basic JavaScript function that would be invoked is shown next. The name of the JavaScript function is passed into the call method as a string value, and a JavaScript Alert window appears above your Flex application:

function simpleJSFunction()
{
    alert("myJavaScriptFunction invoked");
}

You can use this same technique to pass data from ActionScript into JavaScript with function parameters. With a line like this, you can invoke a JavaScript function with parameters passed into it:

ExternalInterface.call( "simpleJSFunctionWithParameters", "myParameter" );

Using this approach, you can pass multiple parameters, complex value objects, or simple parameters from ActionScript into JavaScript.

In JavaScript, you would handle this as you would any other function call that accepts a parameter. When invoked, this function will display the parameter value in a JavaScript alert above your Flex application:

function simpleJSFunctionWithParameters( parameter )
{
    alert( parameter);
}

Often, you may find it necessary to invoke a JavaScript function to return a value from JavaScript to your Flex application. To return a value from JavaScript to your Flex application, use this:

var result:String = ExternalInterface.call( "simpleJSFunctionWithReturn" );

You can see that the corresponding JavaScript function returns a string value, which will be stored in the result string instance within the ActionScript class:

function simpleJSFunctionWithReturn()
{
    return "this is a sample return value: " + Math.random();
}

Section 20.4: Invoke ActionScript Functions from JavaScript

Problem

You need to invoke ActionScript functions from JavaScript in the HTML containing the Flex application.

Solution

Use ExternalInterface to set up callbacks from JavaScript to Flex and invoke ActionScript functions from JavaScript.

Discussion

The ExternalInterface ActionScript class not only encapsulates everything you need to communicate with JavaScript at runtime, but also includes everything that you need to invoke ActionScript functions from JavaScript.

Before you can invoke ActionScript functions from JavaScript, you need to register callbacks for the ActionScript functions that you want to expose to JavaScript. The callbacks are registered through the ExternalInterface class within ActionScript. Callbacks provide a mapping for JavaScript function calls to actual ActionScript functions.

This example shows you how to register callbacks for three ActionScript functions:

private function registerCallbacks() : void
{
    ExternalInterface.addCallback( "function1", callback1 );
    ExternalInterface.addCallback( "function2", callback2 );
    ExternalInterface.addCallback( "function3", callback3 );
}

The corresponding ActionScript functions for these are as follows:

private function callback1() : void
{
    Alert.show( "callback1 executed" );
}

private function callback2( parameter : * ) : void
{
    Alert.show( "callback2 executed: " + parameter.toString() );
}

private function callback3() : Number
{
    return Math.random()
}

Notice that callback1 is a simple ActionScript function that can be invoked. It does not require any parameters and does not return a value. The function callback2 accepts a single parameter, and the function callback3 returns a randomly generated number.

When you want to invoke these functions from JavaScript, you must call a JavaScript function with the callback alias. The following JavaScript code will show you how to invoke these ActionScript functions that have been exposed:

function invokeFlexFunctions()
{
    var swf = "mySwf";
    var container;
    if (navigator.appName.indexOf("Microsoft") >= 0)
    {
        container = document;
    }
    else
    {
        container = window;
    }
    container[swf].function1();
    container[swf].function2( "myParameter" );
    var result = container[swf].function3();
    alert( result );
}

This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.

buy button

The variable swf contains the name of the Flex application, as it has been embedded within the HTML page (in this case, it is mySwf). The first thing that this script does is get a reference to the JavaScript DOM, based on the browser type. After the script has the proper browser DOM, it invokes the Flex functions based on the publicly exposed mappings that are specified when registering callbacks.

The ActionScript function callback1 gets invoked simply by calling the function1 callback on the Flex application instance within the JavaScript DOM, as shown:

container[swf].function1();

After this function is invoked, an alert message shows within the Flex application.

The ActionScript function callback2 gets invoked simply by calling the function2 callback and passing a value into it:

container[swf].function2( "myParameter" );

When invoked, this will display an Alert window within the Flex application that shows the parameter value specified by the JavaScript invocation.

The following example shows you how to return a value from Flex to JavaScript. The function3 callback invokes the callback3 ActionScript function. This function returns a randomly generated number to JavaScript.

When callback3 is invoked, a random number is generated by Flex and returned to JavaScript. This value is then displayed in a JavaScript Alert window. For example:

var result = container[swf].function3();
alert( result );

Section 20.5: Change the HTML Page Title via BrowserManager

Problem

You need to change the HTML page title for your Flex 3 application.

Solution

Use the BrowserManager class instance's setTitle method to change the HTML page title.

Discussion

The BrowserManager class in Flex 3 is used to easily interact with the HTML DOM of the HTML page that contains your Flex application. Among its features is the ability to change the title of the HTML page that contains your application. The following ActionScript code snippet sets the page title for you:

private function changePageTitle( newTitle : String ) : void
{
    //get an instance of the browser manager
    var bm : IBrowserManager = BrowserManager.getInstance();

    //initialize the browser manager
    bm.init();

    //set the page title
    bm.setTitle( newTitle );
}

Section 20.6: Parse the URL via BrowserManager

Problem

You need to read and parse data from the browser's current URL.

Solution

Use the BrowserManager and URLUtil classes to read and parse the current page URL.

Discussion

The following example shows you how to read and parse the current page URL by using the BrowserManager and URLUtil classes, as well as write the parsed results to an instance.

The URLUtil class has functions that will help you parse the different pieces of the current URL. When using deep linking within Flex 3, the URL is broken into two parts: the base and the fragment. The URL base is everything that is to the left of the # sign. The fragment is everything that is to the right of the # sign. The fragment is used to pass values into a Flex application and is also used in history management. A properly constructed fragment can be parsed by the URLUtil.stringToObject method into an ActionScript object that contains the values in the fragment, broken out to string values. Each name-value pair in the URL fragment should be delimited by a semicolon (;).

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    creationComplete="parseURL()">

    <mx:Script>
        <![CDATA[
            import mx.utils.ObjectUtil;
            import mx.managers.IBrowserManager;
            import mx.managers.BrowserManager;
            import mx.utils.URLUtil;

            private function parseURL() : void
            {
                //get an instance of the browser manager
                var bm:IBrowserManager = BrowserManager.getInstance();

                //initialize the browser manager
                bm.init();

                //output the url parameter values
                output.text += "Full URL:\n" + bm.url + "\n\n";
                output.text += "Base URL:\n" + bm.base + "\n\n";
                output.text += "URL Fragment:\n" + bm.fragment + "\n\n";

                //convert url parameters to an actionscript object using URLUtil
                var o:Object = URLUtil.stringToObject(bm.fragment);
                output.text += "Object:\n" + ObjectUtil.toString( o ) + "\n\n";
                output.text += "name:\n" + o.name + "\n\n";
                output.text += "index:\n" + o.index + "\n\n";
                output.text += "productId:\n" + o.productId + "\n\n";

                //parse URL using URLUtil
                output.text += "URL Port:\n" + URLUtil.getPort( bm.url ) + "\n\n";
                output.text += "URL Protocol:\n" + URLUtil.getProtocol( bm.url ) + 
"\n \n";
            output.text += "URL Server:\n" + URLUtil.getServerName( bm.url ) + "\n\n";
                output.text += "URL Server with Port:\n" + 
URLUtil.getServerNameWithPort( bm.url );
            }

        ]]>
    </mx:Script>

    <mx:TextArea id="output" left="10" top="10" bottom="10" right="10"/>

</mx:Application>

If the preceding example had the URL http://localhost:8501/flex3cookbook/main.html#name=Andrew;index=12345;productId=987, the result would be:

Full URL:
http://localhost:8501/flex3cookbook/main.html#name=Andrew;index=12345;productId=987

Base URL:
http://localhost:8501/flex3cookbook/main.html

URL Fragment:
name=Andrew%20Trice;index=12345;productId=987654

Object:
(Object)#0
  index = 12345
  name = "Andrew"
  productId = 987

name:
Andrew

index:
12345

productId:
987

URL Port:
8501

URL Protocol:
http

URL Server:
localhost

URL Server with Port:
localhost:8501

Section 20.7: Deep-Link to Data via BrowserManager

Problem

You need to pass data from the browser's URL into Flex controls, and you need to update the value of the browser URL based on data within your Flex application, which should also work the browser's Forward and Back navigational buttons.

Solution

Use the BrowserManager class and BrowserChangeEvents to read and write data on the browser URL.

Discussion

Whenever the browser URL changes either by text input on the address bar, or through the usage of the navigation controls (Forward and Back buttons), a event is dispatched through the BrowserManager instance. Whenever this type of event is encountered, you simply invoke the updateValues method to update values within the Flex controls. This lets you easily link to, and cycle through, your input values.

The following example shows you how to read data from the browser's URL and put those values into Flex mx:TextInput fields. When the sample application loads, it will read the data from the current URL and write the values of the firstName and lastName parameters into the text boxes. When the value of either the firstName or lastName mx:TextInput field is changed, the application will call the setFragment function on the browser manager, which will update the browser's URL with the new values for the firstName and lastName parameters. This enables you to copy and paste the URL, so that you can easily link directly into the current view, and it also adds every change to the browser history.

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    creationComplete="onCreationComplete()" >

    <mx:Script>
        <![CDATA[
            import mx.events.BrowserChangeEvent;
            import mx.managers.IBrowserManager;
            import mx.managers.BrowserManager;
            import mx.utils.URLUtil;

            private var bm:IBrowserManager

            private function onCreationComplete():void
            {
                //get an instance of the browser manager
                bm = BrowserManager.getInstance();

                //initialize the browser manager
                bm.init();

                //set initial values based on url parameters
                updateValues();

                //add event listeners to handle back/forward browser buttons
                bm.addEventListener( BrowserChangeEvent.BROWSER_URL_CHANGE, 
onURLChange );
            }

            private function updateValues():void
            {
                //update text box values based on url fragment
                var o:Object = URLUtil.stringToObject(bm.fragment);
                firstName.text = o.firstName;
                lastName.text = o.lastName;
            }

            private function updateURL():void
            {
                //update URL fragment
                bm.setFragment( "firstName=" + firstName.text + ";lastName=" + 
lastName.text );
            }

            private function onURLChange( event : BrowserChangeEvent ):void
            {
                //call update values based on change url
                updateValues();
            }
        ]]>
    </mx:Script>

    <mx:TextInput x="10" y="10" id="firstName" change="updateURL()" />
    <mx:TextInput x="10" y="40" id="lastName" change="updateURL()" />

</mx:Application>

This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.

buy button

Section 20.8: Deep-Link Containers via BrowserManager

Problem

You need to control the visible contents of Flex 3 containers based on URL parameters.

Solution

Use the BrowserManager class and BrowserChangeEvents to control the visibility and track the history of the visible Flex components.

Discussion

In this scenario, you use the URL fragment to control and track which containers and components are visible within a Flex application. When the application loads, you initialize the BrowserManager class instance, which helps you parse and handle the browser URL. The updateContainers method (shown in the following code segment) determines which of the tabs within the mx:TabNavigator instance is visible. Any time that tab navigator's visible tab changes, you set the selectedIndex property in the URL fragment by using the following snippet:

bm.setFragment( "selectedIndex=" + tabNav.selectedIndex );

This updates the browser's URL and adds the change to the browser history. If someone were to copy and paste the current browser URL, that user would link directly to the currently selected tab navigator.

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    creationComplete="onCreationComplete()">

    <mx:Script>
        <![CDATA[
            import mx.events.BrowserChangeEvent;
            import mx.managers.IBrowserManager;
            import mx.managers.BrowserManager;
            import mx.utils.URLUtil;

            private var bm:IBrowserManager;

            private function onCreationComplete() : void
            {
                //get an instance of the browser manager
                bm = BrowserManager.getInstance();

                //initialize the browser manager
                bm.init();

                //set visible containers based on url parameters
                updateContainers();

                //add event listeners to handle back/forward browser buttons
                bm.addEventListener( BrowserChangeEvent.BROWSER_URL_CHANGE, 
onURLChange );

                updateURL():
            }

            private function updateContainers():void
            {
                //convert url parameters to an actionscript object
                var o:Object = URLUtil.stringToObject(bm.fragment);

                //set the selected index
                if ( !isNaN(o.selectedIndex) )
                {
                    var newIndex : Number = o.selectedIndex;
                    if ( newIndex >= 0 && newIndex < tabNav.numChildren )
                        tabNav.selectedIndex = newIndex;
                }
            }

            private function onURLChange( event:BrowserChangeEvent ):void
            {
                //call updateContainers when url value changes
                updateContainers();
            }

            private function updateURL():void
            {
                bm.setFragment( "selectedIndex=" + tabNav.selectedIndex );
            }

        ]]>
    </mx:Script>

    <mx:TabNavigator
        bottom="10" top="10" right="10" left="10"
        id="tabNav"
        historyManagementEnabled="false">

        <mx:Canvas label="Tab 0" show="updateURL()" >
            <mx:Label text="Tab 0 Contents" />
        </mx:Canvas>

        <mx:Canvas label="Tab 1" show="updateURL()" >
            <mx:Label text="Tab 1 Contents" />
        </mx:Canvas>

        <mx:Canvas label="Tab 2" show="updateURL()" >
            <mx:Label text="Tab 2 Contents" />
        </mx:Canvas>

    </mx:TabNavigator>
</mx:Application>

You may also notice that the historyManagementEnabled parameter on the is set to false. This is because you are using events from the BrowserManager class to determine whether the browser URL has changed, and to update the tab contents accordingly. Every change to the visible tab ends up with changes to the browser history; users can go back and forward through the visible tabs by using the browser's Back and Forward buttons.

Section 20.9: Implement Custom History Management

Problem

You want actions or changes in your custom components to register with the browser's history and be navigable via the browser's Forward and Back buttons.

Solution

Implement custom history management in your Flex components by implementing the mx.managers.IHistoryManagerClient interface.

Discussion

For this solution to work, history management must be enabled for your Flex project. You can verify that history management is enabled by going to the Flex Project Properties dialog box, selecting the Flex Compiler screen, and verifying that the Enable Integration with Browser check box is selected.

The following code shows you how to implement the IHistoryManagerClient interface for a custom text box component. Any time that a change is made in this component, that change will register with the browser history. Users can go backward and forward through the inputs of this TextInput control by using the browser's Back and Forward buttons.

<mx:TextInput
     xmlns:mx="http://www.adobe.com/2006/mxml"
     text="Change Me!"
     implements="mx.managers.IHistoryManagerClient"
     creationComplete="mx.managers.HistoryManager.register(this);"
     change="textChanged(event)">

     <mx:Script>
         <![CDATA[
            import mx.managers.HistoryManager;

            public function saveState():Object
            {
                return {text:text};
            }

            public function loadState(state:Object):void
            {
                var newState:String = state ? state.text : "";

                if (newState != text)
                {
                    text = unescape( newState );
                }
            }

            private function textChanged(e:Event):void
            {
                HistoryManager.save();
            }
         ]]>
     </mx:Script>

</mx:TextInput>

After the component has been created, you must register that class instance with the history manager. You can see this in the creationComplete event handler for the custom component:

creationComplete="mx.managers.HistoryManager.register(this);"

The IHistoryManagerClient interface requires the saveState and loadState functions to be present within your custom component.

Any time the value of the custom TextInput control is changed, the textChanged method is invoked, which calls the save function on the history manager. When state is saved by the history manager, the saveState method is invoked.


This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.

buy button

The saveState method should return an object that will be persisted in the browser's history. In this case, the method is returning an object with the property text, which is set to the text value of the TextInput component.

When the browser history is changed via the Forward and Back buttons, the loadState method gets invoked. The loadState method reads the text property from the State object that is passed into it. It then sets the text property of the TextInput control based on the value passed in through the State object.

You can add this component to your Flex application by using code similar to the following:

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    xmlns:local="*">

    <local:MyTextInput />

</mx:Application>

Skip to any available Digital Media Help Center chapter of Flex 3 Cookbook:
Chapter 8 | Chapter 20 | Chapter 21