Using SWFAddress with Flex - Search Engine Optimization for Flash

by Todd Perkins

SWFAddress is not only a great deep linking solution with applications created in Flash, it also works incredibly well for deep linking in Flex. It’s an excellent solution because along with easily implementing in an application, you can use SWFAddress to display any state of an application when it initializes. This section demonstrates how to use SWFAddress in a Flex application.

Search Engine Optimization for Flash book cover

This excerpt is from Search Engine Optimization for Flash. Search Engine Optimization for Flash dispels the myth that Flash-based websites won't show up in a web search by demonstrating exactly what you can do to make your site fully searchable -- no matter how much Flash it contains. You'll learn best practices for using HTML, CSS and JavaScript, as well as SWFObject, for building sites with Flash that will stand tall in search rankings.

buy button

Implementing SWFAddress in Flex

You begin with a few small steps when implementing SWFAddress in a Flex app. First, you need to have the right files in the right places. The SWFAddress.as and SWFAddressEvent.as files need to be in the src folder for your application, and the JavaScript folder swfaddress containing swfaddress.js needs to be in your output folder, bin-debug. You can create a Flex project using the SWFAddress folder as your main folder, and by setting App.mxml as your main application file.

After the files are in the appropriate places, you can write the code for your application to implement SWFAddress. Start by making sure your output HTML file links to swfaddress.js using the following code:

<script type="text/javascript" src="swfaddress/swfaddress.js"></script>

Your HTML code should also be using SWFObject, which was discussed earlier in this chapter. Next, you’re ready to write the MXML code. Here’s an example of code that utilizes SWFAddress:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
    <mx:Script>
        <![CDATA[
        import mx.containers.VBox;
        import flash.events.Event;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
        import mx.controls.Text;
        import SWFAddress;

        private var req:URLRequest = new URLRequest("data.xml");
        private var loader:URLLoader = new URLLoader();
        private var xmlData:XML;

        private var urls:Array = new Array();

        private function initApp():void
        {
            loader.addEventListener(Event.COMPLETE,loadComplete);
            loader.load(req);
            SWFAddress.onChange = handleSWFAddress;
        }

        private function loadComplete(event:Event):void
        {
            xmlData = new XML(loader.data);
            for each(var game:XML in xmlData.game)
            {
                var vbox:VBox = new VBox();
                var field:Text = new Text();
                field.text = game.description;
                vbox.label = game.title;
                navigator.addChild(vbox);
                vbox.addChild(field);
                field.width = 375;
                field.height = 100;
                urls.push(formatAsURL(game.title));
            }
        }

        private function handleSWFAddress():void
        {
            var value:String = SWFAddress.getValue();
            value = value.replace(/\//g, "");
            navigator.selectedIndex = urls.indexOf(value);
            SWFAddress.setTitle(formatAsTitle(value));
        }

        private function setSWFAddress():void
        {
           SWFAddress.setValue("/" + urls[navigator.selectedIndex] + "/");
        }

        private function formatAsURL(t:String):String
        {
            var formatted:String = t;
            return formatted.replace(/ /g,"-");
        }

        private function formatAsTitle(t:String):String
        {
            var formatted:String = t;
            return formatted.replace(/-/g," ");
        }
        ]]>
    </mx:Script>
    <mx:TabNavigator id="navigator" width="400" height="150"
change="setSWFAddress()">
    </mx:TabNavigator>

</mx:Application>

Now walk through how this application works. Much of the app is the same application you looked at earlier in this chapter. For example, in the <mx:Application> tag, the creationComplete event is set to trigger initApp(), which initiated the loading of the XML file. Here’s the <mx:Application> tag:

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

And here’s the initApp() function:

private function initApp():void
{

    loader.addEventListener(Event.COMPLETE,loadComplete);
    loader.load(req);
    SWFAddress.onChange = handleSWFAddress;
}

Notice the initApp() function has only one new line of code:

SWFAddress.onChange = handleSWFAddress;

This line of code runs the handleSWFAddress() function whenever the SWFAddressEvent.CHANGE event occurs. This way is a shorthand way of using addEventListener() to connect an event handler function to an event. You’ll look at what handleSWFAddress() does later in this section.

The application has one new variable, urls:

private var urls:Array = new Array();

This variable holds the URL formatted versions of all URLs, as stated in the bottom of the loop at the end of the loadComplete() function:

private function loadComplete(event:Event):void
{
    xmlData = new XML(loader.data);
    for each(var game:XML in xmlData.game)
    {
        var vbox:VBox = new VBox();
        var field:Text = new Text();
        field.text = game.description;
        vbox.label = game.title;
        navigator.addChild(vbox);
        vbox.addChild(field);
        field.width = 375;
        field.height = 100;
        urls.push(formatAsURL(game.title));
    }
}

The URLs are formatted using the formatAsURL() function to format each game title. The returned URL is then stored in the urls array. Here’s the formatAsURL() function:

private function formatAsURL(t:String):String
{
   var formatted:String = t;
    return formatted.replace(/ /g,"-");
}

This function simply holds a duplicate of the string passed in within the formatted variable, and then uses the string’s replace method to replace all spaces with hyphens. The code / /g is a Regular Expression—powerful string referencing code, that identifies all spaces using the global g operator.

Note

For more information about Regular Expressions, see Flex Help.

Address changes for SWFAddress are initiated with the TabNavigator’s change event, which triggers the setSWFAddress() function:

<mx:TabNavigator id="navigator" width="400" height="150" change=
"setSWFAddress()">

Look at the setSWFAddress() function:

private function setSWFAddress():void
{
    SWFAddress.setValue("/" + urls[navigator.selectedIndex] + "/");
}

This function simply calls SWFAddress’ setValue() method to update the address in the browser’s URL. The updated address is the URL formatted game title that corresponds to the selectedIndex of the TabNavigator, wrapped in forward slashes (/). SWFAddress also begins all updates to URLs with a hash character (#).

SWFAddress’ setValue() method triggers the SWFAddressEvent.CHANGE event, which runs the handleSWFAddress() function. Here’s that function:

private function handleSWFAddress():void
{
    var value:String = SWFAddress.getValue();
    value = value.replace(/\//g, "");
    navigator.selectedIndex = urls.indexOf(value);
    SWFAddress.setTitle(formatAsTitle(value));
}

The handleSWFAddress() function begins by capturing SWFAddress’ value—the fragment portion of the URL, using its getValue() method. Then, the forward slashes in the value are stripped using the String.replace() method and a Regular Expression. Next, the TabNavigator’s selectedIndex is set to whatever index corresponds to the current value of SWFAddress, which is retrieved using the urls Array’s indexOf() method. Finally, the title in the browser window is updated using SWFAddresssetTitle() method. The value passed in is the value returned from the formatAsTitle() function.

Let’s look at formatAsTitle():

private function formatAsTitle(t:String):String
{
    var formatted:String = t;
    return formatted.replace(/-/g," ");
}

Where the formatAsURL() function accepts a game title and returns a URL, this function does the opposite. It accepts a game’s URL, and then returns its title.

In order to work properly, the application should be tested using a testing server. When you do test this in a testing server, you see the URLs and page titles update when you click the different tabs (Figure 6.15, “Viewing SWFAddress working in a Flex application”). Further, if you attempt to initialize the application with a URL that contains a fragment, then the application initializes to show its correct state.

Figure 6.15. Viewing SWFAddress working in a Flex application

Viewing SWFAddress working in a Flex application

If you enjoyed this excerpt, buy a copy of Search Engine Optimization for Flash. .