Make Flex Plot Chart items toggled to show/hide item's label - apache-flex

I made an application for generating a plot chart based on previously calculated data (X,Y). After plotting the data on the chart, I tried to make the items (dots) to show a label (through addChild an external custom label component) when a user click on the dots (for example: if a user click on a chart item, the corresponding ID number will show beside the dot).
Although everything works fine, I can't make the items toggled (for example: if a dot is already clicked and label ID is visible, on next click on the same dot I want to hide (removeChild) the label component which corresponds to that item)... A simple example code of what I did so far is attached:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="417" height="468" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]">
<mx:Script><![CDATA[
import mx.charts.events.ChartItemEvent;
import mx.charts.HitData;
import mx.collections.ArrayCollection;
[Bindable]
public var ARR:ArrayCollection = new ArrayCollection([
{ID:1, Y:2000, X:1500},
{ID:2, Y:1000, X:200},
{ID:3, Y:1500, X:500},
{ID:4, Y:500, X:300},
{ID:5, Y:1000, X:450},
{ID:6, Y:2000, X:500}
]);
private function labels_plot1(plot:String, dotIndex:int, labelID:String):void {
var ID_lab:ID_label = new ID_label();
if(this[plot].series[0] == ID_lab.parent){
this[plot].series[0].removeChild(ID_lab);
}else{
this[plot].series[0].addChild(ID_lab);
ID_lab.x = this[plot].series[0].getChildAt(dotIndex).x + 8;
ID_lab.y = this[plot].series[0].getChildAt(dotIndex).y + 1.2;
ID_lab.ID_txt.htmlText = "<B>" + labelID + "</B>";
}
}
private function dotClickEvent(event:ChartItemEvent):void{
labels_plot1(event.currentTarget.id, event.hitData.chartItem.index, event.hitData.item.ID);
}
]]></mx:Script>
<mx:PlotChart id="myChart" dataProvider="{ARR}" itemClick="dotClickEvent(event)">
<mx:series>
<mx:PlotSeries id="pl"
xField="X"
yField="Y"
displayName="Plot 1"
/>
</mx:series>
<mx:annotationElements>
<mx:CartesianDataCanvas id="canvas" includeInRanges="true"/>
</mx:annotationElements>
</mx:PlotChart>
</mx:WindowedApplication>
I tried almost everything, but with no success... How to solve this problem?

The first check in your function could not be true, that is why the children are not removed. First of all you should not create a new label before you have got to know either or not you need a new one.
In your case I would use the property name of a component to save the dotIndex there. The dotIndex is uniq, so you can check anytime if the label exists by using the function getChildByName(dotIndex.toString()).
I also prefer to add new Labels direct into a separate container or in our case into the application itself. Here is something you can try to do:
private function labels_plot1(plot:String, dotIndex:int, labelID:String):void {
var dispObj:DisplayObject = this.getChildByName(dotIndex.toString());
if (dispObj != null)
{
this.removeChild(dispObj);
}
else
{
var ID_lab:Label = new Label();
ID_lab.x = this[plot].series[0].getChildAt(dotIndex).x + 8 + 60;
ID_lab.y = this[plot].series[0].getChildAt(dotIndex).y + 1.2 + 4;
ID_lab.text = labelID;
ID_lab.name = dotIndex.toString();
this.addChild(ID_lab);
}
}
I don't have your component ID_Label, so I have used a normal Label here.

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...

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()" />

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;

tab index on flash movieclip in 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

detect the size of swf. flex/as3

I'm creating a map that has points of interest. (POI) When a user mouses over the POI an info bubble pops onto the screen and it loads an swf. I currently have 3 problems. My 4th problem is that this is due Monday 21st! so any help would be greatly appreciated!
I can't detect the size of the swf so that my infobubble will size itself to the size of the swf.
When I mouse over my swf file, it disappears.
I would love to have the my swf file pop up in a layer on its own instead of being on the stage of my main flex file...but i have no clue how to do this.
package com.modestmaps
{
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.text.TextField;
public class InfoBubble extends Sprite
{
public var textField:TextField;
public var background:Shape;
public var shadow:Shape;
public function InfoBubble(text:String)
{
//I name the instance of my POI marker on my map to the url link of my swf file. So whatever marker i click on the correct url will
this.name = urlLink;
this.mouseEnabled = true;
this.mouseChildren = false;
//this creates a shadow behind my infobubble
shadow = new Shape();
shadow.filters = [ new BlurFilter(16, 16) ];
shadow.transform.matrix = new Matrix(1, 0, -0.5, 0.5, 0, 0);
addChild(shadow);
background = new Shape();
addChild(background);
textField = new TextField();
textField.selectable = true;
textField.multiline = true;
textField.wordWrap = true;
//textField.text = urlLink;
textField.width = textField.textWidth+300;
textField.height = textField.textHeight+288;
//addChild(textField);
var request:URLRequest = new URLRequest(urlLink);
var loader:Loader = new Loader();
loader.load(request);
addChild(loader);
//marker clips are positioned with (0,0) at the given location
//current measurements of swf file w432 h288
//if i could dynamically determine the size of the loaded swf file its position would be automatically calculated
loader.y = -288 - 37;
loader.x = -8;
//marker clips are positioned with (0,0) at the given location
textField.y = -textField.height - 35;
textField.x = -10;
//currently my rectangle's size is determined by the textField size. I don't even use the textfield. I want the rectangle to be drawn using the dimensions of the swf file instead.
var rect:Rectangle = textField.getRect(this);
// get your graph paper ready, here's a "speech bubble"
background.graphics.beginFill(0x12345);
shadow.graphics.beginFill(0x000000);
for each (var g:Graphics in [ background.graphics, shadow.graphics ] ) {
g.moveTo(rect.left, rect.top);
g.lineTo(rect.right, rect.top);
g.lineTo(rect.right, rect.bottom);
g.lineTo(rect.left+15, rect.bottom);
g.lineTo(rect.left+10, rect.bottom+15);
g.lineTo(rect.left+5, rect.bottom);
g.lineTo(rect.left, rect.bottom);
g.lineTo(rect.left, rect.top);
g.endFill();
}
}
}
}
I hope you more skilled coders can help me out. I'm new to flex and as3
Edit: There is no javascript in this file. All of it is AS3.
Edit2: This is the temporary site I am testing it on http://cjbutchershop.com/temp/adtypes/mapTest.swf
You can get the size of your application by doing:
var width:int = Application.application.width;
var height:int = Application.application.height;
With regards to the text disappearing when you hover over the info bubble; you might want to reconsider your approach. Rather than loading an external swf, I have implemented info bubbles for modest maps by adding/removing child objects (like a TextField) to my marker object (which extends Sprite) in response to the appropriate mouse events.
I am new to Flex myself, but i have done something similar while trying out an example while learning.
Basically what i suggest is Open the bubble in a new popup window using the PopUpManager class on MouseOver event on the parent window (on your map).
And show the popup in a TitleWindow Component,also tap the close event on Title window component.That way you will come back to the same page.Hope this helps.
Posting code here
< ? xml version="1.0" encoding="utf-8" ? >
< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
[Bindable]
public var photoFeed:ArrayCollection;
public function searchFlickr():void {
photoService.cancel();
var params:Object = new Object();
params.format = 'rss_200_enc';
params.tags = srchTxtId.text;
photoService.send(params);
}
public function resultHandler(event:ResultEvent):void {
photoFeed = event.result.rss.channel.item as ArrayCollection;
}
public function openPanel(levent:ListEvent):void {
var panelCmpObj:panelcomp = new panelcomp();
panelCmpObj.source = levent.itemRenderer.data.content.url;
PopUpManager.addPopUp(panelCmpObj,this,true);
}
public function test():void {
Alert.show('testtest');
}
]]>
</mx:Script>
<mx:HTTPService id="photoService" url="http://api.flickr.com/services/feeds/photos_public.gne" result="resultHandler(event)"/>
<mx:HBox width="362" height="24">
<mx:TextInput id="srchTxtId"/>
<mx:Button label="Search for pics" id="srchBtnId" click="searchFlickr()"/>
</mx:HBox>
<mx:TileList id="imgTileList" dataProvider="{photoFeed}" width="100%" height="100%" itemClick="openPanel(event)">
<mx:itemRenderer>
<mx:Component>
<mx:VBox width="125" height="125"
paddingBottom="5"
paddingLeft="5"
paddingTop="5"
paddingRight="5">
<mx:Image width="75" height="75" source="{data.thumbnail.url}"/>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:TileList>
CODE FOR THE COMPONENT shown on PopUP
< ? xml version="1.0" encoding="utf-8" ? >
< mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
showCloseButton="true"
styleName="noPadding"
creationComplete="init();"
close="titleWindow_close(event);" >
< ![CDATA[
import mx.managers.IFocusManagerComponent;
import mx.controls.Alert;
import mx.core.IFlexDisplayObject;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
[Bindable]
public var source:String;
private function init():void {
PopUpManager.centerPopUp(this);
}
private function titleWindow_close(evt:CloseEvent):void {
PopUpManager.removePopUp(evt.target as IFlexDisplayObject);
}
]] >
< /mx:Script>
< mx:Image width="379" height="261" id="imgId" source="{source}"/>
<mx:ControlBar horizontalAlign="right" width="100%">
</ mx:ControlBar>
< /mx:TitleWindow >
"So you are trying to get the application size from within the info bubble swf? Why is the info bubble in a separate swf? If you have the info bubble source code, I suggest adding it into your map application and directly instantiate the info bubble object. – elevine 2 hours ago"
I have three different type of infoBubbles (only static bubble is shown). Some of my info bubbles have moving content. I am not looking for the application size of the external swf in the bubble, i am looking for the physical size. The height and width of the external swf that is populating the bubble. If I knew the height and width, I can have the infobubble match the height and width. Right now I have the info bubble hardcoded to the size of the current info bubble; however, i will have different sizes of info bubbles swf files.

Resources