Using Flex 3 Deep Linking (BrowserManager) With SWFObject
May 28, 2008 – 10:59 am by JoeyFlex 3 has a great deep linking feature built right into the framework. I wasn’t actually expecting that it would even work at all much less work well, but it works extraordinarily well. This blog post isn’t about how to use the deep linking feature since the documentation is pretty good in that regard. You can just search on Google for Flex 3 BrowserManager or look at the Adobe site or the Flex Help documentation for that. Instead, this post is about a topic that I was a little surprised wasn’t blogged elsewhere yet. The issue is how to use the deep linking feature with SWFObject.
Since SWFObject is the defacto standard for embedding Flex and Flash applications I find it odd, though not out of character for Adobe, that BrowserManager relies entirely on a very specific HTML template that ships with Flex. If you’ve ever looked at the Flex HTML templates then you know the code is…how to put this nicely…not what you’d want to put on your site. This is part of the reason SWFObject is the standard. Apart from the fact that SWFObject works really well, it also allows you to write really nice-looking, standards-compliant HTML code. We _always_ use SWFObject. We _never_ use the Flex HTML templates for production. The obvious dilemma then is how can we use the deep linking feature from Flex 3 AND use SWFObject if the deep linking feature is seemingly entirely dependent on a specific Flex HTML template?
Note that for this post I’m only talking about SWFObject 2.0, and none of this is relevant to SWFObject 1.5 or earlier.
The solution to this dilemma is not entirely great, but I think it’s better than having to use the Flex HTML template. I should add that there is a third-party deep linking solution called SWFAddress (www.asual.com/swfaddress) that integrates well with SWFObject without any silly workarounds. However, since deep linking does work quite well with BrowserManager, and BrowserManager is built into the Flex 3 framework, I prefer to use the “official” solution in this case. (And yes, I know that it’s rather silly that I’m quick to throw out the “official” HTML solution but reticent to throw out BrowserManager.) The solution that I’ve found requires modifying the JavaScript file used by BrowserManager slightly. I’ll explain the few changes I made to get it to work.
Note that these details are also outlined in the soon-to-be-published Programming Flex 3
Basically the issue is that history.js, the JavaScript file used by BrowserManager (included in the Flex SDK) has a bit of lousy logic in how it finds the Flash Player instance for the Flex application. If you look at line 103 of the standard history.js file (in Flex Builder you’ll find this in the history subdirectory of the html-templates directory) you’ll see the getPlayer() method. This code assumes that the Flash Player is embedded using an <embed> tag nested in an <object> tag. It also assumes that you have only one .swf embedded in a page, or that you want to use history management/deep linking with the first .swf embedded in a page. These are bad assumptions. Even if you have only one .swf in the page this is still not going to work with SWFObject, which uses standards-compliant nested <object> tags. There are a handful of ways you could theoretically resolve this. The manner I use and that we’re using currently at The Morphic Group is to modify getPlayer() by adding the following code at the beginning of the function.
if(BrowserHistory.flexApplication != null) {
return BrowserHistory.flexApplication;
}
Then we need only to assign the Flex application instance to BrowserHistory.flexApplication from within the HTML page. When using SWFObject this requires using the swfobject.addLoadEvent() method to handle the load event before assigning the value. Then you can call swfobject.getObjectById() to get the reference to the Flex application. The following is an example of the necessary JavaScript code in the HTML page. This registers the object, handles the load event, and assigns the BrowserHistory.flexApplication reference.
swfobject.registerObject("content", "9.0.0", "expressInstall.swf");
swfobject.addLoadEvent(loadEventHandler);
function loadEventHandler() {
BrowserHistory.flexApplication = swfobject.getObjectById("content");
}
Note that we’re assuming in this example that the id of the outer <object> tag is content. Also, you can read more about the SWFObject API at the SWFObject site.
6 Responses to “Using Flex 3 Deep Linking (BrowserManager) With SWFObject”
Great post Joey. I prefer to use SWFObject over the default HTML template in Flex too. I’ve used SWFAddress in the past, but I’ll look to use the Flex 3 solution next time I need that feature.
By Danny Patterson on May 28, 2008
Well, just as soon as I start to feel like I might know a little something, I have to go and read something from Joey Lott… Sigh…. it’s bitter sweet.
Some have the gift (Joey Lott) and some (like me)well….don’t have the gift.
Thanks for the post Joey. :-)
By Kevin on Jun 26, 2008
When you say “Note that we’re assuming in this example that the id of the outer tag is content.”
Do you mean the second param to the .embedSWF method or do you mean the div that holds everything?
So which div from below would equal your content from above? my-wrapper : flashDiv?
By j on Aug 12, 2008
Thanks for the post! I think this was fixed in Flex3.1
By Diego Erdody on Sep 1, 2008
Please increase the line-height on your posts. It is very difficult to read when the lines are so close together.
By Brady White on Sep 23, 2008