Archive for August, 2010

Set Flex to Focus on Application Load

By default a Flex application is not in focus in the browser when it loads. This can be especially frustrating if you have say a login view and would like the username field to be in focus when the application starts cranking. However, with some simple JavaScript we can set the Flash object to focus when the application loads.

NOTE: This will not work in Safari, Chrome, or any other browser that leverages Webkit, as it doesn’t allow the focus to be set on embedded objects. If you’re targeting IE and Firefox the proposed solution below will work.

For example purposes, let’s assume we want to make our username TextInput field have focus when the Flex app starts rocking.

First, set the focus to the username field — assume a ViewMediator is doing this:

this.view.userNameTextInput.setFocus();

Create a simple JavaScript method to set the focus of the browser to your Flex application. Create this method in the index.template.html file in your Flex project — just drop it right before the closing HTML tag at the bottom of the file:

<script type="text/javascript">
function onFlexInitialized()
{
	//alert("onFlexInitialized");

	<!-- Force the browser to set flex app with focus -->
	document.getElementById("${application}").focus();
}
</script>

Next catch the application complete event and call the JS method we just created — I put in how to remove the event handler for the app complete for both Flex 3 and 4:

/**
 * Constructor.
 */
public function AppController()
{
	FlexGlobals.topLevelApplication.addEventListener(FlexEvent.APPLICATION_COMPLETE, onAppComplete); // Flex 4
        //Application.application.addEventListener(FlexEvent.APPLICATION_COMPLETE, onAppComplete); // Flex 3
}

/**
 * Handles the application complete event.
 */
protected function onAppComplete(e:FlexEvent):void
{
	FlexGlobals.topLevelApplication.removeEventListener(FlexEvent.APPLICATION_COMPLETE, onAppComplete); // Flex 4
        //Application.application.removeEventListener(FlexEvent.APPLICATION_COMPLETE, onAppComplete); // Flex 3

	if(ExternalInterface.available)
	{
		ExternalInterface.call("onFlexInitialized");
	}
}

And that’s it. Again, it doesn’t work in Safari and Chrome. Here are the 2 defects logged for each brower’s bug-base respectively: Chrome, Safari.

Post to Twitter Tweet This Post

, , , , ,

4 Comments

New AbstractViewMediator For Popups Using Swiz 1.0 RC1

This post builds on my last post regarding the use of the ViewMediator pattern with Swiz. One of the things I hadn’t tested when I wrote the original AbstractViewMediator (AVM) was popups. Once I started using this base class in a couple projects I realized I had a pretty big hole that I quickly need to fix.

Download the new and improved AbstractViewMediator.

Normally, views are added to the display list, but popups are actually added to the SystemManager so they don’t fire off the flash.events.Event.ADDED_TO_STAGE event that’s mediated in the setView() method in my AbstractViewMediator and that’s the core piece of logic behind the entire AbtractViewMediator. See the last post for details.

So how would I connect my views to my VMs? The key was to make the AbstractViewMediator actually create the popup via the following method:

public function createPopupView(
								view:IFlexDisplayObject,
								parent:DisplayObject,
								modal:Boolean = false,
								childList:String = null,
								moduleFactory:IFlexModuleFactory = null
								):IFlexDisplayObject
{
	this.setView(view);

	PopUpManager.addPopUp(view, parent, true); // window:IFlexDisplayObject,parent:DisplayObject,modal:Boolean = false,childList:String = null,moduleFactory:IFlexModuleFactory = null
	PopUpManager.centerPopUp(view);

	return view;
}

If you look at the method signature you’ll see that I pass in a reference to the view we’re creating and then call the all important public function setView(value:*):void method that’s usually called by the mediated event flash.events.Event.ADDED_TO_STAGE. This is what creates the connection between a VM and a View. This also brings up a new question — who calls this method?

In order for the VM to be hooked up to the correct view, we’ll need to make sure we call the createPopupView(...) method on our concrete VM implementation…hmm…so how do we get a hold of that…ahh yes, the nice guys at Swiz gave us access to it via the list of beans that this instance of Swiz has. Let’s learn by example.

We’ll imagine we need to open a popup from MainView after clicking the “Get Users Button”. Naturally, our MainViewMediator mediates the button’s click event and calls this functional method:

/**
 * Open the create user view.
 */
public function openCreateUserView():void
{
	var view:CreateUserView;
	var vm:CreateUserViewMediator;

	view = new CreateUserView();
	vm = this.getViewMediatorBeanById("createUserViewMediator") as CreateUserViewMediator;

	vm.createPopupView(view, this.view, true);
}

The key line is where we get a handle to the CreateUserViewMediator via the method getViewMediatorBeanById(...) in the AbstractViewMediator:

/**
 * Helper method that returns a view mediator managed by Swiz by it's ID.
 *
 * @param	id	The unique ID for the view mediator as defined in the BeanLoader.
 */
public function getViewMediatorBeanById(id:String):AbstractViewMediator
{
	var vm:AbstractViewMediator = this.swiz.beanFactory.getBeanByName(id).source as AbstractViewMediator;

	return vm;
}

/**
 * Helper method that returns a view mediator managed by Swiz by it's ID.
 *
 * @param	clazz	The class type for our view mediator.
 */
public function getViewMediatorBeanByType(clazz:Class):AbstractViewMediator
{
	var vm:AbstractViewMediator = this.swiz.beanFactory.getBeanByType(clazz).source as AbstractViewMediator;

	return vm;
}

This method in the AVM also assumes it has a handle to the instance of Swiz that contains the beans. This is done by implementing the ISwizAware interface in the AVM.

/**
 * Creates a reference to the instance of Swiz this bean is in. This
 * allows us to get a hold of manager beans by using:
 * <code>var vm:MyViewMediator = swiz.beanFactory.getBeanByName("myViewMediator").source as MyViewMediator;</code>
 */
public function set swiz(swiz:ISwiz):void
{
	this._swiz = swiz;
}
public function get swiz():ISwiz
{
	return this._swiz;
}
protected var _swiz:ISwiz;

There you have it. All the pieces. If you create popups this way you’ll get the expected VM to View connection.

Download the new and improved AbstractViewMediator.

Post to Twitter Tweet This Post

, , , , , ,

5 Comments