I have a HGroup with some buttons inside which is my application's menu.
<s:HGroup id="nav">
<s:Button id="homeButton" label="Home" />
<s:Button id="showroomButton" label="Showroom" />
<s:Button label="Catalogue" />
<s:Button label="Offers" />
<s:Button label="My Account" />
<s:Button label="My Orders" />
</s:HGroup>
What I want is when I click for example the #homeButton to change it's state to "over", become disabled and reset all other buttons to the "up" state.
I've written this function
private function resetNavState():void {
for(var i:int = 0,ii:int = nav.numChildren-1;i<ii;i++) {
Button(nav.getChildAt(i)).mouseEnabled = true;
Button(nav.getChildAt(i)).skin.setCurrentState("up",true);
}
}
And then on the homeButton click handler for example i use
protected function homeButton_clickHandler(event:MouseEvent):void
{
resetNavState();
currentState = "home";
homeButton.skin.setCurrentState("over",true);
homeButton.mouseEnabled = false;
}
I resets the states of the #nav buttons but it doesn't change the state of the pressed button.
Any ideas?
Thanx in advance
You'll want to place your buttons in a in a <s:ButtonBar /> control rather than the HGroup.
Related
I'm doing some programmatic validation of some field values in a form, is there any way in Actionscript to highlight the field in red the way the validators do?
you just need to set errorString property on programmatic validation error
<s:TextInput errorString="error string value" />
<mx:TextInput errorString="error string value" />
Using:
var textField:TextField = new TextField();
addChild(textField);
To highlight the background in AS3:
textField.background = true;
textField.backgroundColor = 0xFFF000;
To highlight the border in AS3:
textField.border = true;
textField.borderColor = 0xFFF000;
To turn it off, just set the appropriate boolean to false.
Try using glow filter:
<fx:Declarations>
<s:GlowFilter id="gf" color="#ff0000" alpha="1" blurX="5" blurY="5" />
</fx:Declarations>
<s:TextInput id="ti" width="80%"/>
<s:ToggleButton id="btn" label="glow on/off" click="ti.filters = btn.selected?new Array(gf) : null;"/>
I have created a custom component that I am using, more conveniently, as a SkinnablePopUpContainer and I want to use the same function that calls and receives data from it for several Buttons in the UI. What is the best way to achieve this without having to create a new function for each button?
<fx:Script>
<![CDATA[
import spark.events.PopUpEvent;
protected function button1_clickHandler(event:MouseEvent):void
{
popup.addEventListener(PopUpEvent.CLOSE, onPopUpEventClose1, false, 0, true);
popup.open(this);
}
private function onPopUpEventClose1(event:PopUpEvent):void {
popup.removeEventListener(PopUpEvent.CLOSE, onPopUpEventClose1);
trace(event.commit);
trace(event.data);
button1.label=event.data;
}
protected function button2_clickHandler(event:MouseEvent):void
{
popup.addEventListener(PopUpEvent.CLOSE, onPopUpEventClose2, false, 0, true);
popup.open(this);
}
private function onPopUpEventClose2(event:PopUpEvent):void {
popup.removeEventListener(PopUpEvent.CLOSE, onPopUpEventClose2);
trace(event.commit);
trace(event.data);
button2.label=event.data;
}
]]>
</fx:Script>
<s:Button id="button1" x="102" y="103" label="Button 1 Numbers"
click="button1_clickHandler(event)"/>
<s:Button id="button2" x="102" y="200" label="Button 2 Numbers"
click="button2_clickHandler(event)"/>
You can see how I would rather have one set of functions that can handle all of this rather than manually coding each function.
Is there a way to get the id of the component that calls the function? What's the best way to solve this?
EDIT: SOLUTION
I have been able to replace all of that code with the trimmer following:
private var buttonPick:Button;
public function button_clickHandler(button:Button):void
{
switch (button) {
case button1: popup.addEventListener(PopUpEvent.CLOSE, onPopUpEventClose, false, 0, true);
popup.open(button);
break;
case button2: popup.addEventListener(PopUpEvent.CLOSE, onPopUpEventClose, false, 0, true);
popup.open(button); break;
}
buttonPick = button;
}
private function onPopUpEventClose(event:PopUpEvent):void {
popup.removeEventListener(PopUpEvent.CLOSE, onPopUpEventClose);
trace(event.commit);
trace(event.data);
buttonPick.label=event.data;
}
and this as the mxml:
<s:HGroup click="button_clickHandler(event.target as Button)">
<s:Button id="button1" x="102" y="103" label="Button 1 Numbers"
/>
<s:Button id="button2" x="102" y="200" label="Button 2 Numbers"
/>
</s:HGroup>
Thanks for the input and advice! And if there is a more efficient way to do it than with case statements, be sure to suggest it!
You should put those buttons into a common container and listen for clicks on that container. Then you can use Event#target to detect which element in the container was clicked.
Your buttons in a common container:
<s:Group click="button_clickHandler(event.target as Button)">
<s:Button id="button1" x="102" y="103" label="Button 1 Numbers" />
<s:Button id="button2" x="102" y="200" label="Button 2 Numbers" />
</s:Group>
The event handler:
protected function button_clickHandler(button:Button):void {
switch (button) {
case button1: trace('clicked button 1'); break;
case button2: trace('clicked button 2'); break;
default: trace('clicked somewhere else in the group'); break;
}
}
As you can see, I cast event.target to a Button class using the 'as' keyword. This way, if you click anything else than a Button, the 'button' argument will be 'null'.
Read the docs for Event.target and Event.currentTarget. In this case you want to use currentTarget. This article describes the differences between target and currentTarget.
I have a small flex application.
<mx:Script>
<![CDATA[
import flash.events.Event;
// Event handler function to print a message
// describing the selected Button control.
private function printMessage(event:Event):void {
message.text += event.target.label + " pressed" + "\n";
}
]]>
</mx:Script>
<mx:Panel title="Button Control Example"
height="75%" width="75%" layout="horizontal"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
<mx:VBox>
<mx:Label width="100%" color="blue"
text="Select a Button control."/>
<!-- The button can contain an image, as in the "Button with Icon" button -->
<mx:Button id="iconButton" icon="#Embed('assets/mm-icon.png')" label="Button with Icon"
labelPlacement="right" color="#993300" click="printMessage(event);"/>
<!-- The size of the button and the label attributes can be customized -->
<mx:Button label="Customized Button" color="#993300" toggle="true" selected="true"
textAlign="left" fontStyle="italic" fontSize="13" width="{iconButton.width}"
click="printMessage(event);"/>
<!-- By default, the look and feel of the customized button is
similar to the Default Button. -->
<mx:Button label="Default Button" click="printMessage(event);"/>
</mx:VBox>
<mx:TextArea id="message" text="" editable="false" height="100%" width="100%"
color="#0000FF"/>
</mx:Panel>
What I want to achieve is, I want my user to pass the script as a parameter. so he has the flexibility to do anything with the buttons->like add event, hide the other buttons.
Something like this(below)
<param name="script" value="import flash.events.Event;\n private function printMessage(event:Event):void {\nmessage.text += event.target.label + " pressed" + "\n";\n}">
Thanks.
If I understood, what you want is simply create dynamic event and load it to some component, right? If so in did its very easy to implement.
Just create your own custom event (inherit from Event) or use the Event itself:
var event:Event = new Event("[Your event type here"],[bubbles?],[cancelable?]);
and then add listener to your wanted component to the same "event type".
If you need you can also dispatch this event from wanted component programmatically like this:
[you component].dispatchEvent(event);
but then you have to make sure this component extends EventDispatcher class.
Hope I helped.
Royee
I I have a view in Flex 3 where I use a tab navigator and a number of views inside the tab navigator. I need to be know which view was clicked because of it's one specific view then I need to take action, i.e. if view with id "secondTab" is clicked then do something.
I have set it up to be notified, my problem is that I need to be able to know what view it is. Calling tab.GetChildByName or a similar method seems to only get me back a TabSkin object.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
height="100%"
xmlns:local="*"
creationComplete="onCreationComplete(event)">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.controls.Button;
protected function onCreationComplete(event:Event):void {
for(var i:int = 0; i < myTN.getChildren().length; i++) {
var tab:Button = myTN.getTabAt(i);
tab.addEventListener(FlexEvent.BUTTON_DOWN, tabClickHandler);
}
}
private function tabClickHandler(event:FlexEvent):void {
var tab:Button;
if(event.currentTarget is Button) {
tab = event.currentTarget as Button;
// how do I access the actual view hosted in a tab that was clicked?
}
}
]]>
</mx:Script>
<mx:TabNavigator id="myTN">
<local:ProductListView id="firstTab"
label="First Tab"
width="100%" height="100%" />
<local:ProductListView id="secondTab"
label="Second Tab"
width="100%" height="100%" />
</mx:TabNavigator>
</mx:VBox>
TabNavigator is a subclass of ViewStack and it will fire a change event when you select a tab.
<mx:TabNavigator id="myTN" change="childChanged()">
<local:ProductListView id="firstTab"
label="First Tab"
width="100%" height="100%" />
<local:ProductListView id="secondTab"
label="Second Tab"
width="100%" height="100%" />
</mx:TabNavigator>
It is as straightforward as:
private function childChanged():void
{
if(myTN.selectedChild == this.firstTab) //or myTN.selectedIndex == 0
{
trace("selected the first one");
}
else if(myTN.selectedChild == this.secondTab) //or myTN.selectedIndex == 0
{
trace("selected the second one");
}
}
As TabNavigator is an extension of ViewStack you can access the selected view with the selectedChild property:
private function tabClickHandler(event:FlexEvent):void {
view = myTN.selectedChild;
// Do what you need to do with it here...
}
For more information on how TabNavigator works, check out the Documentation:
http://livedocs.adobe.com/flex/3/html/help.html?content=navigators_4.html
I am creating a lot of dynamic flex components like RadioButton, Combo Box, CheckBox.
if(type=="mx.controls.CheckBox"){
//if(rep.currentIndex<5){
for each(j in x){
k=createNewInstanceOfClass(rep.currentItem.type);
k.id="radioGroup"+rep.currentItem;
k.label=j.linkname;
k.data=j.linkname;
linkPanel[rep.currentIndex].addChild(DisplayObject(k));
}
MXML
<mx:Panel layout="horizontal" id="linkPanel" title="Evaluation" fontWeight="bold" height="100%" backgroundColor="0xFFF7E6"
borderThicknessLeft="0" borderThicknessRight="0" cornerRadius="10" headerHeight="20" dropShadowEnabled="false" roundedBottomCorners="true" verticalScrollPolicy
="off" horizontalScrollPolicy="off" headerColors="[#ffffff,#ffffff]" width="100%">
<mx:Form>
<mx:FormItem paddingLeft="2" paddingTop="2" paddingBottom="2">
<mx:Repeater id="rep2" dataProvider="{sendToActionScript(rep.currentItem.link)}" />
</mx:FormItem>
</mx:Form>
</mx:Panel>
When i click on Submit finally i need to get all the selected Values in each question. All the components are dynamically created at runtime.
You can list the children of linkPanel with getChildren()
when looping through them, read the "selected" property
public function test():void {
for each ( var obj:Object in linkPanel.getChildren()) {
if( obj is RadioButton) {
Alert.show( (obj as RadioButton).selected.toString());
}
}
}
If you are creating a list of radio buttons belonging to a group, look into "selectedValue" for this group
<mx:RadioButtonGroup id="rbg" />
<mx:RadioButton id="answer1" group="{rbg}" label="Answer 1" />
public function test():void {
Alert.show( rbg.selectedValue.toString())
}