Archive for the ‘javascript’ Category

Using the StateManager in AJAX Apps

Monday, November 6th, 2006

Due to the success (and quality) of Asual's SWFAddress, I've decided to stop work on this project. SWFAddress is now capable of all the things that StateManager is, so it doesn't seem very beneficial to the open source community to continue development on StateManager. The source code and examples will remain available but no longer be updated, but keep checking xa for other open source code!

Within days after posting the above message, Rostislav Hristov (the creator of SWFAddress) sent me a very flattering email asking me to join the SWFAddress team. While I probably won't be able to contribute too much time to the project, Rostislav has informed me that he has incorporated my Safari findings into the SWFAddress code base.

After some input from Geoff Stearns, I decided to tweak the JavaScript file that powers the ActionScript StateManager class so that it can also be used to manage your AJAX states. If you've read the article that introduced the StateManager, you should be more than comfortable using it in an AJAX environment. The StateManager source and example files zip file includes two AJAX examples: the first shows how to create an AJAX application that utilizes state management, and the second shows how to implement state management into an already-existing project. However, since the usage is nearly identical to the ActionScript StateManager, I'll just give a brief walkthrough here. (In fact, the only real difference is how the event handlers are defined.)

Download the StateManager source and examples as a zip file or from my as3 subversion repository for all you need to start managing states in both your Flash and AJAX web applications or check out the AJAX StateManager in action.

Step 1: Import the Script

This time, all you need is in the file "statemanager.js". This is the exact same JavaScript file that the AS2 StateManager uses, so don't worry about getting them mixed up or anything. Add it to your html file with a <script> tag:

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

You may also want to make a reference to the "class", so you don't have to keep typing the namespace out:

var StateManager = EXANIMO.managers.StateManager;

Step 2: Initializing the StateManager

Once the DOM is ready to be written to, you'll need to initialize the StateManager. In other words, call the initialize method in the window's onLoad handler:

window.onload = function()
{
    StateManager.initialize();
}

Since the StateManager uses an iframe to keep track of states in Internet Explorer, it's important that you not call initialize until the DOM can be written to.

In previous versions of the StateManager, the class would initialize itself as soon as the body tag was present. However, in large HTML files, the body tag is sometimes present before it becomes writable. Though the new version requires the user to manually initialize the StateManager, it avoids this problem without making assumptions about the user's load handling.

Step 3: Setting a State

Set a state by passing the ID of the state you'd like to set to the setState function. The following illustrates how to set the state "about" when the user clicks on the hyperlink with id "about-link".

window.onload = function()
{
    StateManager.initialize();

    document.getElementById('about-link').onclick = function()
    {
        StateManager.setState('about');
        return false;
    }
}

As in the ActionScript version of the StateManager, there is one special state: the default state of your application. This state is represented by an empty hash in the browser's address bar. The ID of the default state is stored in the property StateManager.defaultStateID. So, if you want a button to return your application to the default state (as we do in "ajax-1.fla", you would use the following code:

window.onload = function()
{
    StateManager.initialize();

    document.getElementById('home-link').onclick = function()
    {
        StateManager.setState(StateManager.defaultStateID);
        return false;
    }

    document.getElementById('about-link').onclick = function()
    {
        StateManager.setState('about');
        return false;
    }
}

In previous versions of the StateManager, the ID of the default state was always "home". In the new version, it defaults to "defaultState", but you can chose anything you want. To change it, simply set the defaultStateID property before you initialize the StateManager. But remember — the ID you chose will never show up in the URL; the default state is always represented with an empty hash value.

Step 4: Reacting to a State Change

By setting the StateManager's stateChange handler, we can determine how our application will react to a change of state. The handler recieves an object with an id property that holds the ID of the new state. In the code below, the contents of a heading tag are updated to reflect our state. We can also update the browser's title bar with the StateManager.setTitle function.

StateManager.onstatechange = function(e)
{
    document.getElementsByTagName('h1')[0].innerHTML =
        'The id of the current state is: ' + e.id;
    StateManager.setTitle('My Website :: ' + e.id);
}

Users familiar with prior versions of the StateManager should note that its event handler names have been changed to reflect JavaScript conventions. The "stateChangeHandler", "stateSetHandler", and "stateRevisitedHandler" functions have been renamed to "onstatechange", "onstateset", and "onstaterevisit", respectively.

Deja Vu?

That's it! Hopefully you're well on your way to managing states in both AJAX and Flash applications. If you have any ideas for making things simpler and more intuitive, leave a comment! And be sure to check out the ajax-2 folder in the StateManager source and example files to see how the StateManager can be integrated into already-existing projects.