Tabbing does not work in mx:TileList component - actionscript-3

I am using mx:Tilelist component to display set of textfields on screen, but when i try to traverse the fields through TAB foucs move out of the list. Please provide solution for this problem. Following is the code i am using
<mx:TileList id="tileList"
dataProvider="{collection}"
change="setCurrentIndex(tileList.selectedIndex);"
dataChange="setCurrentIndex(tileList.selectedIndex);"
columnCount="1"
columnWidth="345"
itemRenderer="components.InputParamIR"
rowHeight="30"
verticalScrollPolicy="auto"
horizontalScrollPolicy="auto"
backgroundColor="#EEEEEE"
dragEnabled="false"
dragMoveEnabled="true"
dropEnabled="true"
width="100%" height="100%"
itemClick="chartTileClick(event);"
/>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.containers.Panel;
[Bindable]
public var index:uint;
[Bindable]
public var collection:ArrayCollection = new ArrayCollection();
[Bindable]
public var isVisible:Boolean ;
public function initEventsLocal(event:Event):void
{
this.initEvents(event);
collection = new ArrayCollection();
isVisible = false;
}
private function chartTileClick(event:ListEvent):void
{
event.currentTarget.tabFocusEnabled=true;
event.currentTarget.tabEnabled=true;
}
]]>
</fx:Script>

In Flex List Itemrenderer may not get the focus since it is non editable and it will not implement the focus manager interface, you need to implement IFocusManagerComponent in your item renderer components.InputParamIR also you have to override your TileList class to enable tab for childrens.
package
{
import mx.controls.TileList;
public class MyTileList extends TileList
{
override protected function createChildren():void {
super.createChildren();
this.listContent.tabChildren = this.tabChildren
this.listContent.tabEnabled = this.tabEnabled
}
}
}
Have a look in to these
Tile list item renderer text focus solved
Issues with keyboard navigation on list with custom renderer
i hope this will help you
happy coding...

Related

Binding in Flex: How to make a variable automatically update when another variable is changed?

I know that it is possible to make a parameter of a component depend on a variable, provided that variable contains the [Bindable] tag. This means that updating the value of the Bindable variable automatically updates the component.
Is it possible to make another variable depend on a Bindable variable?
In the example below I have a variable btnClicked that is bound. When btnClicked is changed by the function btnClick() being called, the text in the TextArea is updated as expected.
I would like to be able to make another variable, btnText, be updated when btnClicked is updated. I do not know how to communicate this dependency. In the code below the value of btnText is initially "clickMe" as expected. However, when btnClicked changes, the text on the button does not update to "unclickMe".
<fx:Script>
<![CDATA[
[Bindable]
public var btnClicked:Boolean = false;
public function btnClick():void{
btnClicked = !btnClicked;
}
[Bindable]
public function get btnText():String{
return btnClicked?"unclickMe":"clickMe";
}
]]>
</fx:Script>
<s:Button click="btnClick()" label="{btnText}"/>
<s:TextArea y="50" text="{btnClicked?'Button is clicked':'Button is unclicked'}"/>
How can I change the code above so that btnText automatically updates when btnClicked is changed?
Would it be possible to have an arbitrarily long chain of connected variables each of which updates when the previous one updates?
You can also use a ChangeWatcher to detect when your bindable property is updated :
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="init(event)">
<fx:Script>
<![CDATA[
import mx.binding.utils.ChangeWatcher;
import mx.events.FlexEvent;
public var watcher:ChangeWatcher;
[Bindable]
public var btnClicked:Boolean = false;
[Bindable]
public var btnText:String = 'clickMe';
protected function btnClick():void {
btnClicked = !btnClicked;
}
protected function init(event:FlexEvent):void
{
watcher = ChangeWatcher.watch(this, 'btnClicked', watcherListener);
}
protected function watcherListener(event:Event):void {
btnText = btnClicked ? 'unclickMe' : 'clickMe';
}
]]>
</fx:Script>
<s:Button x="303" y="30" label="{btnText}" click="btnClick()"/>
<s:TextArea x="303" id="txt" y="96" text="{btnClicked ? 'Button is clicked' : 'Button is unclicked'}"/>
</s:Application>
Hope that can help.
In this case, all you have to do is update your btnClick function to dispatch a PropertyChangeEvent:
public function btnClick():void{
btnClicked = !btnClicked;
dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));
}
This works because of the way [Bindable] works - see What does [Bindable] mean in actionscript? for a nice explanation.
Using the Bindable metadata tag and Binding to functions, Objects, and Arrays are good resources for background reading, too.
Edit: Don't forget the import statement!
import mx.events.PropertyChangeEvent;
Flash Builder will insert the import statement for you if you ctrl-space while typing PropertyChangeEvent.
I have found a solution, but if someone has a cleaner solution that makes use of in built Flex features please post it.
The following code updates the value of btnText each time the value of btnClicked is changed. It does this by having a setter function for btnClicked that explicitly calls function updateBtnText. See this explanation for more information about how getters and setters allow you to call other functions any time a variable is read or written.
<fx:Script>
<![CDATA[
private var _btnClicked:Boolean = false;
[Bindable]
public function get btnClicked():Boolean{
return _btnClicked;
}
public function set btnClicked(newBtnClicked:Boolean):void{
_btnClicked = newBtnClicked;
updateBtnText();
}
private function updateBtnText():void{
btnText = btnClicked?"unclickMe":"clickMe";
}
public function btnClick():void{
btnClicked = !btnClicked;
}
[Bindable]
public var btnText:String = btnClicked?"unclickMe":"clickMe";
]]>
</fx:Script>
<s:Button click="btnClick()" label="{btnText}"/>
<s:TextArea y="50" text="{btnClicked?'Button is clicked':'Button is unclicked'}"/>

how to work with event in Flex?

import flash.events.Event;
public class RequestEvent extends Event
{
public static const REQUEST:String = "request";
private var Results:Boolean;
public function get Results():Boolean
{
return _Results;
}
public function RequestEvent(Results:Boolean=false)
{
super(REQUEST);
Results = Results;
}
override public function clone():Event
{
return new RequestEvent(Results);
}
}
}
hi can some body explain why we are doing overridding of function clone and calling super(request), new in flex ........so don't mind.
One needs to implement the clone method just so that Flex could re-clone the event in the case when an event handler wishes to dispatch the same event again. Flex does provide a default implementation but one may override the method to clone the event differently, if need be.
As for calling the super method, you must call the super becasue you are extending the Event class. The type (in your case, REQUEST) must be a unique string that would uniquely identify the event to Flex platform.
Hope it helps
Regards.
The question about the overriding of the clone method in custom events is very popular and it seems to be one of the Flex strange things. You can read about it here.
So you have to override this method and only in this method you can define values of custom properties. The method is not usual, so if you try to debug it you will never get the debugger in its body.
If you try to define the value of your custom property in the constructor, the value will be ignorred.
It can be unpractical to use a constant string as the event's type value. In this case all instances of your RequestEvent are of the same type and you could not tell them appart using in different situations. As you can see in the example below, this string is used in action listener to map the listener function.
In this example I have three buttons with different events - normal Event, my version of RequestEvent and your version of it. Have a look at it, I hope it can help to understand the case.
//Application
<fx:Script>
<![CDATA[
import fld02.com.customevent.RequestEvent;
import fld02.com.customevent.RequestEvent2;
import mx.controls.Alert;
private function onCustomGroupBtn2Clicked(evt:RequestEvent):void
{
Alert.show('Btn2Clicked: results = ' + evt.results.toString(), 'This is RequestEvent');
}
private function onCustomGroupBtn3Clicked(evt:RequestEvent2):void
{
Alert.show('Btn3Clicked: Results = ' + evt.Results.toString(), 'This is your RequestEvent');
}
]]>
</fx:Script>
<customevent:CustomGroup
BUTTON1_CLICKED="{Alert.show('Btn1Clicked', 'This is Event')}"
BUTTON2_CLICKED="onCustomGroupBtn2Clicked(event)"
request="onCustomGroupBtn3Clicked(event)"/>
</s:Application>
//CustomGroup
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="346" height="144">
<fx:Metadata>
[Event(name="BUTTON1_CLICKED", type="flash.events.Event")]
[Event(name="BUTTON2_CLICKED", type="fld02.com.customevent.RequestEvent")]
[Event(name="request", type="fld02.com.customevent.RequestEvent2")]
</fx:Metadata>
<fx:Script>
<![CDATA[
private function onBtn1Click():void
{
this.dispatchEvent(new Event("BUTTON1_CLICKED"));
}
private function onBtn2Click():void
{
var requestEvent:RequestEvent = new RequestEvent("BUTTON2_CLICKED");
requestEvent.results = true;
this.dispatchEvent(requestEvent);
}
]]>
</fx:Script>
<s:Button x="43" y="31" width="183" label="Generate Event" click="onBtn1Click()"/>
<s:Button x="43" y="62" width="183" label="Generate RequestEvent" click="onBtn2Click()"/>
<s:Button x="43" y="93" width="183" label="Generate Your RequestEvent" click="{this.dispatchEvent(new RequestEvent2(true))}"/>
</s:Group>
//My RequestEvent
package fld02.com.customevent
{
import flash.events.Event;
public class RequestEvent extends Event
{
private var _results:Boolean;
public function RequestEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
override public function clone():Event
{
var requestEvent:RequestEvent = new RequestEvent(this.type);
requestEvent.results = this.results;
return requestEvent;
}
public function get results():Boolean
{
return _results;
}
public function set results(value:Boolean):void
{
_results = value;
}
}
}
//Your RequestEvent
package fld02.com.customevent
{
import flash.events.Event;
public class RequestEvent2 extends Event
{
public static const REQUEST:String = "request";
public function RequestEvent2(Results:Boolean=false)
{
super(REQUEST);
Results = Results;
}
private var _Results:Boolean;
public function get Results():Boolean
{
return _Results;
}
override public function clone():Event
{
return new RequestEvent2(Results);
}
}
}

Flex 4 - Embedding Multiple MP3's

I have an mp3 embedded in a Flex application with a start and stop button. Using this code...
<fx:Script>
<![CDATA[
import mx.core.SoundAsset;
import flash.media.*;
[Embed(source="assets/pie-yan-knee.mp3")]
[Bindable]
public var Song:Class;
public var mySong:SoundAsset = new Song() as SoundAsset;
public var channel:SoundChannel;
public function playSound():void
{
stopSound();
channel = mySong.play();
}
public function stopSound():void
{
if ( channel != null ) channel.stop();
}
]]>
</fx:Script>
<s:HGroup>
<s:Button label="play" click="playSound();"/> <s:Button label="stop"
click="stopSound();"/>
</s:HGroup>
I want to have multiple instances with different sounds though.
How can I do this?
Just make a separate class reference for each:
[Embed(source="assets/song1.mp3")]
[Bindable]
public var Song1:Class;
[Embed(source="assets/song2.mp3")]
[Bindable]
public var Song2:Class;
[Embed(source="assets/song3.mp3")]
[Bindable]
public var Song3:Class;

How to Create Alert Dialog in ActionScript3?

I'm working on a project with Actionscript 3.0 in Flash Pro (CS5). I want to create a confirmation box. If I were using the Flex SDK I could do this using the Alert class in the mx.controls package. However, it seems that no similar control exists in the standard Flash library and any amount of Googling just leads me to Flex references.
Try this Class
package com.whatever {
//Imports
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
//Class
public class AlertBox extends Sprite {
//Vars
protected var box:Shape;
protected var yesBtn:Sprite;
//Constructor
public function AlertBox($:Rectangle):void {
//Initialise
box = new Shape()
yesBtn = new Sprite()
addChild(box)
addChild(yesBtn)
//Render
with (box.graphics) {
lineStyle(1)
beginFill(0, 0.4)
drawRect($.x, $.y, $.width, $.height)
endFill()
}
with (yesBtn.graphics) {
lineStyle(1, 0x00FF00)
beginFill(0x00FF00, 0.4)
drawRect($.x+$.width-100, $.y$.height-40, 80, 20)
endFill()
}
//Events
yesBtn.addEventListener(MouseEvent.CLICK, yesClickHandler, false, 0, true)
yesBtn.addEventListener(MouseEvent.MOUSE_OVER, yesOverHandler, false, 0, true)
}
//Handlers
protected function yesClickHandler($):void {}
protected function yesOverHandler($):void {}
You said that you can't import mx.Controls in AS3 but the following should work in a flex 4 project:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private function init():void
{
Alert.show("This is an Alert!!!");
}// end function
]]>
</fx:Script>
</s:Application>
[UPDATE]
After realizing that I misunderstood the question, I looked on the internet for a Alert component for AS3 projects and found the following:
http://developer.yahoo.com/flash/astra-flash/alertmanager/
I'm going try my hand at creating a replica of the flex framework's Alert control and then update my answer again.
If your final swf is going to run in the browser and have script access, you could just use one of the JavaScript PopUp Boxes:
if(ExternalInterface.available) {
if (ExternalInterface.call("confirm", "Should I trace 'Yes'?")) {
trace("Yes"); // user clicked Okay
} else {
trace("User canceled or the call failed");
}
}
I'm pretty sure this will freeze the Flash UI loop until the JavaScript function returns, so make sure you call it when it's all you want to be doing.
I believe that you can continue to use the same Alert class
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/Alert.html

Flex3: Custom Item Renderer does not listen to events dispatched by parent

I have a List with a custom ItemRenderer. The ItemRenderer contains a Checkbox and a Label.
The component with the List has a 'select all' checkbox.
When the 'select all' checkbox is checked, it dispatches an event that each item should listen to in order to select its own checkbox.
The eventlistener is added on creationComplete of each item, and the event is dispatched correctly when the 'select all' checkbox is selected, but the listener in the custom ItemRenderer does not listen.
How do I make the ItemRenderer listen to an event that is dispatched in its parent??
I'll add some code examples to clarify:
------- container ----------
<mx:VBox>
<mx:Script>
<![CDATA[
public var user1 = new User(1, "Jack");
public var user2 = new User(2, "John");
public var user3 = new User(3, "Mary");
[Bindable]
public var users:ArrayCollection = new ArrayCollection([user1], [user2], [user3]);
public static const SELECT_ALL_USERS:String = "selectAllUsers";
private function selectAllChangeHandler():void
{
if (selectAll.selected)
dispatchEvent(new Event(SELECT_ALL_USERS,true));
}
]]>
</mx:Script>
<mx:CheckBox id="selectAll" change="{selectAllChangeHandler()}" />
<mx:List dataProvider="{users}" itemRenderer="myRenderer" />
</mx:VBox>
------- renderer ----------
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox creationComplete="{init()}">
<mx:Script>
<![CDATA[
private function init():void
{
addEventListener (Container.SELECT_ALL, selectAllHandler, false, 0, true);
}
private function selectAllHandler():void
{
checkbox.selected=true;
}
private function selected(id:int):Boolean
{
return id==1 || id==3;
}
]]>
</mx:Script>
<mx:CheckBox id="checkbox" selected="{selected(data.id)}" />
<mx:Label text="{data.name}" />
</mx:HBox>
Please note that the users ArrayCollection or its containing user objects cannot be changed because I need the values later on.
So when 'selectAll' is clicked, each checkbox in the list should also be checked.
Your custom ItemRenderers should not register an event listener with their parent, but with your "select all" checkbox, i.e.
theCheckbox.addEventListener(YourEvent.YOUR_EVENT, itemRendererSelectAllHandler);
Failing that, can you post your code which adds the event listener and which dispatches the event form the checkbox?
edit:
Here's your bug: In renderer's init(), you need to add an event listener not to the renderer, but to the container which dispatches the event. So make that a
container.addEventListener(Container.SELECT_ALL_USERS, selectAllHandler, false, 0, true);
Doing select all in flex is little complex but I will tell you the way we did it and it works great.
We created a List derived control called "ExList" which has a property "selectAllCB" which we bind it to existing check box which will work for select all logic. Please note, when we set selectAllCB property, we make ExList to listen to checkbox's events.
When checkbox is checked, we manually set selectedItems array to array of dataProvider and all items are selected.
Playing with itemRenderer doesnt work correctly because when you program your list again and again everytime you have to write so much of code.
I am attaching some sample code here below..
public class ExList extends List
{
public function ExTileList()
{
super();
this.allowMultipleSelection = true;
}
private var _selectAllCB:CheckBox = null;
[Bindable]
public function get selectAllCB():CheckBox
{
return _selectAllCB;
}
public function set selectAllCB(v:CheckBox):void
{
if(v==null)
return;
_selectAllCB = v;
v.addEventListener(ListEvent.ITEM_CLICK, handleAllChange,false, 0 , true);
v.addEventListener("change", handleAllChange,false, 0 , true);
}
private function handleAllChange(e:Event):void
{
if(_selectAllCB.selected)
{
this.selectedItems = this.dataProvider.toArray();
}
else
{
this.selectedItems = new Array();
}
}
}
And you can use it as...
<CheckBox id="sAll"/>
<ExList selectAllCB="{sAll}"/>
// Please note its in curly braces
This is how I achieved the solution:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" height="150" verticalGap="0">
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import mx.controls.CheckBox;
import mx.collections.ArrayCollection;
public var listData:ArrayCollection;
private function selectAll():void
{
listChkBox.selectedItems = listData.toArray();
for each (var item:Object in listChkBox.selectedItems)
{
CheckBox(listChkBox.itemToItemRenderer(item)).selected = true;
}
}
private function resetAll():void
{
listChkBox.selectedItems = listData.toArray();
for each (var item:Object in listChkBox.selectedItems)
{
CheckBox(listChkBox.itemToItemRenderer(item)).selected = false;
}
}
]]>
</mx:Script>
<mx:List width="100%" height="100%" id="listChkBox" labelField="name" allowMultipleSelection="true"
dataProvider="{listData}" selectionColor="#FFFFFF" >
<mx:itemRenderer>
<mx:Component>
<mx:CheckBox >
</mx:CheckBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
<mx:HBox width="100%" backgroundColor="#E2DEDE" paddingBottom="2" paddingLeft="2" paddingTop="2" paddingRight="2" borderStyle="solid">
<mx:Button label="All" id="btnAll" click="selectAll()" />
<mx:Button label="None" click="resetAll()"/>
</mx:HBox>
</mx:VBox>
The simple solution is to use typed objects in the list of data you are presenting and then take advantage of databinding and the binding utils to capture changes to the underlying data property on the item renderer. Override the 'set data' function in the item renderer to do whatever you need when some property in the object gets changed to reflect the 'select all/de select all' state.