tab index on flash movieclip in flex - apache-flex

I have a form that pops up in flex, it is a movieclip contained within a UIComponent. Within this movieclip are form fields.
For some reason I can't get the tab button working to be able to tab between the fields. I set up each field with a tabindex, but that doesn't work.
Is there anything else I need to do besides this? This is basically all the code I am using:
email.tabIndex = 1;
city.tabIndex = 2;
firstName.tabIndex = 3;
etc.
Is this not working because of flex? And if so, what is a workaround?

have you tried adding a new FocusManager instance to the UIComponent that contains the movieclip? I am not sure but maybe.
Also another thing I can think of could be the tabEnabled property of the form elements and the containing Objects.
Hope it gets you closer.
Good luck,
Rob
////////// UPDATE ///////////////
Unfortunately I couldn't make it work, but I send you my code, maybe you can do something with it.
I tried to add a movieclip and the textfields into it, but it's the same, no TAB at all. So I simply added the textfields to the UIComponent and set all the possible tab and focus related properties to true - no luck :(.
<?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">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import flash.display.MovieClip;
import flash.text.TextField;
protected function init(event:Event):void
{
var i:uint = 0;
var l:uint = 4;
while (i < l)
{
var tf:TextField = new TextField();
tf.name = "tf_" + i;
tf.width = 200;
tf.height = 21;
tf.border = true;
tf.type = "input";
tf.tabIndex = i;
tf.tabEnabled = true;
tf.text = "tabIndex = " + String(tf.tabIndex);
tf.x = 50;
tf.y = tf.height * i + 10 * i + 100;
uicomp.addChild(tf);
++i;
}
};
]]>
</fx:Script>
<mx:UIComponent hasFocusableChildren="true" tabChildren="true" tabEnabled="true" tabFocusEnabled="true" id="uicomp" width="100%" height="100%" addedToStage="init(event);" />
</s:Application>
Sorry, that's all I could do for now. If you get the answer please let me know, I am keen.
Cheers,
Rob

Related

FillColor of CheckBox in Flex 3

I have about 8 checkboxes that are created dynamically using a for loop. Each checkbox has a different color. Basically i want to change the fillColor of every checkbox (label not included) using 8 predefined colors. Here's my code.
for (var i:int=0; i <= annotatorNames.length; i++)
{
var checkbox:CheckBox = new CheckBox();
var colorIndex:int = parseInt(annotatorColours[i]) - 1;
var checkboxColor:String = UiConstants.ANNOTATOR_COLORS[colorIndex];
checkbox.label=annotatorNames[i];
checkbox.selected=true;
checkbox.setStyle("fillColors", [checkboxColor, checkboxColor, checkboxColor, checkboxColor]);
annotatorCheckboxes[i] = checkbox;
this.addChild(checkbox);
}
For some reason fillCollors does not apply and the checkbox is not styled. If i style the label it works...also pretty much any other style applies..but not fillColors. What am I doing wrong here?
The code does not have errors and colors are in the form of "0XA52A2A".
Try using a stylesheet, including something like:
CheckBox {
fillColors: #yourColor, #yourColor, #yourColor, #yourColor;
}
import it by the following statement:
<mx:Style source="yourstylesheet.css"/>
You have an issue with pieces of code that aren't in the example, i.e. the constants UiConstants.ANNOTATOR_COLORS[colorIndex]; etc
I trimmed your code to just the bare minimum to research your defect and the setting of the styles works without issue.
The following code works perfectly fine, run this and check it out:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.CheckBox;
private function init() : void {
for (var i:int=0; i <= 8; i++)
{
var checkbox:CheckBox = new CheckBox();
var checkboxColor:String = 'red';
checkbox.label=i.toString();
checkbox.selected=true;
checkbox.setStyle("fillColors", [checkboxColor, checkboxColor, checkboxColor, checkboxColor]);
holder.addChild(checkbox);
}
}
]]>
</mx:Script>
<mx:HBox id="holder"/>
</mx:Application>
That should point you in the right direction...

How can I show a line under each row of text in a Spark TextArea

I'm trying to show a horizontal line under each row of text in a Spark TextArea. I want to give the text area the look of legal paper.
Ah actually ran into a similar problem in Flex 3 doing a strikeout for a disabled link-button that was part of our styles. Just checked out the code and looked on the docs for the spark label and found the function I was using from a mx label explicitly says it won't work [from measureText() in spark label]:
Measures the specified text, assuming that it is displayed in a
single-line UITextField (or UIFTETextField) using a UITextFormat
determined by the styles of this UIComponent. Does not work for Spark
components since they don't use UITextField (or UIFTETextField). To
measure text in Spark components, get the measurements of a
spark.components.Label or spark.components.RichText
So I re-figured it out:
<?xml version="1.0" encoding="utf-8"?>
<s:Label xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
override protected function updateDisplayList(unscaledWidth : Number, unscaledHeight : Number) : void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
drawLines();
}
private function drawLines() : void
{
var totalHeight : Number = 0;
for (var i : int = 0; i < mx_internal::textLines.length; i++)
{
totalHeight = mx_internal::textLines[i].y;
graphics.lineStyle(1, 0x000000);
graphics.moveTo(0, totalHeight);
graphics.lineTo(width, totalHeight);
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Label>
Set the textDecoration style for the control.

Spark TextArea or RichText autosize

I have done lots of searching on this subject, but it seems what I am finding is either out of date or just does not seem to work.
With TextFields in the past, you could set the TextField to a certain width, set wordWrap to true and you would end up with a textfield that changed height according to the text you added.
Now I am trying to do this with either the Spark TextArea or RichText.
I tried this HeightInLines = NAN, but that seems to be out of date.
I also tried this routine:
var totalHeight:uint = 10;
this.validateNow();
var noOfLines:int = this.mx_internal::getTextField().numLines;
for (var i:int = 0; i < noOfLines; i++)
{
var textLineHeight:int =
this.mx_internal::getTextField().getLineMetrics(i).height;
totalHeight += textLineHeight;
}
this.height = totalHeight;
But the mx_internal is not in the Spark components.
I am trying to do this with AS3, not MXML. If anyone has any suggestions or links that could help me figure this out using AS3, I'd really appreciate it.
Been struggling with this all afternoon. But it looks like the RichEditableText component will autosize if you set its width and leave its height undefined.
This works fine:
<?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" minWidth="955" minHeight="600">
<s:TextArea updateComplete="event.currentTarget.heightInLines = NaN" />
</s:Application>
Found in comments here. You can do the same in ActionScript using the same updateComplete event.
This is how I set the height of a TextArea to fit its content when used inside an ItemRenderer (e.g. for a List component):
private function onUpdateComplete( e: Event ): void
{
// autoresize the text area
if ( theText ) {
var actualNumOfLines: int = theText.textFlow.flowComposer.numLines;
theText.heightInLines = actualNumOfLines;
invalidateSize();
}
}
ItemRenderer must have this property set:
<s:ItemRenderer ... updateComplete="onUpdateComplete(event)>
Maybe the updateComplete event is not the optimal trigger for auto-resize actions but works fine for me.
You can remove scrollers from TextArea's skin and it becomes autoresizable. You can download completed skin here: http://www.yumasoft.com/node/126
Here's a solution for spark text areas (it works as mx text areas do):
var ta_height:int;
for(var i:int=0; i < StyleableTextField(myTextArea.textDisplay).numLines; i++) {
ta_height += StyleableTextField(myTextArea.textDisplay).getLineMetrics(i).height;
}
myTextArea.height = ta_height;
This seems to work for me:
<s:TextArea id="testTextArea"
change="testTextArea_changeHandler(event)"
updateComplete="testTextArea_updateCompleteHandler(event)"/>
<fx:Script>
<![CDATA[
protected function testTextArea_changeHandler(event:TextOperationEvent):void
{
testTextArea.height = RichEditableText(testTextArea.textDisplay).contentHeight + 2;
}
protected function testTextArea_updateCompleteHandler(event:FlexEvent):void
{
testTextArea.height = RichEditableText(testTextArea.textDisplay).contentHeight + 2;
}
]]>
</fx:Script>
Been doing the same head banging over that s:TextArea, and then found out that this gets the job done :
<s:RichEditableText id="txtArea" left="0" right="0" backgroundColor="#F7F2F2"
change="textChanged()" />

Why wont this move effect work on my sprites when the fade effect does?

Could someone please explain why this doesn't want to work? It's a bit of decoration to go behind a logo.
When the dMove var is commented out I get the appropriate line of squares fading in and out at random spots along the x = 78 axis, but when introduced nothing appears at all...
private var floatBG:UIComponent = new UIComponent();
private function addDP(event:TimerEvent):void{
var dY:Number = 5+Math.ceil(Math.random()*60);
var dSize:Number = Math.ceil(Math.random()*12);
var dAlpha:Number = Math.random()*0.5 + 0.2
var dDuration:Number = Math.ceil(Math.random()*5000) + 1000;
var d:Sprite = new Sprite();
d.graphics.beginFill(0x1C75BC,dAlpha);
d.graphics.drawRect(78, dY, dSize,dSize);
d.graphics.endFill();
floatBG.addChild(d);
var dMove:Move = new Move(d);
dMove.xBy = 300;
dMove.duration = dDuration;
dMove.play();
var dFade:Fade = new Fade(d);
dFade.alphaFrom = 1;
dFade.alphaTo = 0;
dFade.duration = dDuration;
dFade.play();
this.addElement(floatBG);
}
Also, what would be the best/correct method for destroying the sprites at the end of each cycle?
Thanks a lot in advance, massively appreciate it!
Josh
Ok, so after a bit of playing around with it I managed to find a solution, I really appreciated Brian Bishop's help, who managed to very much point me in the right direction.
As Brian suggested, simply entering d as a UIComponent rather a sprite allowed the dMove to effect (I'm still not sure why this is, as the dFade effect worked when it was still a sprite). However adding the floatBG (BG being background, the UIComponent to which all the d UIComponents are added) each time was unnecessary, so I made this.addElement(floatBG) part of my creationComplete function
I then ran into the issue that the application began to fill with the d instances (d originally stood for "datapoint" by the way, which was kind of the theme of the effect which I was trying to create, a plume of them), and progressively slowed the application to a crawl. To continuously add d elements is necessary as it's part of the logo that sits in the corner of the screen looking as pretty as I can make it...
Eventually I came to the below solution, the crux of it was to load floatBG with 600 dummy UIComponents, and then with each cycle of the addDP function both add a moving d UIComponent to floatBG and remove another UIComponent off of the total array of children which it contains.
Thus, in the end it looked something like this:
<?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" creationComplete="init(event)">
<fx:Script>
<![CDATA[
import mx.core.DesignLayer;
import mx.core.UIComponent;
import mx.effects.effectClasses.MoveInstance;
import mx.events.EffectEvent;
import mx.events.FlexEvent;
import mx.states.RemoveChild;
import spark.effects.AnimateColor;
import spark.effects.AnimateFilter;
import spark.effects.Fade;
import spark.effects.Move;
import spark.effects.Rotate;
import spark.effects.easing.Sine;
private var floatBG:UIComponent = new UIComponent;
private var floatColour:uint = 0x1C75BC
protected function init(event:FlexEvent):void
{
//Float BackGround set up
floatBG.mask = floatMaskBlock;
floatBG.depth = -1;
this.addElement(floatBG);
//Fill FloatBG with 600 filler elements
for(var i:int=0; i<600; i++)
{
var filler:UIComponent = new UIComponent;
floatBG.addChild(filler);
}
//Float Animation Timer
var floatTimer:Timer = new Timer(1,0);
floatTimer.addEventListener(TimerEvent.TIMER,DPstartup)
floatTimer.start();
private function DPstartup(event:TimerEvent):void
{
this.addDP(5,60)
this.addDP(22,14);
this.addDP(18,18);
}
private function addDP(yf:Number,yt:Number):void
{
this.title.text = floatBG.numChildren.toString();
var dY:Number = yf+Math.ceil(Math.random()*yt);
var dXby:Number = Math.ceil(Math.random()*1000 + 50);
var dSize:Number = Math.ceil(Math.random()*12);
var dAlpha:Number = Math.random()*0.5 + 0.2
var dMotionDuration:Number = Math.ceil(Math.random()*15000) + 1000;
var dFadeDuration:Number = Math.random()*dMotionDuration;
var d:UIComponent = new UIComponent;
d.graphics.beginFill(floatColour,dAlpha);
d.graphics.drawRect(78, dY, dSize,dSize);
d.graphics.endFill();
var dMove:Move = new Move(d);
dMove.xBy = dXby;
dMove.duration = dMotionDuration;
dMove.easer = Linear;
dMove.play();
var dFade:Fade = new Fade(d);
dFade.alphaFrom = dAlpha;
dFade.alphaTo = 0;
dFade.duration = dFadeDuration;
dFade.play();
floatBG.addChild(d);
floatBG.removeChildAt(0);
};
]]>
</fx:Script>
<fx:Declarations>
<s:Sine id="Sine"/>
<s:Bounce id="Bounce"/>
<s:Linear id="Linear"/>
</fx:Declarations>
<s:Group x="88" width="1000" height="80" id="floatMaskBlock">
<s:Rect width="100%" height="100%">
<s:fill>
<s:SolidColor color="0xffffff"/>
</s:fill>
</s:Rect>
</s:Group></s:Group>
Ok, apologies if that was pretty long-winded, but someone may find it useful... it's a nice effect (I think so anyway)
I use the mask to give a sharp edge to the point at which the d elements appear. Alternatively one could just place it behind another object, but if, as in my case, the object is a line of width less than the size of some of the d elements, such a mask is necessary.
The colour is declared as a variable at the beginning as I'll likely add a function to change it on click, or something similar.
Thanks!
Josh
I ran this in Flex 4, only change I made was to use a UIComponent instead of a spirte, which works fine. Maybe your using pure AS3 project though? Not sure about destroying after they play.
<?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" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.effects.Fade;
import mx.effects.Move;
private var floatBG:UIComponent = new UIComponent();
private function addDP(event:TimerEvent):void{
var dY:Number = 5+Math.ceil(Math.random()*60);
var dSize:Number = Math.ceil(Math.random()*12);
var dAlpha:Number = Math.random()*0.5 + 0.2
var dDuration:Number = Math.ceil(Math.random()*5000) + 1000;
var d:UIComponent = new UIComponent();
d.graphics.beginFill(0x1C75BC,dAlpha);
d.graphics.drawRect(78, dY, dSize,dSize);
d.graphics.endFill();
floatBG.addChild(d);
var dMove:Move = new Move(d);
dMove.xBy = 300;
dMove.duration = dDuration;
dMove.play();
var dFade:Fade = new Fade(d);
dFade.alphaFrom = 1;
dFade.alphaTo = 0;
dFade.duration = dDuration;
dFade.play();
this.addElement(floatBG);
}
private function onClick():void{
var t:Timer = new Timer(100, 10);
t.start();
t.addEventListener(TimerEvent.TIMER, addDP);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button click="onClick()" />
</s:Application>

Is there a way to show the errorTip (error ToolTip) to the left of the target?

I'm creating an errorTip that gets displayed when the user mouses over an image. I would like the popup to appear to the left of the image, but the only properties I can pass to create the toolTip are "errorTipRight", "errorTipAbove" and "errorTipBelow".
Any thoughts?
Sample code:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
[Embed(source="assets/some_image.png")]
[Bindable]
private var myIcon:Class;
private var myToolTip:ToolTip;
private function showToolTip(evt:MouseEvent, text:String):void
{
var pt:Point = new Point(evt.currentTarget.x, evt.currentTarget.y);
pt = evt.currentTarget.parent.contentToGlobal(pt);
// I WANT TO POP THE ERRORTIP UP TO THE LEFT HERE INSTEAD OF ABOVE.
myToolTip = ToolTipManager.createToolTip(text, pt.x, pt.y, "errorTipAbove") as ToolTip;
var yOffset:int = myToolTip.height + 5;
myToolTip.y -= yOffset;
}
// Remove the tooltip
private function killToolTip():void
{
ToolTipManager.destroyToolTip(myToolTip);
}
]]>
</fx:Script>
<mx:Image source="{myIcon}" mouseOver="showToolTip(event, 'My ToolTip Message Goes Here')" mouseOut="killToolTip()" />
</mx:HBox>
You'll need to create a replacement for the ToolTipBorder class and assign that as the skin for your ToolTip. I would do this by copying the ToolTipBorder source and modifying the updateDisplayList and borderMetrics methods to include a new "errorTipLeft" style to the switch statements in those methods. Then assign that skin class to the ToolTip class in CSS. Hope that helps.
Why can't you subtract the width of the tooltip from the pt.x when you give the coordinates to the ToolTipManager?
myToolTip = ToolTipManager.createToolTip(text, (pt.x - somewidth), pt.y, "errorTipAbove") as ToolTip;

Resources