Browser Communication: Chapter 20 - Flex 3 Cookbook
Pages: 1, 2
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="parseURL()">
<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
import mx.managers.IBrowserManager;
import mx.managers.BrowserManager;
import mx.utils.URLUtil;
private function parseURL() : void
{
//get an instance of the browser manager
var bm:IBrowserManager = BrowserManager.getInstance();
//initialize the browser manager
bm.init();
//output the url parameter values
output.text += "Full URL:\n" + bm.url + "\n\n";
output.text += "Base URL:\n" + bm.base + "\n\n";
output.text += "URL Fragment:\n" + bm.fragment + "\n\n";
//convert url parameters to an actionscript object using URLUtil
var o:Object = URLUtil.stringToObject(bm.fragment);
output.text += "Object:\n" + ObjectUtil.toString( o ) + "\n\n";
output.text += "name:\n" + o.name + "\n\n";
output.text += "index:\n" + o.index + "\n\n";
output.text += "productId:\n" + o.productId + "\n\n";
//parse URL using URLUtil
output.text += "URL Port:\n" + URLUtil.getPort( bm.url ) + "\n\n";
output.text += "URL Protocol:\n" + URLUtil.getProtocol( bm.url ) +
"\n \n";
output.text += "URL Server:\n" + URLUtil.getServerName( bm.url ) + "\n\n";
output.text += "URL Server with Port:\n" +
URLUtil.getServerNameWithPort( bm.url );
}
]]>
</mx:Script>
<mx:TextArea id="output" left="10" top="10" bottom="10" right="10"/>
</mx:Application>
If the preceding example had the URL http://localhost:8501/flex3cookbook/main.html#name=Andrew;index=12345;productId=987, the result would be:
Full URL: http://localhost:8501/flex3cookbook/main.html#name=Andrew;index=12345;productId=987 Base URL: http://localhost:8501/flex3cookbook/main.html URL Fragment: name=Andrew%20Trice;index=12345;productId=987654 Object: (Object)#0 index = 12345 name = "Andrew" productId = 987 name: Andrew index: 12345 productId: 987 URL Port: 8501 URL Protocol: http URL Server: localhost URL Server with Port: localhost:8501
Section 20.7: Deep-Link to Data via BrowserManager
Problem
You need to pass data from the browser's URL into Flex controls, and you need to update the value of the browser URL based on data within your Flex application, which should also work the browser's Forward and Back navigational buttons.
Solution
Use the BrowserManager class
and BrowserChangeEvents to read and write data
on the browser URL.
Discussion
Whenever the browser URL changes either by text input on the
address bar, or through the usage of the navigation controls (Forward
and Back buttons), a
event is dispatched through the BrowserManager instance. Whenever this type
of event is encountered, you simply invoke the updateValues method to update values within
the Flex controls. This lets you easily link to, and cycle through,
your input values.
The following example shows you how to read data from the
browser's URL and put those values into Flex mx:TextInput fields. When the sample
application loads, it will read the data from the current URL and
write the values of the firstName
and lastName parameters into the
text boxes. When the value of either the firstName or lastName mx:TextInput field is changed, the
application will call the setFragment
function on the browser manager, which will update the browser's URL
with the new values for the firstName and lastName parameters. This enables you to
copy and paste the URL, so that you can easily link directly into the
current view, and it also adds every change to the browser
history.
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onCreationComplete()" >
<mx:Script>
<![CDATA[
import mx.events.BrowserChangeEvent;
import mx.managers.IBrowserManager;
import mx.managers.BrowserManager;
import mx.utils.URLUtil;
private var bm:IBrowserManager
private function onCreationComplete():void
{
//get an instance of the browser manager
bm = BrowserManager.getInstance();
//initialize the browser manager
bm.init();
//set initial values based on url parameters
updateValues();
//add event listeners to handle back/forward browser buttons
bm.addEventListener( BrowserChangeEvent.BROWSER_URL_CHANGE,
onURLChange );
}
private function updateValues():void
{
//update text box values based on url fragment
var o:Object = URLUtil.stringToObject(bm.fragment);
firstName.text = o.firstName;
lastName.text = o.lastName;
}
private function updateURL():void
{
//update URL fragment
bm.setFragment( "firstName=" + firstName.text + ";lastName=" +
lastName.text );
}
private function onURLChange( event : BrowserChangeEvent ):void
{
//call update values based on change url
updateValues();
}
]]>
</mx:Script>
<mx:TextInput x="10" y="10" id="firstName" change="updateURL()" />
<mx:TextInput x="10" y="40" id="lastName" change="updateURL()" />
</mx:Application>
Section 20.8: Deep-Link Containers via BrowserManager
Problem
You need to control the visible contents of Flex 3 containers based on URL parameters.
Solution
Use the BrowserManager class
and BrowserChangeEvents to
control the visibility and track the history of the visible
Flex components.
Discussion
In this scenario, you use the URL fragment to control and track
which containers and components are visible within a Flex application.
When the application loads, you initialize the BrowserManager class instance, which helps
you parse and handle the browser URL. The updateContainers method (shown in the following code segment) determines which
of the tabs within the mx:TabNavigator
instance is visible. Any time that tab navigator's visible tab
changes, you set the selectedIndex
property in the URL fragment by using the following snippet:
bm.setFragment( "selectedIndex=" + tabNav.selectedIndex );
This updates the browser's URL and adds the change to the browser history. If someone were to copy and paste the current browser URL, that user would link directly to the currently selected tab navigator.
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import mx.events.BrowserChangeEvent;
import mx.managers.IBrowserManager;
import mx.managers.BrowserManager;
import mx.utils.URLUtil;
private var bm:IBrowserManager;
private function onCreationComplete() : void
{
//get an instance of the browser manager
bm = BrowserManager.getInstance();
//initialize the browser manager
bm.init();
//set visible containers based on url parameters
updateContainers();
//add event listeners to handle back/forward browser buttons
bm.addEventListener( BrowserChangeEvent.BROWSER_URL_CHANGE,
onURLChange );
updateURL():
}
private function updateContainers():void
{
//convert url parameters to an actionscript object
var o:Object = URLUtil.stringToObject(bm.fragment);
//set the selected index
if ( !isNaN(o.selectedIndex) )
{
var newIndex : Number = o.selectedIndex;
if ( newIndex >= 0 && newIndex < tabNav.numChildren )
tabNav.selectedIndex = newIndex;
}
}
private function onURLChange( event:BrowserChangeEvent ):void
{
//call updateContainers when url value changes
updateContainers();
}
private function updateURL():void
{
bm.setFragment( "selectedIndex=" + tabNav.selectedIndex );
}
]]>
</mx:Script>
<mx:TabNavigator
bottom="10" top="10" right="10" left="10"
id="tabNav"
historyManagementEnabled="false">
<mx:Canvas label="Tab 0" show="updateURL()" >
<mx:Label text="Tab 0 Contents" />
</mx:Canvas>
<mx:Canvas label="Tab 1" show="updateURL()" >
<mx:Label text="Tab 1 Contents" />
</mx:Canvas>
<mx:Canvas label="Tab 2" show="updateURL()" >
<mx:Label text="Tab 2 Contents" />
</mx:Canvas>
</mx:TabNavigator>
</mx:Application>
You may also notice that the historyManagementEnabled parameter on the
is set to false. This
is because you are using events from the BrowserManager class to determine whether
the browser URL has changed, and to update the tab contents
accordingly. Every change to the visible tab ends up with changes to
the browser history; users can go back and forward through the visible
tabs by using the browser's Back and Forward buttons.
Section 20.9: Implement Custom History Management
Problem
You want actions or changes in your custom components to register with the browser's history and be navigable via the browser's Forward and Back buttons.
Solution
Implement custom history management in your Flex components by
implementing the mx.managers.IHistoryManagerClient
interface.
Discussion
For this solution to work, history management must be enabled for your Flex project. You can verify that history management is enabled by going to the Flex Project Properties dialog box, selecting the Flex Compiler screen, and verifying that the Enable Integration with Browser check box is selected.
The following code shows you how to implement the IHistoryManagerClient interface for a custom
text box component. Any time that a change is made in this component,
that change will register with the browser history. Users can go
backward and forward through the inputs of this TextInput control by using the browser's
Back and Forward buttons.
<mx:TextInput
xmlns:mx="http://www.adobe.com/2006/mxml"
text="Change Me!"
implements="mx.managers.IHistoryManagerClient"
creationComplete="mx.managers.HistoryManager.register(this);"
change="textChanged(event)">
<mx:Script>
<![CDATA[
import mx.managers.HistoryManager;
public function saveState():Object
{
return {text:text};
}
public function loadState(state:Object):void
{
var newState:String = state ? state.text : "";
if (newState != text)
{
text = unescape( newState );
}
}
private function textChanged(e:Event):void
{
HistoryManager.save();
}
]]>
</mx:Script>
</mx:TextInput>
After the component has been created, you must register that
class instance with the history manager. You can see this in the
creationComplete event handler for
the custom component:
creationComplete="mx.managers.HistoryManager.register(this);"
The IHistoryManagerClient
interface requires the saveState and
loadState functions to be present
within your custom component.
Any time the value of the custom TextInput control is changed, the textChanged method is invoked, which calls
the save function on the history manager. When state is saved by the
history manager, the saveState
method is invoked.
The saveState method should
return an object that will be persisted in the browser's history. In
this case, the method is returning an object with the property
text, which is set to the text
value of the TextInput
component.
When the browser history is changed via the Forward and Back
buttons, the loadState method gets
invoked. The loadState method reads
the text property from the State object that is passed into it. It then
sets the text property of the
TextInput control based on the
value passed in through the State
object.
You can add this component to your Flex application by using code similar to the following:
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
xmlns:local="*">
<local:MyTextInput />
</mx:Application>
This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.
