SWFAddress: Extending and Adding to a framework

In my last SWFAddress post, I called for all flash developers big and small to consider using SWFAddress in their upcoming projects. I dont want to just preach afterall, so I created a basic example project.

Since most of the Flash sites I build at visicswire use a small framework of custom components, my approach to incorporating SWFAddress into projects is to register my navigation components with the SWFAddress. I have also tweaked the SWFAddress source code slightly to add a handy method (will explain below).

In my example, I have 2 navigation elements: a main menu and thumb scroller. For the sake of keeping a common method for registering the SWFAddress with these components, I created an Interface class that will be implemented by both my SimpleMenu class and my ThumbContainer class:

interface com.visicswire.interfaces.ISWFAddressable 
{   
    public function enableSWFAddress(addressPrefix:String)
}

If you’re new to interfaces, this file simply defines the public function (with its accepted parameters and return type) that every class that implements this interface must contain. So both my SimpleMenu and ThumbContainer class both have method signatures that look something like this:

public function enableSWFAddress(addressPrefix:String)
{
    //internal functionality for the method goes here....
    //this code can be different from class to class....
}

In both classes, I use this function to as a toggle for the SWFAddress. When this function is called, its sets a flag telling this class to call the SWFAdress.setValue() method when the user make a navigation change. This SWFAdress.setValue() requires a string parameter that will become the hash of your URL. When I call the enableSWFAddress() method, I pass the parameter addressPrefix which will be the prefix of the new hash value sent to the SWFAddress. Each of my navigation classes will append the rest of the desired hash value to the addressPrefix string before passing it onto SWFAdress.setValue().

Example from SimpleMenu:

public function selectItem(clip:MovieClip, bypassSWFAdress:Boolean):Void
{
    if(_selectOption == 'multi' && clip.selected) 
    {
        deselectItem(clip);
    }
    else if(_selectOption == 'singleClick' && !clip.selected)
    {
        clip.selected = true;
        clip.label_txt.setTextFormat(clip.selStyle);

        var evt:Object = {}
            evt.type = 'itemSelected';
            evt.label = clip.label_txt.text;
            evt.target = clip;
            evt.selected = clip.selected;
            evt.obj = clip.data;
            evt.data = clip.data.data

        if(_useSWFAddress && bypassSWFAdress != true && clip.data.useSWFAddress != false && _addrPrefix != "###") 
        {
            SWFAddress.setValue(_addrPrefix + '' + evt.label);
        }

        dispatchEvent(evt);
    }
}

That pretty much takes care of the setting logic for SWFAddress. The next part is writing the logic to handle the URL hash changes. With SWFAddress properly installed in your project’s HTML, the SWFAddress.js file will communicate with your SWF via the ExternalInterface class. Don’t worry about exactly what that means, just know that Flash will be told the URL hash has changed; the SWFAddress class will receive that information and fire its SWFAddress.onChange() method. We just have to override this method and add our own logic to it.

(If you need help setting up your HTML page for SWFAddress, check out the SWFAddress website for guidance, or download my source files and have a look)

I like to override SWFAddress.onChange method in my project’s constructor function. Here is the constructor from my example:

function SWFAddressSite()
{
    var home:SWFAddressSite = this;

    SWFAddress.onChange = function()
    {
        home._handleSWFAddressChange();
    }

    _createMainMenu();
    _createThumbBox();

    _console = new FlashBug(true);
}

Here is the _handleSWFAdressChange() method that contains the getting logic for the SWFAddress in this project:

private function _handleSWFAddressChange()
{
	var path:Array = SWFAddress.getPathArray();
	var selectedMILabel:String = mainMenu.getSelectedItems()[0].label_txt.text.toLowerCase();
	var selectedThumbName:String = 'box ' + thumbBox.getSelectedThumb().label_txt.text.toLowerCase();
	
	//if there are no path elements, the SWF should be in the 'home' state
	if(path.length == 0)
	{
		mainMenu.deselectAll();
		thumbBox.clear();
	}
	
	//if the first path array element (corresponds to the mainMenu item selected)
	//is different than the currently selected mainMenu item, select the desired one
	if(selectedMILabel != path[0]) 
	{
		mainMenu.getMIByLabel(path[0]).onRelease();
	}
	
	//if the second path array element (corresponding to the thumbBox item selected)
	//is different than the currently selected thumbBox item, select the desired one
	//if the second path array element is undefined, that means no thumbBox item should be selected,
	//so reset the thumbBox
	if(selectedThumbName != path[1] && path[1] != undefined) 
	{
		var thumbs:Array = thumbBox.getThumbs()
		for(var el in thumbs)
		{
			var nameString:String = 'box ' + thumbs[el].label_txt.text.toLowerCase();
			_console.log(nameString + ' :: ' + path[1]);
			if(nameString == path[1])
			{
				thumbs[el].onRelease();
				break;
			}
		}
	}
	else if(path[1] == undefined) 
	{
		thumbBox.deselectAll();
		thumbBox.setToBeginning();
	}
}

I am essentially parsing the URL hash that I receive from the SWFAddress and determining what navigation elements to adjust (if any) based on the new URL hash. If you have used the SWFAddress before, you may have noticed I am using a new method SWFAddress.getPathArray(). I added this method to the SWFAddress class to parse the URL hash into an array based on ‘/’ characters in the hash. This is very handy for incorporating restful URLs (or URLs that follow an internal navigation schema).

Here is the method code:

//added a new method to return the appended URL attributes as an array of string w/o '-' marks
public static function getPathArray(splitMe:String):Array
{
	var toSplit:String;
	(splitMe != undefined) ? toSplit = splitMe : toSplit = getPath();
	var pathArray:Array = []
	pathArray = toSplit.split('/');
	
	var i:Number;
	for(var el in pathArray)
	{
		var valueArray:Array = pathArray[el].split('-');
		var valueString:String = "";
		for(i = 0; i<valueArray.length; i++) 
		{
			(i < valueArray.length-1) ? valueString += valueArray[i] + ' ' : valueString += valueArray[i];
		}
		
		pathArray[el] = valueString;
	}
	
	for(i = 0; i<pathArray.length; i++) 
	{
		if(pathArray[el] == "") pathArray.splice(i, 1);
	}
	
	return pathArray;
}

Another little tweak I made to the SWFAddress class: I am auto replacing spaces in any of the hash values with dash characters when I set the new URL hash, and i revert dashes back to spaces when I get the URL hash. This allows you a cleaner way of using spaces in your naviagtion elements without have the URLEncoded %20 appear in the hash.

Well, that just about covers my basic example of how you can use SWFAddress and extend it as a part of your framework when building Flash sites. I hope you find this helpful.

Here are all the source files for this example. They include several additional files (part of my framework, and some other utility files). Here is a link to the example working.

Leave a Reply

Your email address will not be published. Required fields are marked *

*