Better use of SWFAddress deep-linking

Let’s talk SWFAddress. For those unfamiliar, SWFAddress is an open source library using Flash and Ajax to enable URL deep-linking within Flash. Or in less technical terms, it lets you hook a Flash movie into the web browser URL so that you can navigate through Flash using URL addresses (just the way you would if you were browsing an entirely HTML-based site). So, this is a great tool for Flash accessibility!

However, SWFAddress is really only as good as your implementation of it. Quite frankly, a sloppy implementation makes it more of a liability than a benefit. Unlike HTML, Flash doesn’t have a friendly 404 Error message to kindly tell users that there was a problem accessing the URL (or at least, not unless you specifically program the error handling). With Flash, you’ll get whatever ugly mess was left unrendered on stage before ActionScript failed to configure it. Why is this? Well, by nature you need to make SWFAddress a critical component within your master application controller in order for it to do its job. In essence, you need to program your Flash application to be navigable by a set of key values which are going to be incorporated into the URL string. When those values change, your application needs to update to match the new configuration. That said, it’s essential that those key values are handled with the utmost care, caution, and sanctity; otherwise you open the door for having your application fail when values leak in that the controller doesn’t know what to do with. So, I’ve walked onto a few suffering SWFAddress projects now and, in the process of tightening them up to make them bullet-proof, I’ve found some best practices to help avoid pitfalls.

First, what NOT to do:

For your own sanity, DO NOT start placing direct calls to SWFAddress on every button and content portal in your application. In doing so, you’re limiting your ability to validate input and creating lots of opportunity for output errors. If two buttons don’t agree on how to get and set URL values, then one button’s output may clash with another button’s input, which leads to unpredictable results. Caution, consistency, and control are essential factors here.

Instead, here’s what I’d suggest TO do:

  1. Have ONE single adapter class which acts as a proxy between SWFAddress and the entire rest of your application. Never import SWFAddress into anything but that proxy.
  2. Within the proxy class, create getters and setters for all controller values used by your application. Have the rest of your application interface with those getters / setters.
  3. Privately store the source values of the proxy’s getter and setter values as properties of the proxy object. DO NOT directly interface those source values with the SWFAddress URL. Covet and protect those valid source values at all costs!
  4. Create only one method for the proxy to get the SWFAddress URL with, and only one method for the proxy to set the SWFAddress URL with. This creates a funnel: only one object in your application talks to SWFAddress, and that object only has one input and one output with the URL. This funnel will make expansion, modification, and debugging much easier in the long run, given that all URL logic will be centralized in one spot.
  5. When setting the SWFAddress URL, create a single standardized format that organizes and writes all source proxy values out to the URL in a rigid and consistent manner.
  6. When getting the SWFAddress URL, extract the values in an organized fashion that directly counters your setter operation. Then, validate ALL input. Never accept a value into your proxy unless you’re sure that you want it. If you get garbage information, leave your valid source value protected and untouched.
  7. After getting and validating the SWFAddress input, reset the SWFAddress URL with the final, resolved value set. This will replace any garbage that may have shown up in the URL with valid address information.

The goal in these guidelines is to build an armor-plated guard for your application that protects against unknown or unwanted data. This avoids the embarrassment of having your Flash site fail when a visitor makes a typo in the web address. While I advocate using SWFAddress to increase Flash’s accessibility, I also believe that it’s not worth integrating unless you’re prepared to put in the time and effort to implement an iron curtain around it.

5 Responses to “Better use of SWFAddress deep-linking”

  1. Chris Says:

    Interesting post… I just heard about this recently and was intending to look into it, might have to pick your brain on this at some stage :)

  2. mike Says:

    Good post – you are entirely correct on this – I have made a mess of a site using swfaddress flippantly and I am much more careful now.

  3. Cicit Says:

    Hello I think you are right, the samples given by default from SWFAddress is just for simple website. However can I have an example files / class of your best practice using this? I am still using AS2

    Thanks

    • bigmac Says:

      I don’t have any readily available working examples that I can post quickly, so I’ll just type up a quick example of the logic pattern’s flow. This is really quick ActionScript that I wrote in a text editor, so I can’t guarantee that it is syntactically accurate or fully functional. It’s just a demo. Also, my AS2 is a little rusty, so you’ll have to follow the logic flow as AS3.

      package
      {
      	import SWFAddress;
      	import flash.events.EventDispatcher;
      	import flash.events.Event;
      
      	public class SWFAddressProxyDemo extends EventDispatcher
      	{
      		private var _page:String = "main";
      
      		public function SWFAddressProxyDemo():void {
      			super();
      			SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this._onSwfAddressChange);
      		}
      
      		/** set the page value to the URL */
      		private function _externalize():void {
      			SWFAddress.setValue("/" + page +"/");
      		}
      
      		/** get the page value from the URL */
      		private function _internalize():void {
      			var $page:String = page;
      			page = SWFAddress.getValue().split("/").join("");
      
      			// if value has changed while internalizing,
      			// forcibly push out all current valid values.
      			if ($page != page) _externalize();
      		}
      
      		/** page value */
      		public function get page():String {
      			return _page;
      		}
      		public function set page($page:String):void {
      			_page = _validatePage($page);
      			dispatchEvent(new Event(Event.CHANGE));
      		}
      
      		/** validate page */
      		private function _validatePage($page:String):String {
      			// test if the new page value is valid.
      			// if so, return the new value.
      			// otherwise, return the existing (valid) value.
      		}
      
      		/** called each time SWFAddress changes */
      		private function _onSwfAddressChange($event:Event):void {
      			_internalize();
      		}
      	}
      }
      

Leave a Reply