Programming, Technology, Web Development, Whatever
Posts tagged Flex
Disable DataTip targets in Flex charts
May 13th
After working on my new data visualization project at Grooveshark, I’ve been looking for a way to remove the DataTip “targets”, which I have considered calling “points”, “dots”, and “circles” in my search to turn these little things off.
In case you don’t know what they are, here’s a picture:

After trudging through the Flex SDK source code, turns out its a simple style setting for the ChartBase class. Now I feel silly…
var myChart:ColumnChart = new ColumnChart();
myChart.setStyle("showDataTipTargets",false);
or in MXML
<mx:ColumnChart showDataTipTargets="false"/>
Integer Division In Flex/Actionscript
Jan 18th
If you’re used to C and other elemental high level programming languages, you know that 5÷9 = 0 and 10÷7 = 1. ActionScript being higher level than C automatically coerces the quotient of two numbers to the Number class, producing a decimal. To get the correct integer quotient, use the Math.floor function, which drops the decimal.
//This produces 4 var integer:int = Math.floor(14/3);
Intro to Try/Catch in Flex/Actionscript
Jan 15th
Sometimes when you’re making a Flex application, you’ll expect a certain piece of code to fail at some point. This is the job of try and catch. For example, say I wanted to loop over a bunch of components I had within an HBox:
<mx:HBox id="myHBox"> <mx:Panel title="1"/> <mx:Panel title="2"/> <mx:Panel title="3"/> <mx:Panel title="4"/> <mx:Panel title="5"/> <mx:Panel title="6"/> <mx:Panel title="7"/> </mx:HBox>
To loop over these panels without setting a specific id for each, we can use the DisplayObject‘s getChildAt() function. So within the
private function averageTitles(box:HBox):Number
{
// initialize some variables
var tempTotal:int = 0;
var i:int = 0;
var length:int = 0;
var isEnd:Boolean = false;
var tempPanel:Panel;
//loop until the isEnd variable is true
while(!isEnd)
{
//Try to get the child at location i
try
{
tempPanel = box.getChildAt(i);
tempTotal += parseInt(tempPanel.title);
i++;
}
//if it fails, we have reached the end of the panels
catch(e:Error)
{
isEnd = true;
}
//we always want to increase the length,
//since the length is longer than the index
finally
{
length++;
}
}
//return the average
return tempTotal / length;
}
(Obviously the length is unnecessary, Its just an example)
The try block is what the program will attempt to execute first, and the code you expect to fail. In this example, the myHBox.getChildAt(i) is undoubtedly going to fail at some point when the HBox runs out of panels. When this happens, the program will throw an error, more specifically a RangeError, meaning you’re attempting to access something outside the array’s bounds. The catch block will quite literally “catch” the error before it escapes to the main application and causes a runtime error(the window that pops up when something goes wrong in a flash movie in your browser). The catch block will then execute the code within its block. A catch block can catch many kinds of errors; in my example I use the error type Error, meaning it will catch all errors. Since I know what kind of error will occur in my code, I could have just as easily written:
catch(e:RangeError)
{
isEnd = true;
}
And the effect would be the same. You can also catch multiple types of errors within a try block using multiple catch statements where appropriate.
For a list of all types of errors, look at the Subclasses of the Error class in the Adobe Flex Language Reference.
You may also have noticed the finally block which increments the var length. The finally block is used to execute code regardless of when an error happens. So in the finally block in my code:
finally
{
length++;
}
The length will always be incremented if there is an error or not, as we need the total number of items to find the average.
That’s basically it, I’ll write a more advanced tutorial later on things like throwing new errors and such. Good luck in your coding endeavors.
Access Specifiers in Flex/Actionscript
Dec 9th
There are four types of basic access in Flex:
| Access | Description |
|---|---|
| public | All objects and classes can access |
| private | Only objects with the same class can access |
| protected | Only objects with the same class or derived classes |
| internal | Only objects in the same package(essentially the same directory in flex) |
There are custom namespaces and other operators that exist to to limit access, but these are the basics that you’ll use the most.
Flex Auto-Resizing Datagrid
Dec 9th
If you’ve ever wanted to make a datagrid that re-sizes to fit its content, heres how…
Make a function that computes the size necessary to accommodate all the data:
private function datagridChange():void
{
var newHeight:int = sampleDG.rowHeight * sampleDG.dataProvider.length
//this is for the column headers, and the extra empty row
+ 2*sampleDG.rowHeight;
sampleDG.height = newHeight;
}
Flex automatically adds an empty row at the end of the datagrid, which accounts for the addition of two extra rows(the other coming from the column headers). You can get around this by setting the datagrid’s verticalScrollPolicy to “off”, then change the extra row addition back to one:
<mx:DataGrid id="sampleDG" verticalScrollPolicy="off">
private function datagridChange():void
{
var newHeight:int = sampleDG.rowHeight * sampleDG.dataProvider.length
//just for the column headers now
+ sampleDG.rowHeight;
sampleDG.height = newHeight;
}
Finally add that function to the dataChange event property of the datagrid.
<mx:DataGrid id="sampleDG" dataChange="datagridChange();" verticalScrollPolicy="off">
In the case where you have a pre-determined dataProvider for the datagrid, you may also want to add the function to the creationComplete event as well.
Working with Events and Popups in Flex
Dec 7th
Problem:
If you’re like me in flex, you use a lot of popups. If you’re also like me, you constantly rely on event propagation. Unfortunately due to the nature of Flex, popups can be a tricky beast. When you create a popup using the PopUpManager class, it looks a little something like this:
private function createPopup():void
{
var popup:IFlexDisplayObject;
popup = PopUpManager.createPopUp(this,components.aSimplePopup,true);
PopUpManager.centerPopUp(popup);
}
Now, the problem with this is that its setting this as the parent DisplayObject doesn’t allow you to perfectly center the popup. A simple fix is to set the popup’s parent to the Application.application Object and explicitly coercing it to a DisplayObject.
private function createPopup():void
{
var popup:IFlexDisplayObject;
popup = PopUpManager.createPopUp(Application.application as DisplayObject,
components.aSimplePopup,true);
PopUpManager.centerPopUp(popup);
}
However this creates another problem. This breaks Flex’s natural event propagation for both the Capturing and Bubbling phases. While the natural thing to do would be to change the popups parent property after it’s centered, however the property becomes read-only after the constructor is called.
Solution:
While there are a few solutions to this problem, heres the one that works the best for me.
Create a new public DisplayObject variable in the popup you wish to use, I called mine myParentObject.
public var myParentObject:DisplayObject;
Now assign that object to this in the creating component.
private function createPopup():void
{
var popup:IFlexDisplayObject;
popup = PopUpManager.createPopUp(Application.application,components.aSimplePopup,true);
PopUpManager.centerPopUp(popup);
popup["myParentObject"] = this;
}
Now whenever we need to send an event back to the creating component, we simply dispatch an event to the myParentObject.
//This is a function in the popup itself
private function closePopup():void
{
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE,true);
myParentObject.dispatchEvent(closeEvent);
}
Or if you want you can reroute all the events of a specific type using an event listener:
//This is a function in the popup itself
private function init():void
{
addEventListener(MouseEvent.CLICK,clickEventHandler);
}
private function clickEventHandler(event:MouseEvent):void
{
myParentObject.dispatchEvent(event);
}