February 09, 2007
Flex 2 and Accessibility
One improtant thing to keep in mind is that Accessibility support doesn't happen automatically. You have to tell flex you want Accessibility support in your app, and you need to implement it accordingly. Here are all the relevant links regarding Accessibility.Enabling Application Accessibility
There are multiple ways to enabling application accessibility. See here for details. If you are using flex builder 2 to compile your app, from Flex builder, go to project--->properties ---> flex compiler, check the box "generate accessible SWF file".
Flex Accessibility Best Practices
Flex includes 22 components with built-in accessibility support. But this does not mean you can simply compile you app with accessibility enabled, and your app will meet all the requirement. You need to make sure you have taking care of Controlling Reading Order, Providing Instructions , Ensuring Keyboard Access, Providing Captions, Providing Text Equivalents, and Using Color Wisely.
Using Flex with JAWS
In order to most effectively use the JAWS screen reader with an Adobe Flex application, users must download and install scripts.
Posted by lin at 04:45 PM | Comments (244)
February 08, 2007
Example of Designing Loosely Coupled Flex 2 Components --- pass data from main to child component
There is a good article regarding Designing Loosely Coupled Flex 2 Components. This is a good place to learn about different ways to design your components in Flex 2. On the third page of this article, it demonstrated how to Create Custom Event ActionScript Classes for sending complex data with an example. This example shows how to send data to the parent page by dispatch an event from the child component. What if you want to dispatch the event from the parent page, and pass the data into the child? Here is a simple example to show how we can accomplish that.
1. create a customer event ActionScript class:
In order to pass extra data via event, a customer event class is needed. We do this by extends existing Flex event classes and inherit all the events of the base class. Here we create myEvent.as to pass selectedAlbum with the event.
myEvent.as:
package
{
import flash.events.Event;
import mx.core.Application;
public class myEvent extends Event
{
public var myAlbum:String;
public function myEvent(selectedAlbum:String,type:String) {
super(type);
this.myAlbum = selectedAlbum;
Application.application.lb.text=myAlbum;
}
public override function clone():Event{
return new myEvent(myAlbum,type);
}
}
}
2. Create the main application:
The main application has a datagrid. The goal is to be able to display data in a new state based on selected row in the datagrid. The follwoing two handlers are the most improtant:
1).datagrid's itemClick event handler itemClickEvent(): this will get the selected row and value of selectedAlbum.
2).eventHandler(): this will display the new state, dispatch event myEvent (must make sure the event is dispatched after the child is created), and pass selectedAlbum to the child component. We reference the child component as <v:looselyCoupledChild />.
Note, eventObj = new myEvent(selectedAlbum,"passID");
Here, passID is the event name we will define in the Metadata of the child component:
<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>
main flex page looselyCoupled.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:v="*" layout="vertical">
<!--This example passes selectedAlbum to child.mxml by listening to myEvent -->
<mx:Script>
<![CDATA[
import flash.events.EventDispatcher;
import mx.events.ListEvent;
import mx.collections.ArrayCollection;
[Bindable]
public var selectedAlbum:String;
public var eventObj:myEvent;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, SalePrice: true },
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, SalePrice: false }
]);
private function itemClickEvent(event:ListEvent):void {
selectedAlbum=event.currentTarget.selectedItem.Album;
eventObj = new myEvent(selectedAlbum,"passID");
this.dispatchEvent(eventObj);
lb1.text=eventObj.myAlbum;
}
private function eventHandler(stateView:String):void{
//the stateView must be created before the event dispatch.
this.currentState = stateView;
dispatchEvt();
}
private function dispatchEvt():void{
eventObj = new myEvent(selectedAlbum,"passID");
this.dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:Label id="lb" text="show selectedAlbum -- from myEvent"/>
<mx:Label id="lb1" text="show selectedAlbum -- from eventObj.myAlbum"/>
<mx:DataGrid id="dg" dataProvider="{initDG}" itemClick="itemClickEvent(event)">
</mx:DataGrid>
<mx:Button x="117" y="240" label="dispaly Album" id="bt" click="eventHandler('child')" />
<mx:states>
<mx:State name="child">
<mx:AddChild position="lastChild">
<v:looselyCoupledChild />
</mx:AddChild>
</mx:State>
</mx:states>
</mx:Application>
3. create the child component:
In the child component, we need to add event listener to listen to passID as following: Application.application.addEventListener("passID", passIDHandler);
looselyCoupledChild.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" initialize="initHandler()" >
<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import mx.core.Application;
import myEvent;
private function initHandler():void{
Application.application.addEventListener("passID", passIDHandler);
}
private function passIDHandler(event:myEvent):void {
tinput.text = event.myAlbum;
}
]]>
</mx:Script>
<mx:Label text="Album you selected from event:" x="26" y="10"/>
<mx:TextInput x="107" y="8" id="tinput" />
<mx:Label x="291" y="10" text="Album you selected from selectedAlbum:"/>
<mx:TextInput x="372" y="8" text="{Application.application.selectedAlbum}"/>
</mx:Panel>
Note, Application.application.addEventListener("passID", passIDHandler); This means we will always have a reference to the child. If you are concerned about memory issue, you should check and destroy the event when it is done. If you don't want to destroy the event, you can set weakRef to true in addEventListener.
To test the sample,
1). run looselyCoupled.mx, and select a row. You will see the Album name displayed on top of the datagrid.
2). click on "dispaly Album" Button, you will see the Album name has passed into the child component.
3). select another row in the datagrid, you will see the value in the child component is changed as well.
Posted by lin at 05:16 PM | Comments (204)
January 23, 2007
Tips for configuring QTP with flex 2.0.1
Key info:
1. must have QTP 9.1, flex 2.0.1, IE 6+, and install the QTP plug-in.
2. must recomiple the app in flex 2.0.1 with automation testing libraries.
3. must put the swf and html file to the QTP machine.
4. When testing, access the html(not the swf) file from a browser via web server. don't open the html from the file system.
- Before you start to test your flex app with QTP, you have to make sure you have all the necessary software installed and configured correctly.
- Make sure you installed QTP 9.1, not 9.0.
- Make sure you installed flex 2.0.1 , and your flex app should be recompiled using flex 2.0.1.
- Make sure you have installed the QTP plug-in. You can download it from our website. You will need to register to login the page first. After you login into the page, scroll down and you will see "Flex Automation Package". From there you can download Flex_Automation.zip. After you unzip the zip file, you can see QTP_Plugin_Installer.exe. Run that exe file and that will install the plugin. Note, To verify if you have installed the plug-in or not, go to your registry, and search for entry of TEAPluginIE.dll and TEAPluginQTP.dll. If those dlls are not in the registry, then your plug-in has not been installed correctly.
- If you have above installation and configuration, but the QTP does not record the flex app, then check the following:
- QTP plug-in is only supported on IE 6+, you need to make sure your browser is using IE 6 or higher version. And your flash player must be version 9.0.28. or higher. To verify your flash player version, request the following link from your testing browser: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_15507
- The flex app you are going to test with QTP must be prepared for automation. You need compile your app with automation testing libraries, such as automation.swc, automation_agent.swc, and qtp.swc, etc. You can compile this via Command-line compiler or flex builder. If you have compiled your flex app in flex 2.0.1 already, and want to Test run-time loading, then you can compile RunTimeLoading. Please follow the instruction step by step described here.
- If you request your flex app from a browser, you have to use the html wrapper file. Do not accessing the swf directly, it needs to be loaded from an object tag with an ID. You can open the wrapper or the SWF file from the file system, but it is not a recommended practice. You should try to deploy the SWF file to a web server and request the html wrapper through HTTP from the server. See page 13 of Testing Flex Applications with Mercury QuickTest Professional for more details.
- If you still have trouble getting up and running with Flex QTP plugin, you can create a log by following the steps below:
- Go to the mercury installation/bin directory say: "C:\Program Files\Mercury Interactive\QuickTest Professional\bin" and run MicLogSetting.exe .
- Select the log settings as: Level: MicLogLevelDebug2 Folder:C:\Program Files\Mercury Interactive\QuickTest Professional\ Selected Categories:LogCatPackTEA
- Run QTP and record a flex application say flexstore.html
- A log file would have been generated like C:\Program Files\Mercury Interactive\QuickTest Professional\MicLogFile_QTPro_pid1912_11_32_32.html
- Check whether you are seeing the following in the log: "Read Flex environment and matching ProgId TEAPluginQTP.TEAFlexAgentQTP.
Posted by lin at 12:45 PM | Comments (352)