Friday, September 28, 2012

Flex: Simple Chart Animation

I was playing with the column charts, a bit of styling, animation, etc... And all of us out there love animations and beautiful stuff therefore here you go. XD

The main source file - SimpleChartAnimation.mxml
<?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"
      backgroundColor="#CDCDCD"
      creationComplete="creationCompleteEvent(event)"> 
 <fx:Declarations>
  <s:RadioButtonGroup change="animateChangeEvent(event)" 
       id="rdoGrpAnimate"/>
  <!-- 
   We need to specify the types of animations over here
   1) For parallel animations, meaning all the effects
      will be executed together.
   2) For sequence animations, the effects will be running
      one by one.
  -->
  <s:Parallel id="parallelEffect">
   <s:Fade duration="1000" alphaFrom="0" alphaTo="1"/>
   <mx:SeriesSlide duration="1000" direction="up"/>
  </s:Parallel>
  <s:Sequence id="sequenceEffect">
   <mx:SeriesSlide duration="500" direction="up"/>
   <s:Fade duration="500" alphaFrom="0.5" alphaTo="1"/>
  </s:Sequence>
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.conversion.TextConverter;
   
   import mx.charts.HitData;
   import mx.charts.chartClasses.IChartElement2;
   import mx.charts.series.ColumnSeries;
   import mx.collections.ArrayCollection;
   import mx.collections.Sort;
   import mx.collections.SortField;
   import mx.events.FlexEvent;
   import mx.formatters.DateFormatter;
   import mx.graphics.Stroke;
   
   import spark.events.IndexChangeEvent;
   
   //Records used in the chart
   [Bindable]
   private var myData:XML = 
    <records> 
     <record>
      <date>01/09/2013</date>
      <people>63</people>
     </record>
     <record>
      <date>02/09/2013</date>
      <people>61</people>
     </record>
     <record>
      <date>03/09/2013</date>
      <people>67</people>
     </record>
     <record>
      <date>04/09/2013</date>
      <people>75</people>
     </record>
     <record>
      <date>05/09/2013</date>
      <people>65</people>
     </record>
     <record>
      <date>06/09/2013</date>
      <people>32</people>
     </record>
     <record>
      <date>07/09/2013</date>
      <people>66</people>
     </record>
     <record>
      <date>08/09/2013</date>
      <people>85</people>
     </record>
     <record>
      <date>09/09/2013</date>
      <people>37</people>
     </record>
     <record>
      <date>10/09/2013</date>
      <people>80</people>
     </record>
    </records>;
   
   private var localSeries:ColumnSeries = new ColumnSeries();
   private var firstRun:Boolean = false;
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    // Parsing the xml data into ArrayCollection
    var objArray:ArrayCollection = new ArrayCollection();
    var tempObj:Object;
    var dateArray:Array;
    var tempDate:Date;
    for(var i:int = 0; i < myData.record.length(); i ++)
    {
     tempObj = new Object();
     dateArray = String(myData.record[i].date).split("/");
     //Convert the date data into a Date Object
     tempDate = new Date(dateArray[2], 
      Number(dateArray[1]) - 1, 
      dateArray[0]);
     tempObj.date = tempDate;
     tempObj.time = tempDate.time;
     tempObj.people = myData.record[i].people;
     tempObj.label = dateFormatter(tempDate);
     objArray.addItem(tempObj);
    }
    
    //Create the SortField object for the "time" field in 
    //the ArrayCollection object, and make sure we do a 
    //numeric sort.
    var dataSortField:SortField = new SortField();
    dataSortField.name = "time";
    dataSortField.numeric = true;
    
    //Create the Sort object and add the SortField object 
    //created earlier to the array of fields to sort on.
    var numericDataSort:Sort = new Sort();
    numericDataSort.fields = [dataSortField];
    
    objArray.sort = numericDataSort;
    objArray.refresh();
    
    //Create the new series and set its properties.
    localSeries.dataProvider = objArray;
    localSeries.yField = "people";
    localSeries.xField = "date";
    //Create alternate colors for the columns
    localSeries.setStyle("fills", [0xCDFFCD, 0xCDCDFF]);
    //Create the strokes for the columns
    localSeries.setStyle("stroke", 
     new Stroke(0xFFFFFF, 0.1, 0.5));

    //Animation the Column Charts
    animateChangeEvent(null);
   }
   
   //This function will return a string based on the
   //Date format DD/MM/YYYY.
   private function dateFormatter(tempDate:Date):String
   {
    var fmt:DateFormatter = new DateFormatter();
    fmt.formatString = "DD/MM/YYYY";
    return fmt.format(tempDate);
   }
   
   //We are customizing the datatip / tool tip of the
   //chart data.
   public function myDataTipFunction(e:HitData):String {
    var s:String = "";
    var tempDate:Date = e.item.date as Date;
    s += "Date: " + dateFormatter(tempDate) + "<br>";
    s += "No. of People: " + e.item.people;
    return s;
   }
   
   //This function will be used to change the date labels of
   //the chart to match the data.
   public function createDate(s:Date):Date {    
    var newDate:Date = new Date();
    newDate.time = s.time;
    //We need to increase a day to the labels.
    newDate.date += 1;
    return newDate;
   }  
   
   protected function animateChangeEvent(event:Event):void
   {
    //We will remove all the series attach to the chart
    //first
    columnChart.series = null;
    
    //End all the effects first, else some glich will
    //appear.
    parallelEffect.end();
    sequenceEffect.end();
    
    //Base on the type of animation selected, attach 
    //the effect to the column
    if(rdoGrpAnimate.selectedValue == "parallel")
    {
     localSeries.alpha = 0;
     if(!firstRun)
     {
      localSeries.setStyle("creationCompleteEffect", 
       parallelEffect);
     }else{
      localSeries.setStyle("addedEffect", 
       parallelEffect);
     }
    }else{
     localSeries.alpha = 0.5;
     if(!firstRun)
     {
      localSeries.setStyle("creationCompleteEffect", 
       sequenceEffect);
     }else{
      localSeries.setStyle("addedEffect", 
       sequenceEffect);
     }
    }
    
    firstRun = true;
    
    // Back up the current series on the chart.
    var currentSeries:Array = columnChart.series;
    // Add the new series to the current Array of series.
    currentSeries.push(localSeries);
    // Add the new Array of series to the chart.
    columnChart.series = currentSeries;
   } 
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%"
     verticalAlign="middle"
     horizontalAlign="center">
  <s:BorderContainer width="100%"
         backgroundAlpha="0"
         borderVisible="false">
   <s:HGroup verticalAlign="middle" horizontalAlign="center"
       width="100%"
       height="100%">
    <!-- Need to set the gutterLeft and 
    gutterTop of the chart -->
    <mx:ColumnChart id="columnChart"
         gutterTop="0"
         gutterLeft="50"
         showDataTips="true" 
         width="80%"
         height="80%"
         dataTipFunction="myDataTipFunction">
     <mx:horizontalAxis>
      <mx:DateTimeAxis dataUnits="days" id="dateAxis" 
           alignLabelsToUnits="false" 
           parseFunction="createDate"/> 
     </mx:horizontalAxis>
    </mx:ColumnChart>
   </s:HGroup>
  </s:BorderContainer>
  <s:HGroup width="100%" horizontalAlign="center" 
      verticalAlign="middle">
   <s:VGroup gap="0">
    <s:Spacer height="4"/>
    <s:Label text="Show Column Animation:"/>
   </s:VGroup>
   <s:RadioButton value="parallel"
         group="{rdoGrpAnimate}"
         selected="true"
         label="Parallel Animation"/>
   <s:RadioButton value="sequence"
         group="{rdoGrpAnimate}"
         label="Sequence Animation"/>
  </s:HGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, September 21, 2012

FB + Adobe AIR: Logout Bug

A question was thrown at me the other day, regarding the issue of successfully logging out of FB on a Adobe AIR application. It seems that the Facebook Graph Desktop API has a bug. If a user has successfully log in to FB through the Adobe AIR application, the username and the password will be stored somewhere. Even after the user has log out of FB, the username and the password isn't cleared by the application and when another user tries to log in through the same application on the same machine, rather than prompting the user to enter his username and password, the application will log in automatically using the last set of username and password that are working perfectly. After spending a bit of time playing with it, I managed to find a workaround for this bug.

Rather than doing the following,
 //Rather than using the logout function of the API,
 //you need to add some more codes to it.
 FacebookDesktop.logout(handleLogout, APP_ORIGIN);

You need to add a few more lines to log out properly.
 /*
  All the following liners are required to logout successfully.
 */
 var uri:String = APP_ORIGIN;
 var params:URLVariables = new URLVariables();
 params.next = uri;
 params.access_token = FacebookDesktop.getSession().accessToken;
     
 var req:URLRequest = new URLRequest("https://www.facebook.com/logout.php");
 req.method = URLRequestMethod.GET;
 req.data = params;
     
 var netLoader:URLLoader = new URLLoader();
 netLoader.load(req);
     
 FacebookDesktop.logout(handleLogout, APP_ORIGIN);
* Click here to play with the Adobe AIR application.
^ Click here to take a look at the source files that I'm playing with.
~ Click here to find out more about the Facebook Graph Desktop API.

Sunday, September 16, 2012

Flash: Playing with Tabbing Sequence

You have created a simple form and rather than left to right, you wanted to change the tab sequence a bit, but how to do that?

Source code of the main application file - SimpleTabSequence.mxml
<?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="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   /*
    When the laste checkbox has been selected, we
    will change the tab sequence from top to bottom,
    else it will be bottom to top. 
   */
   protected function rdoChangeHandler(event:Event):void
   {
    if(chk1.selected)
    {
     setupSeq();
    }else{
     setupSeq(false);
    }
   }
   
   // Upon CreationComplete, setup the tab sequence from 
   // top to bottom.
   protected function creationCompleteEvent(e:FlexEvent):void
   {
    setupSeq();
   }
   
   /*
    Most of the work will be done here. It will assign 
    the tabIndex of all the components and it will also
    remove one of the checkbox from the tab sequence
    upon selection.
   */
   private function setupSeq(isTopdown:Boolean = true):void
   {
    if(isTopdown)
    {
     txtTxt0.tabIndex = 1;
     txtTxt1.tabIndex = 2;
     btn0.tabIndex = 3;
     txtTxt2.tabIndex = 4;
     btn1.tabIndex = 5;
     if(!chk0.selected)
     {
      chk0.tabIndex = 6;
      chk1.tabIndex = 7;
     }else{
      chk1.tabIndex = 6;
     }
    }else{
     if(!chk0.selected)
     {
      txtTxt0.tabIndex = 7;
      txtTxt1.tabIndex = 6;
      btn0.tabIndex = 5;
      txtTxt2.tabIndex = 4;
      btn1.tabIndex = 3;
      chk0.tabIndex = 2;
     }else{
      txtTxt0.tabIndex = 6;
      txtTxt1.tabIndex = 5;
      btn0.tabIndex = 4;
      txtTxt2.tabIndex = 3;
      btn1.tabIndex = 2;
     }
     chk1.tabIndex = 1;
    }
    chk0.tabFocusEnabled = !chk0.selected;
    lblTxt0.text = "Textfield(" + txtTxt0.tabIndex + ")";
    lblTxt1.text = "Textfield(" + txtTxt1.tabIndex + ")";
    btn0.label = "Does Nothing(" + btn0.tabIndex + ")";
    lblTxt2.text = "Textfield(" + txtTxt2.tabIndex + ")";
    btn1.label = "Not going to do anything(" + 
     btn1.tabIndex + ")";
    if(!chk0.selected)
    {
     chk0.label = "Checking will remove this " +
      "from tabbing(" + chk0.tabIndex + ")";
    }else{
     chk0.label = "Checking will remove this " +
      "from tabbing";
    }
    chk1.label = "Tabbing Sequence Is Top To " +
     "Bottom(" + chk1.tabIndex + ")";
   }
   
  ]]>
 </fx:Script>
 <!-- Just a list of components -->
 <s:VGroup width="100%" height="100%"
     verticalAlign="middle" horizontalAlign="center">
  <s:VGroup width="300" height="100%"
      verticalAlign="middle" horizontalAlign="center">
   <s:HGroup width="100%"
       horizontalAlign="center"
       verticalAlign="middle">
    <s:Label id="lblTxt0"/>
    <s:TextInput id="txtTxt0"/>
    <s:Spacer width="100%"/>
    <s:Label id="lblTxt1"
       text=""/>
    <s:TextInput id="txtTxt1"/>
   </s:HGroup>
   <s:HGroup width="100%" 
       horizontalAlign="center">
    <s:Button id="btn0" />
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center"
       verticalAlign="middle">
    <s:Label id="lblTxt2"/>
    <s:TextInput id="txtTxt2"/>
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:Button id="btn1"/>
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:CheckBox id="chk0" 
       change="rdoChangeHandler(event)" />
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:CheckBox id="chk1"  
       selected="true"
       change="rdoChangeHandler(event)" />
   </s:HGroup>
  </s:VGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, September 7, 2012

AS3: In Search of the missing ReleaseOutside

In the older flash, or during the AS2 era, there's a onReleaseOutside that allows you to click on a button and release it outside. However, in AS3, one could easily find MouseEvents like MOUSE_DOWN, MOUSE_UP, CLICK, etc... but there isn't a RELEASE_OUTSIDE action, so how do work around it?

Time for some source files - SimpleMouseReleaseOutside.mxml
<?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="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   //Upon creation complete, setup the button event of the button
   //and setup the check box
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    btn1.buttonMode = true;
    btn1.label = "Select Me Please";
    btn1.addEventListener(MouseEvent.MOUSE_DOWN, btnMouseDownEvent);
    
    chk1.buttonMode = true;
    chk1.label = "Click me to enable 'ReleaseOutside' on the btn.";
    chk1.selected = false;
   }
   
   //Upon performing a MOUSE DOWN action on the button, add the 
   //listeners for MOUSE UP and if the checkbox is selected, we
   //will be adding a MOUSE UP listener for the stage (This
   //will perform like a ReleaseOutside event in as2.
   private function btnMouseDownEvent(event:Event):void
   {
    btn1.label = "I'm selected";
    btn1.addEventListener(
     MouseEvent.MOUSE_UP, btnMouseUpEvent);
    if(chk1.selected)
    {
     stage.addEventListener(
      MouseEvent.MOUSE_UP, btnMouseUpEvent);
    }
   }
   
   //Upon performing a MOUSE UP action on the button or anywhere
   //in the file, we will be removing the listeners for the button
   //away.
   private function btnMouseUpEvent(event:Event):void
   {
    btn1.label = "Select Me Please";
    btn1.removeEventListener(
     MouseEvent.MOUSE_UP, btnMouseUpEvent);
    if(chk1.selected)
    {
     stage.removeEventListener(
      MouseEvent.MOUSE_UP, btnMouseUpEvent);
    }
   }
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%"
     height="100%"
     horizontalAlign="center">
  <s:Spacer height="100%"/>
  <s:Button id="btn1" 
      width="200"/>
  <s:Spacer height="100%"/>
  <s:CheckBox id="chk1"/>
  <s:Spacer height="100%"/>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, September 1, 2012

Flex: Locating a point

Probably there' a requirement that requires you to place an icon for both the highest and lowest y value of a chart, but how do you do it?

And here's my answer to the above question. :P Time for some coding... Here's my main application file - "SimpleChartPositionOfAPoint.mxml"
<?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"
      backgroundColor="#CDCDCD"
      creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.conversion.TextConverter;
   
   import mx.charts.HitData;
   import mx.charts.chartClasses.IChartElement2;
   import mx.charts.series.LineSeries;
   import mx.collections.ArrayCollection;
   import mx.collections.Sort;
   import mx.collections.SortField;
   import mx.events.FlexEvent;
   import mx.formatters.DateFormatter;
   
   import spark.events.IndexChangeEvent;
   
   //Records used in the chart
   [Bindable]
   private var myData:XML = 
    <records>
     <record>
      <date>16/11/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>24/07/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>05/04/2013</date>
      <people>79</people>
     </record>
     <record>
      <date>08/07/2012</date>
      <people>54</people>
     </record>
     <record>
      <date>22/11/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>10/04/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>17/03/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>16/10/2011</date>
      <people>63</people>
     </record>
     <record>
      <date>06/02/2012</date>
      <people>80</people>
     </record>
     <record>
      <date>09/01/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>18/11/2011</date>
      <people>100</people>
     </record>
     <record>
      <date>25/11/2011</date>
      <people>88</people>
     </record>
     <record>
      <date>29/05/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>30/03/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>26/01/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>12/11/2012</date>
      <people>48</people>
     </record>
     <record>
      <date>17/05/2013</date>
      <people>57</people>
     </record>
     <record>
      <date>13/04/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>18/07/2013</date>
      <people>81</people>
     </record>
     <record>
      <date>09/08/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>04/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/12/2012</date>
      <people>15</people>
     </record>
     <record>
      <date>17/08/2011</date>
      <people>1</people>
     </record>
     <record>
      <date>09/10/2012</date>
      <people>76</people>
     </record>
     <record>
      <date>20/02/2012</date>
      <people>62</people>
     </record>
     <record>
      <date>24/06/2013</date>
      <people>70</people>
     </record>
     <record>
      <date>17/07/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>21/04/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>92</people>
     </record>
     <record>
      <date>02/08/2013</date>
      <people>97</people>
     </record>
     <record>
      <date>27/12/2011</date>
      <people>5</people>
     </record>
     <record>
      <date>01/05/2012</date>
      <people>90</people>
     </record>
     <record>
      <date>20/04/2013</date>
      <people>75</people>
     </record>
     <record>
      <date>26/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>02/01/2012</date>
      <people>31</people>
     </record>
     <record>
      <date>04/02/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>22/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>10/09/2011</date>
      <people>97</people>
     </record>
     <record>
      <date>27/11/2012</date>
      <people>18</people>
     </record>
     <record>
      <date>15/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>17/10/2011</date>
      <people>85</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>12</people>
     </record>
     <record>
      <date>09/10/2011</date>
      <people>92</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>17</people>
     </record>
     <record>
      <date>22/10/2012</date>
      <people>45</people>
     </record>
     <record>
      <date>09/11/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>06/09/2012</date>
      <people>75</people>
     </record>
     <record>
      <date>13/08/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>04/03/2012</date>
      <people>20</people>
     </record>
     <record>
      <date>17/11/2012</date>
      <people>34</people>
     </record>
     <record>
      <date>01/02/2012</date>
      <people>51</people>
     </record>
     <record>
      <date>29/08/2011</date>
      <people>35</people>
     </record>
     <record>
      <date>11/02/2012</date>
      <people>35</people>
     </record>
     <record>
      <date>02/06/2012</date>
      <people>26</people>
     </record>
     <record>
      <date>20/01/2013</date>
      <people>98</people>
     </record>
     <record>
      <date>07/02/2013</date>
      <people>4</people>
     </record>
     <record>
      <date>27/08/2012</date>
      <people>44</people>
     </record>
     <record>
      <date>12/12/2012</date>
      <people>29</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>01/09/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>09/02/2013</date>
      <people>34</people>
     </record>
     <record>
      <date>22/09/2012</date>
      <people>86</people>
     </record>
     <record>
      <date>28/02/2012</date>
      <people>14</people>
     </record>
     <record>
      <date>02/02/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>08/06/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>23/03/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>07/04/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>28</people>
     </record>
     <record>
      <date>02/11/2012</date>
      <people>28</people>
     </record>
     <record>
      <date>14/11/2011</date>
      <people>3</people>
     </record>
     <record>
      <date>05/02/2013</date>
      <people>12</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>41</people>
     </record>
     <record>
      <date>30/09/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>19/02/2013</date>
      <people>29</people>
     </record>
     <record>
      <date>09/07/2013</date>
      <people>86</people>
     </record>
     <record>
      <date>30/04/2013</date>
      <people>35</people>
     </record>
     <record>
      <date>21/01/2012</date>
      <people>4</people>
     </record>
     <record>
      <date>26/06/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>55</people>
     </record>
     <record>
      <date>04/10/2011</date>
      <people>38</people>
     </record>
     <record>
      <date>20/03/2013</date>
      <people>38</people>
     </record>
     <record>
      <date>19/05/2013</date>
      <people>91</people>
     </record>
     <record>
      <date>28/08/2011</date>
      <people>73</people>
     </record>
     <record>
      <date>31/08/2011</date>
      <people>65</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>10/06/2013</date>
      <people>78</people>
     </record>
     <record>
      <date>03/07/2013</date>
      <people>8</people>
     </record>
     <record>
      <date>08/10/2012</date>
      <people>16</people>
     </record>
     <record>
      <date>19/03/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>28/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/07/2013</date>
      <people>51</people>
     </record>
     <record>
      <date>05/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>18/02/2012</date>
      <people>63</people>
     </record>
     <record>
      <date>03/09/2011</date>
      <people>45</people>
     </record>
     <record>
      <date>30/12/2011</date>
      <people>76</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>96</people>
     </record>
     <record>
      <date>15/06/2012</date>
      <people>55</people>
     </record>
    </records>;
   
   private var localSeries:LineSeries = new LineSeries();
   
   //This function will show a text box which is positioned
   //above the selected point
   protected function cb1ChangeEvent(event:IndexChangeEvent):void
   {
    //We will need the date, the date in numerical format
    //and the number of people during that date
    var tempDate:Date = event.currentTarget.selectedItem.date;
    var xPos:Number = tempDate.time;
    var yPos:Number = event.currentTarget.selectedItem.people;
    
    //Next, create a point withe the date in numerical format
    //and the number of people, which is used to create the
    //x and y axis of the chart
    var myPoint:Point = new Point(xPos,yPos);
    
    //Next, check it against the line series to find the 
    //and y postion of the point on the chart
    //Note: dataToLocal didn't calculate the gutters around
    //the chart, you need to calculate yrself.
    myPoint = localSeries.dataToLocal(xPos, yPos);
    
    //Next, offset the gutters on the left and top of the point
    myPoint.x += lineChart.getStyle("gutterLeft");
    myPoint.y += lineChart.getStyle("gutterTop");
    
    //find the global position of the point
    myPoint = lineChart.localToGlobal(myPoint);
    
    //followed by the step of mapping the point into the
    //layer abouve the chart 
    myPoint = canvas.globalToLocal(myPoint);
    
    //We will position the textfield above the selected point
    txtResult.visible = true;
    txtResult.x = myPoint.x - txtResult.width / 2;
    txtResult.y = myPoint.y - txtResult.height - 5;
    
    //Let's populate the textfield with some data.
    var tempStr:String = "";
    tempStr += "Date: " + dateFormatter(tempDate) + "<br>";
    tempStr += "No. of People: " + yPos;
    txtResult.textFlow = TextConverter.importToFlow(tempStr,
     TextConverter.TEXT_FIELD_HTML_FORMAT);
   }
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    // Parsing the xml data into ArrayCollection
    var objArray:ArrayCollection = new ArrayCollection();
    var tempObj:Object;
    var dateArray:Array;
    var tempDate:Date;
    for(var i:int = 0; i < myData.record.length(); i ++)
    {
     tempObj = new Object();
     dateArray = String(myData.record[i].date).split("/");
     //Convert the date data into a Date Object
     tempDate = new Date(dateArray[2], 
      Number(dateArray[1]) - 1, 
      dateArray[0]);
     tempObj.date = tempDate;
     tempObj.time = tempDate.time;
     tempObj.people = myData.record[i].people;
     tempObj.label = dateFormatter(tempDate);
     objArray.addItem(tempObj);
    }
    
    //Create the SortField object for the "time" field 
    //in the ArrayCollection object, and make sure we
    //do a numeric sort.
    var dataSortField:SortField = new SortField();
    dataSortField.name = "time";
    dataSortField.numeric = true;
    
    //Create the Sort object and add the SortField 
    //object created earlier to the array of fields
    //to sort on.
    var numericDataSort:Sort = new Sort();
    numericDataSort.fields = [dataSortField];
    
    objArray.sort = numericDataSort;
    objArray.refresh();
    
    //Create the new series and set its properties.
    localSeries.dataProvider = objArray;
    localSeries.yField = "people";
    localSeries.xField = "date";
    
    //Back up the current series on the chart.
    var currentSeries:Array = lineChart.series;
    //Add the new series to the current Array of 
    //series.
    currentSeries.push(localSeries);
    //Add the new Array of series to the chart.
    lineChart.series = currentSeries;
    
    cb1.dataProvider = objArray;
   }
   
   //This function will return a string based on the
   //Date format DD/MM/YYYY.
   private function dateFormatter(tempDate:Date):String
   {
    var fmt:DateFormatter = new DateFormatter();
    fmt.formatString = "DD/MM/YYYY";
    return fmt.format(tempDate);
   }
   
   //We are customizing the datatip / tool tip of the
   //chart data.
   public function myDataTipFunction(e:HitData):String {
    var s:String = "";
    var tempDate:Date = e.item.date as Date;
    s += "Date: " + dateFormatter(tempDate) + "<br>";
    s += "No. of People: " + e.item.people;
    return s;
   }
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%"
     verticalAlign="middle"
     horizontalAlign="center">
  <s:BorderContainer width="100%"
         height="100%"
         backgroundAlpha="0"
         borderVisible="false">
   <s:HGroup verticalAlign="middle" horizontalAlign="center"
       width="100%"
       height="100%">
    <!-- Need to set the gutterLeft and 
     gutterTop of the chart -->
    <mx:LineChart id="lineChart"
         gutterTop="0"
         gutterLeft="50"
         showDataTips="true" 
         width="80%"
         height="80%"
         dataTipFunction="myDataTipFunction">
     <mx:horizontalAxis>
      <mx:DateTimeAxis dataUnits="days" id="dateAxis" 
           alignLabelsToUnits="true"/> 
     </mx:horizontalAxis>
    </mx:LineChart>
   </s:HGroup>
   <s:BorderContainer width="100%" 
          height="100%"
          id="canvas"
          mouseEnabled="false"
          backgroundAlpha="0"
          borderVisible="false"
          mouseChildren="false">
    <s:TextArea width="150"
       height="50" 
        visible="false"
       id="txtResult"/>
   </s:BorderContainer>
  </s:BorderContainer>
  <s:HGroup width="100%" 
      verticalAlign="middle"
      horizontalAlign="center">
   <s:Label text="Select a Date:"/>
   <s:ComboBox id="cb1" 
       change="cb1ChangeEvent(event)"/>
  </s:HGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.