Accessibility
 
Home / Developer Center / Pet Market Application Center

Developer Center Article

Icon or Spacer Icon or Spacer Icon or Spacer
Mike Chambers
 
Mike Chambers
mesh@macromedia.com
 

Sample Header

This article discusses the implementation of back button functionality within the Pet Market application. You can find more information on the Pet Market application, as well as view it and download its source at Pet Market Application Center.

Intuitive navigation
The Pet Market application was designed to allow users to navigate both forward and backward through the application states by using the browser’s Forward and Back buttons. This makes the application more useable as users are able to use navigation techniques that they are familiar with.

 

There are three primary difficulties in implementing this functionality within a Macromedia Flash application:

1
The dynamic nature of many Macromedia Flash applications makes it difficult to recreate the application state when the back or forward buttons are used.
2
The complexity of many Macromedia Flash applications can make it difficult for developers, or the browser to determine where exactly the back / forward buttons should take users.
3
Since access to the back and forward buttons requires that Macromedia Flash integrate closer with the browser than normal, developers have to concern themselves with cross-browser and platform compatibility issues.

The technique used to implemented browser navigation functionality within the Pet Market application takes into account and addresses all of these concerns. It utilizes a technique that uses a combination of JavaScript, hidden frames, and the ActionScript LocalConnection object to integrate the browser’s navigation buttons into the Macromedia Flash application in a manner that works across platforms and browsers.

 

Navigation flow
Before we look at exactly how this technique works, let’s quickly examine how it is presented to the end user. Open up the Pet Market application, and navigate to the Birds section. Notice that the history panel of the application does not contain any items yet. In the Pet Market application, the browser’s navigation buttons are used to navigate through the application states represented by items within the history panel.

Select a couple of bird types to from the Bird section and notice that as you select birds, they are added to the history panel. You can now go through and select other animals and they will also be added to the panel.

 
 

Once a couple of items have been added to the history panel, press the back button in the browser. The Pet Market application responds by moving back through the animals which you have selected. This provides an intuitive navigation scheme that users are familiar with.

 

Execution Flow
So how does that work? If you look at the URL you will notice that it is not changing, and does not contain anchors. Thus it is not using the built in book marking feature of Macromedia Flash MX. Let’s step through what happens when the user navigates to a different section within the Pet Market application.

Here is a quick summary of the execution flow:

1
User changes state of Macromedia Flash application.
2
Hidden frame is called from Macromedia Flash application, and is passed information about the current state of the application.
3
The hidden frame takes the information passed from the Macromedia Flash application, and passes it to a Macromedia Flash movie embedded within the hidden frame.
4
The Macromedia Flash movie communicates this information back to the main Macromedia Flash movie using the LocalConnection object.
5
If the back button is pressed in the browser, the hidden frame goes back to its previous state, and communicates that state to the Macromedia Flash application.
6
The Macromedia Flash application then changes its state based on the data sent from the hidden frame.

First, as we mentioned above, not all events are tracked, only those defined by the developers: Browsing to a product description (also tracked by the "History panel"); returning to the "home" state of the application, or visiting all the "checkout section" of the application. We will call these events "history events". A history event contains all of the information, and data necessary to:

1
Allow the application to determine which state it should be in.
2
Allow the application to recreate itself in that state.

When the user navigates to a new animal description, a history event is generated and stored. This can be tracked through the application’s history panel. Additionally, when the user returns to the "home" state or visits the "checkout" section of the application, browser history events are generated although these events are not represented in the History panel.

 
 

History events within the application are represented in ActionScript by a history event object, which contains the following properties:

 
·
mode = "home" | "browse" | "checkout"
·
pageTitle = a string generated by concatenating the localized displayName for the mode, and category and product labels if applicable
·
catOID = the categoryOID for browsing events only
·
productOID = the productOID for browsing events only
 

This is all of the information and data necessary for the application to recreate the application state at a later time.

When a history event is generated by the user’s actions within a movie, the data from the history event are appended to a query string and attached to a getURL action. The getURL action targets a hidden HTML frame, named "_bottom", within the store.html frameset that contains the main Macromedia Flash movie.

HistoryUI.prototype.registerState = function(mode, productRecord, catLabel_str)
{
   var newTitle =
     HistoryUI.prototype.makeEscapedPageTitle
         (mode, productRecord, catLabel_str);
   if(newTitle != _global.history_mc.registeredTitle && unescape(newTitle) != unescape(_global.history_mc.retrievedStateTitle)){
       if(mode == "browse"){
           this.lastBrowse = new Object();
           this.lastBrowse.productRecord = productRecord;
           this.lastBrowse.catLabel_str = catLabel_str;
       }
       var url = "subswf.html";

       var target = "_bottom";
       _global.history_mc.registeredTitle = newTitle;
       var q_str = "?mode="+mode+"&pageTitle=";
       q_str += newTitle;
       q_str += "&catOID="+productRecord.CATEGORYOID+"productOID="+productRecord.PRODUCTOID;
       if(_global.testMovieMain){
           trace("Register State to Target: "+target+" with: "+url+q_str);
       }
       else{
           getURL(url+q_str, target);
       }
   }
}

 

The source of the HTML for the hidden frame contains JavaScript that parses the data from the query string sent via the getURL action.

<script language="JavaScript">
function parseQuery(q_str)
{
   var pairHalves;
   var queryVars = {};
   var N_V_pairs = q_str.split("&");
   var l = N_V_pairs.length;
   for(i=0; i<l; i++){
       pairHalves = N_V_pairs[i].split("=");
       queryVars[pairHalves[0]] = pairHalves[1];
   }
   return queryVars;
}
var undef;
var q_str = new String(window.location.search);
q_str = q_str.substr(1);
var queryVars = parseQuery (q_str);
if(queryVars.pageTitle != undef){
   document.title = unescape(queryVars.pageTitle);
}
</script>

The parsed data is then passed to a small Macromedia Flash movie, named "subswf.swf", within the hidden frameset. The data is passed through the FlashVars HTML tag, which is dynamically created by JavaScript.

<Script language="JavaScript">
document.write(
      '<OBJECT
      classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
      codebase=
     "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
      WIDTH="300"
      HEIGHT="100"
      id="subswf"
      ALIGN="">');
document.write(
      ' <PARAM NAME=movie VALUE="subswf.swf">
      <PARAM NAME=FlashVars VALUE="' + q_str + '">
      <PARAM NAME=quality VALUE=low>
      <PARAM NAME=bgcolor VALUE=#FFFFFF>');
document.write(
      ' <EMBED src="subswf.swf"
      quality=low bgcolor=#FFFFFF
      WIDTH="300" HEIGHT="100"
      FlashVars="' + q_str + '"
      NAME="subswf"
      ALIGN=""
      TYPE="application/x-shockwave-flash"
      PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
      </EMBED>');
document.write(
   '</OBJECT>');
</SCRIPT>

Here is the code snippet where the data is actually written out and passed to Macromedia Flash:

<PARAM NAME=FlashVars VALUE="' + q_str + '">

When the subswf.swf movie loads, it contains all of the information from the history event object passed from the main Pet Market SWF. It then uses the ActionScript LocalConnection object to pass this event history data back to the main Pet Market Macromedia Flash movie. When the main Macromedia Flash Pet Market movie receives this information, it recreates the state that the information represents. If this is prompted by the user navigating to a new section, the application will already be in the state represented by the history event and thus will not do anything.

//Setup _global.state_obj with data passed in via FlashVars
_global.state_obj = new Object();
_global.state_obj.mode = _root.mode;
_global.state_obj.catOID = _root.catOID;
_global.state_obj.productOID = _root.productOID;
_global.state_obj.pageTitle = _root.pageTitle;
for(prop in _global.state_obj){
   _global.traceIt("propName: "+prop+" = "+_global.state_obj[prop]);
}
//open up the connection to the main Pet Market Flash movie
var main_lc = new LocalConnection();
main_lc.getBottomFrameState = function(){
   return _global.state_obj;
}
//send the data to the Pet Market Flash movie
main_lc.send("main", "gotoState", _global.state_obj);

That in itself does not seem too useful. However, lets review what happened when the user navigated to a section of the Pet Market application. A getURL was called to a hidden frame. This action is treated by the browser as a new page loading, and is thus registered as a browser history event. Since the hidden frame contains all of the data necessary to recreated the state within the Pet Market application, and since pressing the back button on the browser will move the hidden frame to its previous state, with its previous data, pressing the back button on the browser has the effect of changing the state of the main Pet Market application. Since the frame is hidden, this is all seamless to the end user.

One of the main advantages of this technique is that it relies on the browser’s own mechanisms for navigation, and does not rely on complex Macromedia Flash / JavaScript / browser integration. Because of this, it works across virtually all browsers.

Of course, there are a number of ways that this could be improved and expanded. You could use Shared Objects to store the history event data, or pass more complex data types between application states. However, for the Pet Market application, it was only necessary to pass a simply set of data represented by the history event object.

 

Resources
Robert Penner’s Back Button Code

Using FlashVars to pass variables to SwF files

Using the LocalConnection feature in Macromedia Flash MX



About the author
Mike Chambers has been creating applications using primarily Macromedia Flash, Generator and Java for the past three years. He also has experience working with ASP, JSP, PHP and ColdFusion. Recently he has been working with Macromedia Flash and embedded devices, contributing to the “Macromedia Flash Pocket PC Player Authoring Kit.” He is co-author of "Flash Enabled" and “Generator and Flash Demystified."
Mike received his Masters in International Economics and European Studies from the John Hopkins School of Advanced International Studies (SAIS) in 1998.