Version 57, last updated by judah at October 30, 2009 21:11 UTC
Using the Link Manager
UPDATE: As of August 6th, 2009. Numerous sub-system are being refactored. It is advisable to not use this in a production environment and it may not compile at this point. When the upgrades are complete a notice will be posted here, demos and an example project will be made available for download. These changes will facilate a much stronger foundation for a wider variety of projects and more flexible control on your current projects. So you 3 people using this stay tuned and send me any feedback and questions you have.
The Link Manager class is the key component of the Flex Capacitor library beta. Note: The 'not writing code' part is not there yet. Eventually tools like plug in panels will write the code. This is very much a work in progress. More description...
Create a New Flex Project
Add the Flex Capacitor Library to your project either through the Project > Properties > Flex Build Paths
or dropping the swc into the libs folder as described here. Don't forget to include the index template file and scripts as described in the setup instructions.
Add the following code:
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="Name of Site" debug="true" >
</managers:LinkManager>
Let's also add the mouse wheel and context manager classes at this point as well. The MouseWheelManager adds mouse wheel support for mac browsers. The Context Menu manager adds support for context menu's on the Application, link components and images. Note: The Context Menu Manager is imported by the Link Manager instance but adding the class here allows us to set and modify it's behavior.
<!-- MOUSE WHEEL MANAGER -->
<managers:MouseWheelManager />
<!-- CONTEXT MENU MANAGER -->
<managers:ContextMenuManager />
We are also going to add the CompilationDate class. This allows us to know when the application was compiled and display that date, time and local version in our application. We use this so we can see if we are viewing a cached swf when we view it in the browser. It will show us the compile time of the swf.
<!-- COMPILE DATE -->
<utils:CompilationDate id="date1" />
Now we are going to add in the layout. The following code is in the base layout. We will use states to inherit this layout and define any changes. The base state will include the appilcation title, several text links and the footer text. It will serve as a sort of template.
Note: Although the Flex Capacitor classes are included already in the example code be sure to import the classes as needed. Place your cursor after, "controls:TextLink" and press ctrl+space or cmd+space and Flex Builder will import the class.
<!-- LAYOUT AND DESIGN -->
<controls:TextLink text="SITE NAME" x="10" y="10" fontSize="28"/>
<mx:HBox x="10" y="48">
<controls:TextLink text="PAGE 1"/>
<controls:TextLink text="PAGE 2"/>
<controls:TextLink text="PAGE 3"/>
<controls:TextLink text="PAGE 4"/>
<controls:TextLink text="PAGE 5"/>
</mx:HBox>
<mx:Text x="10" y="309" text="COPYRIGHT 2010 SITE NAME"/>
So far if we look at our code it looks like this:
stage_01.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
backgroundColor="#ffffff"
backgroundGradientAlphas="{[1,1]}"
backgroundGradientColors="{[0xffffff,0xffffff]}"
color="#333333"
creationPolicy="all"
horizontalScrollPolicy="off"
xmlns:controls="com.flexcapacitor.controls.*"
xmlns:local="components.*"
xmlns:managers="com.flexcapacitor.managers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:behaviors="com.flexcapacitor.behaviors.*"
xmlns:utils="com.flexcapacitor.utils.*"
layout="absolute"
name="number9">
<!-- COMPILE DATE -->
<utils:CompilationDate id="date1" />
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="SITE NAME" debug="true" >
</managers:LinkManager>
<!-- MOUSE WHEEL MANAGER -->
<managers:MouseWheelManager />
<!-- CONTEXT MENU MANAGER -->
<managers:ContextMenuManager />
<!-- LAYOUT AND DESIGN -->
<controls:TextLink text="SITE NAME" x="10" y="10" fontSize="28"/>
<mx:HBox x="10" y="48">
<controls:TextLink text="PAGE 1"/>
<controls:TextLink text="PAGE 2"/>
<controls:TextLink text="PAGE 3"/>
<controls:TextLink text="PAGE 4"/>
<controls:TextLink text="PAGE 5"/>
</mx:HBox>
<mx:Text id="footer1" x="10" y="311" text="© {date1.currentYear} Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved." height="22"/>
</mx:Application>

As you've noticed we've put the text links in a HBox. This container automatically lays out each of it's components horizontally and spaces them an equal distance apart.
With the Compile Date class we can get and show the date, time and local version of the compiled SWF. This will let us know if we are viewing the most current version in the browser and not a cached version. Note: the version number tells you which version you are viewing in your browser. It is only applicable to you. The class stores the version number in a cookie and updates it when the compile time of the swf is newer than the compile time saved in the cookie. When in the browser notice the version number and the time before you reload the page. If they stay the same after you reload the page you are looking at the same SWF you were before and the time stamp will show you that. If the version updates or the time stamp changes then obviously you are looking at newer version.
<mx:Text id="footer1" x="10" y="311" text="© {date1.currentYear} Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved." height="22"/>
Now instead of pages like we have in a classical website we are going to add different states to the site that we can navigate to.

Add this code:
<!-- STATES -->
<mx:states>
<mx:State name="news"/>
<mx:State name="blog"/>
<mx:State name="events"/>
<mx:State name="pictures"/>
<mx:State name="contact"/>
</mx:states>
Now we want to add some text to the blog state. Select the blog state if you are in Flex Builder and add a TextAutoSize to it. In the near future we'ill add a source field so we can pull text from an external source. For now we'll fill it with filler text.
<!-- STATES -->
<mx:states>
<mx:State name="news"/>
<mx:State name="blog">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="Text on the Blog page" />
</mx:AddChild>
</mx:State>
<mx:State name="events"/>
<mx:State name="pictures"/>
<mx:State name="contact"/>
</mx:states>
Note: In Flex 4 the syntax for States changed so you'll write the above code a bit different. The same thing would look something like this:
<!-- STATES -->
<mx:states>
<mx:State name="news"/>
<mx:State name="blog"/>
<mx:State name="events"/>
<mx:State name="pictures"/>
<mx:State name="contact"/>
</mx:states>
<controls:TextAutoSize x="10" y="74" text="Text on the Blog page" includeIn="blog"/>
Notice the "includeIn" attribute. This indicates that this component is only included in the "blog" state. The Flex Capacitor classes also use a similar term, "includeInStates" and "excludeFromStates" that basically do the same thing. At the time of this writing Flex 4 is still in development. Another tutorial will made available when it is released.
Anyway, let's make the "Page 1" link go to the blog state. We can do that easily by setting the hyperlink to the state name like so:
<controls:TextLink text="blog" hyperlink="blog"/>
Go ahead and run the example (scroll down to get the complete stage_02.mxml example code). When you click the "blog" link in the browser you move to the "blog" state. Notice the url is updated in the browser to reflect the state you are in. Let's add links and a description to each state:
<!-- LAYOUT AND DESIGN -->
<controls:TextLink text="SITE NAME" x="10" y="10" fontSize="20" hyperlink="news"/>
<mx:HBox x="10" y="48">
<controls:TextLink text="news" hyperlink="news"/>
<controls:TextLink text="blog" hyperlink="blog"/>
<controls:TextLink text="events" hyperlink="events"/>
<controls:TextLink text="pictures" hyperlink="pictures"/>
<controls:TextLink text="contact" hyperlink="contact"/>
</mx:HBox>
<mx:Text id="footer1" x="10" y="311" text="© 2009 Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved."/>
<!-- STATES -->
<mx:states>
<mx:State name="news">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="News" />
</mx:AddChild>
</mx:State>
<mx:State name="blog">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="Blog" />
</mx:AddChild>
</mx:State>
<mx:State name="events">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="Events" />
</mx:AddChild>
</mx:State>
<mx:State name="pictures">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="Pictures" />
</mx:AddChild>
</mx:State>
<mx:State name="contact">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="Contact" />
</mx:AddChild>
</mx:State>
</mx:states>
Try typing the state name in the URL, for example, "/index.html#blog" and then hitting enter. Notice that you are automatically taken to the state you enter.
NOTE: If you enter an incorrect state name currently nothing happens. You can check the debug console and you should see a message (as of update 5.15.2009). In the future an event will be dispatched.
If you enter a state that doesn't exist you can specify a "404 Not Found" state and redirect to it. Let's create this state and specify it in the Link Manager:
<!-- STATES -->
<mx:State name="not_found">
<mx:AddChild position="lastChild">
<controls:TextAutoSize x="10" y="74" text="State not found" />
</mx:AddChild>
</mx:State>
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="Site Name" debug="true"
stateNotFoundState="not_found" >
Now if you enter a state that doesn't exist you are taken to the "Not Found" state where you can display a message to the visitor.
Notice that the footer is not bound to the bottom of the stage. Using the Vertical Spacer component we can dynamically position the component at the bottom of the stage and below specific components.
<controls:VerticalSpacer
debugSpacer="true"
snapToApplicationFooter="true"
snapToApplicationFooterOffset="-12"
targets="{[footer1]}" />
<mx:Text id="footer1" x="10" y="311" text="© 2009 Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved."/>
This will anchor the footer to the bottom of the Application as we resize. We can also position it below the content on each state. Let's assign id's and content to the Text fields:
<controls:VerticalSpacer
debugSpacer="true"
sources="{[blogText1,contactText1,eventsText1,newsText1,picturesText1,stateNotFoundText1]}"
snapToApplicationFooter="true"
snapToApplicationFooterOffset="-14"
targets="{[footer1]}" />
<mx:Text id="footer1" x="10" y="311" text="© 2009 Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved."/>
<!-- STATES -->
<mx:states>
<mx:State name="news">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="newsText1" x="10" y="74" text="News
News
News
News
News
News
News
News
News
News
News
News
News
News
" />
</mx:AddChild>
</mx:State>
<mx:State name="blog">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="blogText1" x="10" y="74" text="Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
Blog
">
</controls:TextAutoSize>
</mx:AddChild>
</mx:State>
<mx:State name="events">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="eventsText1" x="10" y="74" text="Events
Events
Events
Events
Events
" />
</mx:AddChild>
</mx:State>
<mx:State name="pictures">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="picturesText1" x="10" y="74" text="Pictures" />
</mx:AddChild>
</mx:State>
<mx:State name="contact">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="contactText1" x="10" y="74" text="Contact" />
</mx:AddChild>
</mx:State>
<mx:State name="not_found">
<mx:AddChild position="lastChild">
<controls:TextAutoSize id="stateNotFoundText1" x="10" y="74" text="State not found" />
</mx:AddChild>
</mx:State>
</mx:states>
For simplicity we can place the text components inside a canvas and position the footer based on the canvas height. All together we have the following code so far:
stage_02.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
backgroundColor="#ffffff"
backgroundGradientAlphas="{[1,1]}"
backgroundGradientColors="{[0xffffff,0xffffff]}"
color="#333333"
creationPolicy="all"
horizontalScrollPolicy="off"
xmlns:controls="com.flexcapacitor.controls.*"
xmlns:local="components.*"
xmlns:managers="com.flexcapacitor.managers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:behaviors="com.flexcapacitor.behaviors.*"
xmlns:utils="com.flexcapacitor.utils.*"
layout="absolute"
name="number9"
currentState="news">
<!-- COMPILE DATE -->
<utils:CompilationDate id="date1" />
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="MY SITE" debug="true"
stateNotFoundState="not_found" >
</managers:LinkManager>
<!-- MOUSE WHEEL MANAGER -->
<managers:MouseWheelManager />
<!-- CONTEXT MENU MANAGER -->
<managers:ContextMenuManager />
<!-- LAYOUT AND DESIGN -->
<controls:TextLink text="MY SITE" x="10" y="10" fontSize="22" hyperlink="news" id="textlink6" fontWeight="bold"/>
<mx:HBox x="10" y="48">
<controls:TextLink text="news" hyperlink="news" id="textlink1"/>
<controls:TextLink text="blog" hyperlink="blog" id="textlink2"/>
<controls:TextLink text="events" hyperlink="events" id="textlink3"/>
<controls:TextLink text="pictures" hyperlink="pictures" id="textlink4"/>
<controls:TextLink text="contact" hyperlink="contact" id="textlink5"/>
</mx:HBox>
<controls:VerticalSpacer
debugSpacer="false"
sources="{[canvas1]}"
snapToApplicationFooter="true"
snapToApplicationFooterOffset="-14"
targets="{[footer1]}" />
<mx:Text id="footer1" x="10" y="311" text="© {date1.currentYear} Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved." height="22"/>
<mx:Canvas y="75" left="10" right="10" id="canvas1"/>
<!-- STATES -->
<mx:states>
<mx:State name="news">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="newsText1" x="0" y="0" text="News" />
</mx:AddChild>
</mx:State>
<mx:State name="blog">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="blogText1" x="0" y="0" text="Blog" />
</mx:AddChild>
</mx:State>
<mx:State name="events">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="eventsText1" x="0" y="0" text="Events" />
</mx:AddChild>
</mx:State>
<mx:State name="pictures">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="picturesText1" x="0" y="0" text="Pictures" />
</mx:AddChild>
</mx:State>
<mx:State name="contact">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="contactText1" x="0" y="0" text="Contact" />
</mx:AddChild>
</mx:State>
<mx:State name="not_found">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="stateNotFoundText1" x="0" y="0" text="State not found" />
</mx:AddChild>
</mx:State>
</mx:states>
</mx:Application>

Have you noticed yet? What you ask? The Context Menu. Right click on the application. You should see a menu with the following properties:

If you right click on a TextLink you will see this menu:

Note: Not all context menu items work when run from the file system. Viewing from the file system is when you are viewing the page in the browser and the url starts with "file://" rather than "http:". You may need to upload them to a server or run them from a local server. Check out WAMP or MAMP if you need to setup a local host to test your site.
Images and ImageLink components have their own context menu as well. Let's add a ImageLink component to the stage.
<mx:State name="news">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="newsText1" x="0" y="0" text="news" />
</mx:AddChild>
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:ImageLink x="0" y="20" source="http://www.flexcapacitor.com/images/SantaCruz_01.jpg" hyperlink="pictures" width="200" height="300"/>
</mx:AddChild>
</mx:State>
When you right click on the image you will see these options:

When you choose the View Image menu option you are taken into the View Preview screen. The View Image preview displays the image on top of the Application and lets you zoom in and out and save the image to your computer.

Let's also put our components inside a canvas container so we only have one source to follow in our vertical spacer.
Most sites have more information in the URL than just the page or state name. We can easily add more parameters to the url. As we add more parameters the format will automatically change from "http://domain.com/#stateName" to "http://domain.com/#s=stateName;param2=value;". For example, we can include a parameter called, "state" on the URL when we are in the states, blog and pictures.
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="MY SITE" debug="true"
stateNotFoundState="not_found" >
<managers:dynamicParameters>
<managers:ParameterProperty target="{this}" propertyName="currentState" parameterName="state" includeInStates="{['blog','pictures']}"/>
</managers:dynamicParameters>
</managers:LinkManager>
When we go to the blog or picture state we grab the value of, "application.currentState" and append it to the URL. In this case including the application state is redundant since the Link Manager already appends the current state in the URL. We'll remove this code for now.
The Fun Part
In a traditional HTML web page scenario you provide the browser with a url like, "http://mysite.com/mypage.php" and the server sends a response back. Sometimes the URL contains parameters appended to the end of it like so, "http://mysite.com/mypage.php?postID=10&language=en". These parameters can be read and used by the server page to send back different responses to the client.
The LinkManager class works similarly. By setting they hyperlink property we automatically append our own parameters to the url and we can immediately handle them in the application at the same time. Once we apply this principal to our application every part of it can be deep linked with full support for all the context menus you see in todays browsers. Using the behavior model we can even add interactions.
Imagine we have the following URL, "http://www.flexcapacitor.com/mysite.html#s=post;id=1". We can respond to the presense of the id parameter by calling a set of actions as in the following,
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="Site Name" debug="true" stateNotFoundState="not_found" >
<!-- Handlers handle different events from components, state changes or parameter changes -->
<managers:handlers>
<!-- Display an Alert when the id parameter is not blank and we are on the blog state -->
<managers:ParameterHandler id="postsParamaterHandler1"
runAfterStateChange="true" includeInStates="blog" parameter="id" isNotBlank="true">
<managers:actions>
<behaviors:CallMethod target="{Alert}" method="show" arguments="{['id='+postsParamaterHandler1.value]}" />
</managers:actions>
</managers:ParameterHandler>
</managers:handlers>
</managers:LinkManager>
In the previous example we check the presense of the "id" parameter. If the parameter "id" exists and is not blank and we are on the blog state then we display an alert with the parameter value.
We can also handle State changes through behaviors list,
<!-- Handlers handle different events from components, state changes or parameter changes -->
<managers:handlers>
<!-- This loads the posts if we navigate to the blog state and we have not loaded the posts yet -->
<managers:StateHandler runOnEveryClick="true" state="blog" runBeforeStateChange="true">
<managers:actions>
<behaviors:CallMethod target="{Alert}" method="show" arguments="{['State Change']}" />
</managers:actions>
</managers:StateHandler>
</managers:handlers>
In the previous code we display an alert when we enter the "blog" state.
We can also add event handlers via the EventHandler class,
<!-- Handlers handle different events from components, state changes or parameter changes -->
<managers:handlers>
<managers:EventHandler target="{this}" eventName="{StateChangeEvent.CURRENT_STATE_CHANGE}"
callFunction="{Alert.show('STATE CHANGE - via call function event')}">
<managers:actions>
<behaviors:CallMethod target="{Alert}" method="show" arguments="{['STATE CHANGE - via behaviors']}" />
</managers:actions>
</managers:EventHandler>
</managers:handlers>
In the previous code we display an alert when the application state changes.
You don't have to use actions to handle EventHandlers, StateHandlers or ParameterHandlers. You can listen for the "callFunction" event as shown in the code above.
The purpose of using is actions and behaviors is to allow for non-developers to apply interactions to their application. Imagine a graphic designer has just imported his design into Flash Catalyst. When he wants to create an image gallery he drags an image component to the stage and a forward and reverse button. He selects the Image Gallery component and opens the Interactions panel. A list of interactions appears and he applies the, "Flicker Interactions: Retrieve images from friends category". He then selects the Image Gallery component and a button. The interactions panel filters lists all the interactions and behaviors between a button component and an Image Gallery component. He sees the interaction, "Move to next image on click event" and applies that. He does the same with the previous button. When he runs the application a list of images are retrieved from the server. When he clicks the next button the next image is displayed. This whole application is done without writing any code.
The Hyperlink property provides many different conventions. The following are provided:
<controls:TextLink hyperlink="stateName" />
<controls:TextLink hyperlink="stateName#anchorName" />
<controls:TextLink hyperlink="stateName#anchorName?parameter=value;parameter2=value" />
<controls:TextLink hyperlink="stateName?parameter=value;parameter2=value" />
<controls:TextLink hyperlink="s=stateName;a=anchorName;" />
<controls:TextLink hyperlink="s=stateName;a=anchorName;parameter=value;parameter2=value" />
<controls:TextLink hyperlink="#anchorName" />
<controls:TextLink hyperlink="#anchorName?parameter=value;parameter2=value;" />
<controls:TextLink hyperlink="a=anchorName;" />
<controls:TextLink hyperlink="a=anchorName;parameter=value;parameter2=value;" />
<controls:TextLink hyperlink="?parameter=value;parameter2=value" />
<controls:TextLink hyperlink="parameter=value;parameter2=value" />
<controls:TextLink hyperlink="http://domain.com/page.html" />
<controls:TextLink hyperlink="anchor" hyperlinkTarget="_anchor" />
<controls:TextLink hyperlink="file.zip" hyperlinkTarget="_download" />
<controls:TextLink hyperlink="image.jpg" hyperlinkTarget="_media" />
<controls:TextLink hyperlink="page.html" hyperlinkTarget="_browser" />
<controls:TextLink hyperlink="page.html" hyperlinkTarget="_self" />
<controls:TextLink hyperlink="page.html" hyperlinkTarget="_blank" />
<controls:TextLink hyperlink="page.html" hyperlinkTarget="windowName" />
There are numerous target hyperlink keywords that help you handle different kinds of hyperlinks. They are as follows:
STATE_HYPERLINK - defines the hyperlink describes a state in your application
ANCHOR_HYPERLINK - specifies the hyperlink is an anchor
DOWNLOAD_HYPERLINK - specifies the hyperlink is a file and prompts to download dialog. if useBrowserDownloadDialog is true then the hyperlink string is passed to the browser via nagivateToURL
BROWSER_HYPERLINK - passes the hyperlink value to the navigateToURL method
SELF_HYPERLINK - passes the hyperlink and the targetHyperlink values to navigateToURL like so, "navigateToURL(new URLRequest(hyperlink);, hyperlinkTarget);"
BLANK_HYPERLINK - same as SELF_HYPERLINK but opens in a new window
When the hyperlinkTarget has a length greater than 0 - same as SELF_HYPERLINK but opens a named window
You can apply these to the following components or wrap an existing display object in an Anchor container:
TextLink - extends Text component and adds HTML link look and feel styles
ButtonLink - extends Button component
ImageLink - extends Image component
Anchor - extends VBox and provides hyperlink and hyperlink target to it's child components
When you write a hyperlink think about restoring the site from scratch later with nothing but the URL. Obviously you don't need to include the state name in the parameters as this is handled automatically for you. You can also offload parameters to certain states you are in using the LinkManager dynamicParameters array. But you do need to include any other parameters you may need to restore the state later. You are really preparing the link to restore the state later. We do this so your visitors can use the, "Back", "Forward", "Reload", "Bookmark this page", "Open in New Window", "Copy page location" and "Send Link in email" context menu items. You do want your users to have a good experience don't you??? :P User's tend to not like Flash sites because of the lack of these features. The LinkManager and ContextMenuManager alleviate most of these issues if you use it and in future versions more of these features will be added. When we restore the state later we use the LinkManager startupHandlers. These handlers run once when the Application start in the order they're listed.
Startup Handlers Example:
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="Site Name" debug="true"
stateNotFoundState="not_found" defaultFragment="blog">
<!-- Startup handlers run when the application is created -->
<managers:startUpHandlers>
<!-- This loads the posts if the first state we go to is the blog state -->
<managers:StateHandler state="blog" runAfterStateChange="true">
<managers:actions>
<behaviors:CallMethod target="{posts1}" method="send" />
</managers:actions>
</managers:StateHandler>
<!-- Parse the post id and retrieve this specific post -->
<managers:ParameterHandler id="postsParamaterHandler1"
runAfterStateChange="true" includeInStates="post" parameter="id" isNotBlank="true">
<managers:actions>
<!-- Clear out the previous text while new text loads -->
<behaviors:SetProperty target="{postTitle0}" name="text" value="" />
<behaviors:SetProperty target="{postDateCreated0}" name="text" value="" />
<behaviors:SetProperty target="{postDescription0}" name="text" value="" />
<!-- Set the postId to load. We bind to this in the post1 service call -->
<behaviors:SetProperty name="postId" value="{postsParamaterHandler1.value}" />
<!-- Retrieve the requested post -->
<behaviors:CallMethod target="{post1}" method="send" />
</managers:actions>
</managers:ParameterHandler>
</managers:startUpHandlers>
<!-- Handlers handle different events from components, state changes or parameter changes -->
<managers:handlers>
<!-- This loads the posts if we navigate to the blog state and we have not loaded the posts -->
<managers:StateHandler runOnEveryClick="false" state="blog" runBeforeStateChange="true">
<managers:actions>
<behaviors:CallMethod target="{posts1}" method="send" />
</managers:actions>
</managers:StateHandler>
<!-- Parse the post id and retrieve this specific post -->
<managers:ParameterHandler id="postsParamaterHandler2" runOnEveryClick="true"
runBeforeStateChange="true" runAfterStateChange="true" includeInStates="post" parameter="id" isNotBlank="true">
<managers:actions>
<!-- Clear out the previous text while new text loads -->
<behaviors:SetProperty target="{postTitle0}" name="text" value="" />
<behaviors:SetProperty target="{postDateCreated0}" name="text" value="" />
<behaviors:SetProperty target="{postDescription0}" name="text" value="" />
<!-- Set the postId to load. We bind to this in the post1 service call -->
<behaviors:SetProperty name="postId" value="{postsParamaterHandler2.value}" />
<!-- Retrieve the requested post -->
<behaviors:CallMethod target="{post1}" method="send" />
</managers:actions>
</managers:ParameterHandler>
</managers:handlers>
</managers:LinkManager>
Right now you have the startupHandlers and regular handlers. In the previous code it is obvious there is some duplicate handlers.This may be consolidated in the future.
stage_03.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
backgroundColor="#ffffff"
backgroundGradientAlphas="{[1,1]}"
backgroundGradientColors="{[0xffffff,0xffffff]}"
color="#333333"
creationPolicy="all"
horizontalScrollPolicy="off"
xmlns:controls="com.flexcapacitor.controls.*"
xmlns:local="components.*"
xmlns:managers="com.flexcapacitor.managers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:behaviors="com.flexcapacitor.behaviors.*"
xmlns:utils="com.flexcapacitor.utils.*"
layout="absolute"
name="number9"
currentState="news">
<!-- COMPILE DATE -->
<utils:CompilationDate id="date1" />
<!-- LINK MANAGER -->
<managers:LinkManager id="linkManager" projectName="MY SITE" debug="true"
stateNotFoundState="not_found" >
<!-- Startup handlers run when the application is created -->
<managers:startUpHandlers>
<!-- This loads the posts if the first state we go to is the blog state -->
<managers:StateHandler state="blog" runAfterStateChange="true">
<managers:actions>
<behaviors:CallMethod target="{posts1}" method="send" />
</managers:actions>
</managers:StateHandler>
<!-- Parse the post id and retrieve this specific post -->
<managers:ParameterHandler id="postsParamaterHandler1"
runAfterStateChange="true" includeInStates="post" parameter="id" isNotBlank="true">
<managers:actions>
<!-- Clear out the previous text while new text loads -->
<behaviors:SetProperty target="{postTitle0}" name="text" value="" />
<behaviors:SetProperty target="{postDateCreated0}" name="text" value="" />
<behaviors:SetProperty target="{postDescription0}" name="text" value="" />
<!-- Set the postId to load. We bind to this in the post1 service call -->
<behaviors:SetProperty name="postId" value="{postsParamaterHandler1.value}" />
<!-- Retrieve the requested post -->
<behaviors:CallMethod target="{post1}" method="send" />
</managers:actions>
</managers:ParameterHandler>
</managers:startUpHandlers>
<!-- Handlers handle different events from components, state changes or parameter changes -->
<managers:handlers>
<!-- This loads the posts if we navigate to the blog state and we have not loaded the posts -->
<managers:StateHandler runOnEveryClick="false" state="blog" runBeforeStateChange="true">
<managers:actions>
<behaviors:CallMethod target="{posts1}" method="send" />
</managers:actions>
</managers:StateHandler>
<!-- Parse the post id and retrieve this specific post -->
<managers:ParameterHandler id="postsParamaterHandler2" runOnEveryClick="true"
runBeforeStateChange="true" runAfterStateChange="true" includeInStates="post" parameter="id" isNotBlank="true">
<managers:actions>
<!-- Clear out the previous text while new text loads -->
<behaviors:SetProperty target="{postTitle0}" name="text" value="" />
<behaviors:SetProperty target="{postDateCreated0}" name="text" value="" />
<behaviors:SetProperty target="{postDescription0}" name="text" value="" />
<!-- Set the postId to load. We bind to this in the post1 service call -->
<behaviors:SetProperty name="postId" value="{postsParamaterHandler2.value}" />
<!-- Retrieve the requested post -->
<behaviors:CallMethod target="{post1}" method="send" />
</managers:actions>
</managers:ParameterHandler>
</managers:handlers>
</managers:LinkManager>
<!-- MOUSE WHEEL MANAGER -->
<managers:MouseWheelManager />
<!-- CONTEXT MENU MANAGER -->
<managers:ContextMenuManager />
<!-- HTTP SERVICE CALL - for Remote Testing -->
<!-- Retrieve multiple posts -->
<!-- Use posts1.lastResult.posts.post -->
<mx:HTTPService id="posts1" resultFormat="e4x"
url="http://flexcapacitor.com/content/"
result="trace(event.result.posts.post)" showBusyCursor="true">
<mx:request>
<fx>1</fx>
</mx:request>
</mx:HTTPService>
<!-- Retrieve single post -->
<!-- Use post1.lastResult.posts.post -->
<mx:HTTPService id="post1" resultFormat="e4x"
url="http://flexcapacitor.com/content/"
result="trace(event.result.posts.post)" showBusyCursor="true">
<mx:request>
<fx>1</fx>
<p>{postId}</p>
</mx:request>
</mx:HTTPService>
<!-- POST ID - Holds the current post id -->
<mx:String id="postId">1</mx:String>
<!-- LAYOUT AND DESIGN -->
<controls:TextLink text="MY SITE" x="10" y="10" fontSize="22" hyperlink="news" id="textlink6" fontWeight="bold"/>
<mx:HBox x="10" y="48">
<controls:TextLink text="news" hyperlink="news" id="textlink1"/>
<controls:TextLink text="blog" hyperlink="blog" id="textlink2"/>
<controls:TextLink text="events" hyperlink="events" id="textlink3"/>
<controls:TextLink text="pictures" hyperlink="pictures" id="textlink4"/>
<controls:TextLink text="contact" hyperlink="contact" id="textlink5"/>
</mx:HBox>
<controls:VerticalSpacer
debugSpacer="false"
sources="{[canvas1]}"
snapToApplicationFooter="true"
snapToApplicationFooterOffset="-14"
targets="{[footer1]}" />
<mx:Text id="footer1" x="10" y="311" text="© {date1.currentYear} Site Name. Authored {date1.monthName} {date1.dayNumber}, {date1.year} {date1.hour}:{date1.minute} {date1.ampm} v{date1.version}. All Rights Reserved." height="22"/>
<mx:Canvas y="75" left="10" right="10" id="canvas1"/>
<!-- STATES -->
<mx:states>
<mx:State name="news">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="newsText1" x="0" y="0" text="News
News
News
News
News
News
News
News
News
News
News
News
News
News
" />
</mx:AddChild>
</mx:State>
<mx:State name="blog">
<mx:AddChild relativeTo="{canvas1}" position="lastChild" creationPolicy="all">
<mx:VBox id="contentVBox1" width="100%" verticalGap="0">
<mx:Repeater id="postsRepeater" dataProvider="{posts1.lastResult.posts.post}" width="100%" x="0" y="0">
<mx:VBox id="contentVBox2" width="100%" verticalGap="0">
<mx:Canvas id="canvas2" width="100%" >
<controls:TextLink id="postTitle1" height="26" styleName="postTitle" rollOverStyle="postTitleHover" rollOutStyle="postTitle"
text="Post Title"
hyperlink="post?id={postsRepeater.currentItem.@id}"
toolTip="post?id={postsRepeater.currentItem.@id}"
htmlText="{postsRepeater.currentItem.@title}" fontWeight="bold" fontSize="14"/>
<controls:TextAutoSize id="postDateCreated1" y="25" selectable="true" styleName="postDateCreated"
text="Saturday, January 1, 2009"
htmlText="{postsRepeater.currentItem.@dateCreated}" color="#797979"/>
<controls:TextAutoSize id="postDescription1" width="100%" y="52" styleName="postDescription"
text="Description area" cleanWordpressFormatting="true"
htmlText="{postsRepeater.currentItem.content}" />
</mx:Canvas>
<controls:Spacer id="spacer4" height="20" />
</mx:VBox>
</mx:Repeater>
</mx:VBox>
</mx:AddChild>
</mx:State>
<mx:State name="events">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="eventsText1" x="0" y="0" text="Events
Events
Events
Events
Events
" />
</mx:AddChild>
</mx:State>
<mx:State name="pictures">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="picturesText1" x="0" y="0" text="Pictures" />
</mx:AddChild>
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:ImageLink x="0" y="20" source="http://www.flexcapacitor.com/developer/wp-content/uploads/2008/08/67524160rhkibt0022.jpg" height="300" width="200"/>
</mx:AddChild>
</mx:State>
<mx:State name="contact">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="contactText1" x="0" y="0" text="Contact" />
</mx:AddChild>
</mx:State>
<mx:State name="not_found">
<mx:AddChild relativeTo="{canvas1}" position="lastChild">
<controls:TextAutoSize id="stateNotFoundText1" x="0" y="0" text="State not found" />
</mx:AddChild>
</mx:State>
<mx:State name="post">
<mx:AddChild relativeTo="{canvas1}" position="lastChild" creationPolicy="all">
<mx:VBox id="contentVBox0" width="100%" verticalGap="0" creationPolicy="all">
<mx:Canvas id="canvas0" width="100%" creationPolicy="all">
<controls:TextLink id="postTitle0" height="26" styleName="postTitle" rollOverStyle="postTitleHover" rollOutStyle="postTitle"
text="Post Title"
hyperlink="post?postId={post1.lastResult.posts.post.@id}"
htmlText="{post1.lastResult.posts.post.@title}" fontWeight="bold" fontSize="14"/>
<controls:TextAutoSize id="postDateCreated0" y="25" selectable="true" styleName="postDateCreated"
text="Saturday, January 1, 2009"
htmlText="{post1.lastResult.posts.post.@dateCreated}" color="#797979"/>
<controls:TextAutoSize id="postDescription0" width="100%" y="52" styleName="postDescription"
text="Description area" cleanWordpressFormatting="true"
htmlText="{post1.lastResult.posts.post.content}" />
</mx:Canvas>
<controls:Spacer id="spacer0" height="20" />
</mx:VBox>
</mx:AddChild>
</mx:State>
</mx:states>
</mx:Application>