Monday, December 24, 2012

Last post for this year - Greetings

Today is 'Christmas Eve'. Therefore...


Thanks for all your help and support.
And I wish you a Merry Christmas.


and a Happy New Year.

Actually, from tomorrow onwards, I will be travelling overseas.
Therefore, I wouldn't be updating the blog(s) for a very long time.
Sorry for any inconvenience caused. Well then, I would see you next year.

Saturday, December 22, 2012

Keeping track of all the...

serial numbers of all the applications / softwares that are installed on your PC can be a complete mess. Therefore what if there is a way to grab all the serial numbers of all your applications / softwares at one go, will that make your life easier? Introducing...


'Belarc Advisor'
By installing and running this software, it will create a html web page
in your PC, showing a table of installed softwares and the corresponding
serial numbers. Just imagine how much time you can save by using this...

* Click here to find out more about the software 'Belarc Advisor'.

Friday, December 14, 2012

Flex: Changing the border colour of a Tool Tip of a Area Series

You might have encounter the following issue. You have created a few Charts with a combination of numerous Area Series. However, the border colour of the tool tip is taken from the area fill of the Area Series and you wanted to change the border colour of the tool tip into the stroke colour of the Area Series. And here's a simple solution to the scenario stated in the above.

Let's take a look at the main application file first.

SimpleAreaChartToolTip.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 mx.charts.HitData;
   import mx.charts.chartClasses.IChartElement2;
   import mx.charts.chartClasses.Series;
   import mx.charts.series.AreaSeries;
   import mx.collections.ArrayCollection;
   import mx.collections.Sort;
   import mx.collections.SortField;
   import mx.events.FlexEvent;
   import mx.formatters.DateFormatter;
   import mx.graphics.GradientEntry;
   import mx.graphics.LinearGradient;
   import mx.graphics.SolidColorStroke;
   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>
      <car>23</car>
     </record>
     <record>
      <date>02/09/2013</date>
      <people>61</people>
      <car>81</car>
     </record>
     <record>
      <date>03/09/2013</date>
      <people>67</people>
      <car>47</car>
     </record>
     <record>
      <date>04/09/2013</date>
      <people>75</people>
      <car>95</car>
     </record>
     <record>
      <date>05/09/2013</date>
      <people>65</people>
      <car>45</car>
     </record>
     <record>
      <date>06/09/2013</date>
      <people>32</people>
      <car>52</car>
     </record>
     <record>
      <date>07/09/2013</date>
      <people>66</people>
      <car>46</car>
     </record>
     <record>
      <date>08/09/2013</date>
      <people>85</people>
      <car>105</car>
     </record>
     <record>
      <date>09/09/2013</date>
      <people>37</people>
      <car>57</car>
     </record>
     <record>
      <date>10/09/2013</date>
      <people>80</people>
      <car>100</car>
     </record>
    </records>;
   
   private var localSeries:AreaSeries = new AreaSeries();
   private var localSeriesFill:LinearGradient = 
    new LinearGradient();
   private var localSeriesFillArray:Array = 
    new Array();
   private var localSeriesStroke:SolidColorStroke = 
    new SolidColorStroke();
   
   private var localCarSeries:AreaSeries = new AreaSeries();
   private var localCarSeriesFill:LinearGradient = 
    new LinearGradient();
   private var localCarSeriesFillArray:Array = 
    new Array();
   private var localCarSeriesStroke:SolidColorStroke = 
    new SolidColorStroke();
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    
    //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];
    
    // 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);
    }
    
    objArray.sort = numericDataSort;
    objArray.refresh();
    
    //Create the new series and set its properties.
    localSeries.dataProvider = objArray;
    localSeries.yField = "people";
    localSeries.xField = "date";
    
    //Create the gradient for the first Area Series
    var tempFill:GradientEntry = 
     new GradientEntry(0x999999, 0, 0.5);
    localSeriesFillArray.push(tempFill);
    tempFill = 
     new GradientEntry(0x000000, 1, 0.5);
    localSeriesFillArray.push(tempFill);
    localSeriesFill.entries = localSeriesFillArray;
    localSeries.setStyle("areaFill", localSeriesFill);
    
    //Create the Stroke for the first Area Series
    localSeriesStroke = new SolidColorStroke(0xFF0000, 2, 0.5);
    localSeries.setStyle("areaStroke", localSeriesStroke);
    
    localSeries.displayName = "area_people";
    
    objArray = new ArrayCollection();
    for(i = 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.car = myData.record[i].car;
     tempObj.label = dateFormatter(tempDate);
     objArray.addItem(tempObj);
    } 
    
    objArray.sort = numericDataSort;
    objArray.refresh();
    
    //Create the new series and set its properties.
    localCarSeries.dataProvider = objArray;
    localCarSeries.yField = "car";
    localCarSeries.xField = "date";
    
    //Create the gradient for the second Area Series
    tempFill = 
     new GradientEntry(0xFF7300, 0, 0.8);
    localCarSeriesFillArray.push(tempFill);
    tempFill = 
     new GradientEntry(0xFFBB00, 1, 0.5);
    localCarSeriesFillArray.push(tempFill);
    localCarSeriesFill.entries = localCarSeriesFillArray;
    localCarSeries.setStyle("areaFill", localCarSeriesFill);
    
    //Create the Stroke for the second Area Series
    localCarSeriesStroke = new SolidColorStroke(0x00FF00, 2, 0.5);
    localCarSeries.setStyle("areaStroke", localCarSeriesStroke);
    localCarSeries.displayName = "area_car";
    
    //We will remove all the series attach to the chart
    //first
    chart.series = null;
    
    // Back up the current series on the chart.
    var currentSeries:Array = chart.series;
    // Add the new series to the current Array of series.
    currentSeries.push(localCarSeries);
    currentSeries.push(localSeries);
    // Add the new Array of series to the chart.
    chart.series = currentSeries;
   }
   
   //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>";
    if(Series(e.element).displayName == "area_people")
    {
     s += "No. of People: " + e.item.people;
    }else{
     s += "No. of Cars: " + e.item.car;
    }
    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;
   }
  ]]>
 </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:CartesianChart id="chart"
           gutterTop="0"
           gutterLeft="50"
           showDataTips="true" 
           width="80%"
           height="80%"
           dataTipRenderer="ToolTip.AreaSeriesToolTip"
           dataTipFunction="myDataTipFunction">
     <mx:horizontalAxis>
      <mx:DateTimeAxis dataUnits="days" id="dateAxis" 
           alignLabelsToUnits="false" 
           parseFunction="createDate"/> 
     </mx:horizontalAxis>
    </mx:CartesianChart>
   </s:HGroup>
  </s:BorderContainer>
 </s:VGroup>
</s:Application>

ToolTip Renderer File
ToolTip/AreaSeriesToolTip.as
package ToolTip
{
 import mx.charts.HitData;
 import mx.charts.chartClasses.DataTip;
 import mx.charts.chartClasses.Series;
 
 public class AreaSeriesToolTip extends DataTip
 {
  public function AreaSeriesToolTip()
  {
   super();
  }
  
  override public function set data(value:Object):void
  {
   //Get the HitData
   var dataPoint:HitData = value as HitData;
   //Cast it into a series so that we can find the
   //display name of the series
   var dataElement:Series = Series(dataPoint.element);
   //Based on the display name of the series, change
   //the contextColor accordingly.
   if(dataElement.displayName == "area_people")
   {
    value.contextColor = 0xFF0000;
   }else if(dataElement.displayName == "area_car")
   {
    value.contextColor = 0x00FF00; 
   }
   super.data = value;
  }
 }
}
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, December 8, 2012

OMG it still exists....

Do you have experience creating a website? Spending too much time creating and debugging a website? And how much time have you spent on the debugging process? But do you know that IE6 still holds more than 5% of the overall market share for web browsers?


Image taken from 'NetMarketShare'.
According to the website shown in the above, more than 50% of the market
share are IE browsers. On top of that just by combining IE6, IE8 and IE9
still takes up more than 50% of the overall market share. And if you do
a search for the term 'IE6' in google, you will be getting all sorts of
results related to articles asking users to upgrade their browser to a better one.

Anyway the website doesn't provide statistics of the desktop browser alone.
There's statistics for the Operating System used by desktop users,
Operating System used by mobile, Search Engines, etc...
(I wonder when can we reach the day where IE6 would drop to less than 1%
in the overall market share for Web browsers. O.O)

* Click here to find out more about 'NetMarketShare'.