June 21, 2010

Hiding Series in ExtJS Charts

In the last few posts we saw how to create and handle events in Ext JS charts. We will have a look at some advanced tasks using Ext JS charts. In this post, we will learn how to hide and display a series in a chart.

As usual, I will go with the sales and revenue chart. In our chart we will have two series - Sales and Revenue. We will provide two check boxes to toggle the series' visibility.
Lets begin with the data store (The data store is same as the one used in previous tutorials):
var store = new Ext.data.JsonStore({
fields:['month', 'sales','rev'],
data: [
    {month:'Jan', sales: 2000, rev: 3000},
    {month:'Feb', sales: 1800, rev: 2900},
    {month:'Mar', sales: 1500, rev: 3100},
    .
    .
    .
    {month:'Nov', sales: 2100, rev: 3000},
    {month:'Dec', sales: 2650, rev: 3300}
]
});
The framework does not provide us with APIs for what we are trying to achieve. But before that lets display the chart and the controls without the proposed functionality:
new Ext.Panel({
    title: 'Hiding series in ExtJS Charts',
    renderTo: 'container',
    width:600,
    height:300,
    tbar:[{
         xtype:'checkbox',
         boxLabel:'Toggle Sales',
         handler: function() {
                  alert('Hide / Show Sales');
           }
         },{
         xtype:'checkbox',
         boxLabel:'Toggle Revenue',
         handler: function() {
                  alert('Hide / Show Revenue');
           }
         }],
    items: [{
        xtype: 'columnchart',
        id:'myChart',
        store: store,
        xField: 'month',
        extraStyle: {
                  legend: {
                        display: 'right'
                  }
    },
    series: [{
        yField: 'sales',
        displayName: 'Sales'
        },{
        yField: 'rev',
        displayName: 'Revenue'
    }]
  }]
});
Now we have the chart and the necessary handler methods on the checkbox, let's split the problem into two parts. First is hiding the series in the chart and second is to hide the series name in the legend.

To hide the series, you will have to access the APIs exposed by flash component. The SWF component exposes a method named setSeriesStylesByIndex for setting styles for a series. The method has two parameters - index of the series you are about to modify and the config object that will hold the new style.You can pass the following parameters and its values to the config object:
  • color
  • colors
  • size
  • alpha
  • borderColor
  • borderAlpha
  • fillColor
  • fillAlpha
  • lineSize
  • lineColor
  • lineAlpha
  • image
  • images
  • mode
  • connectPoints
  • connectDiscontinuousPoints
  • discontinuousDashLength
  • skin
  • visibility
For more details on these attributes, have a look at YUI documentation. Back to our method, it will now look something like this:
function setSeriesStylesByIndex(index, styles){
    // Assuming swfObject is an instance of swf available in chart
    swfObject.setSeriesStylesByIndex(index, Ext.encode(styles));
}
Our next hurdle is how to call this method when clicking on our checkbox. To accomplish our task we will use the override method (static method) available in Ext class.
Here is the final code of our function being injected into chart:
Ext.override(Ext.chart.Chart, {
    setSeriesStylesByIndex: function(index, styles){
        this.swf.setSeriesStylesByIndex(index, Ext.encode(styles));
    }
});
If you execute our project and have a look at the chart rendered you will notice that the series display can be toggled but the legend of the chart is not updated properly. To update the chart's legend, we will update the showInLegend property of the series. Each series can be accessed in a chart using the series array. So, to modify the first first series, we just need to use the array notation to access the series and the showInLegend property. For example:
chart.series[0].showInLegend = false;
By just setting the property will not have any effect on the chart. We will have to update the display by calling the refresh method available with the chart object. Here is how our checkbox event handler look finally:
function() { 
var chart = Ext.ComponentMgr.get('myChart');
    if(this.checked) {
         // hide the columns (series in chart)
         chart.setSeriesStylesByIndex(0,
                  {connectPoints: false,alpha:0.0});
         // hide the series label in legend
         chart.series[0].showInLegend = false;
    } else {
         chart.setSeriesStylesByIndex(0,
                  {connectPoints: true,alpha:1.0});
         chart.series[0].showInLegend = true;
    }
    // Refresh the chart
    chart.refresh();
}
You will have to hard-code the appropriate series index so that the correct series properties is modified.The complete code is given below:
new Ext.Panel({
    title: 'Hiding series in ExtJS Charts',
    renderTo: 'container',
    width:600,
    height:300,
    tbar:[{
         xtype:'checkbox',
         boxLabel:'Toggle Sales',
         handler: function() {
             var chart = Ext.ComponentMgr.get('myChart');
             if(this.checked) {
                 chart.setSeriesStylesByIndex(0,
                          {connectPoints: false,alpha:0.0});
                 chart.series[0].showInLegend = false;
             } else {
                 chart.setSeriesStylesByIndex(0,
                          {connectPoints: true,alpha:1.0});
                 chart.series[0].showInLegend = true;
             }
             chart.refresh();
         }
    },{
         xtype:'checkbox',
         boxLabel:'Toggle Revenue',
         handler: function() {
             var chart = Ext.ComponentMgr.get('myChart');
             if(this.checked) {
                 chart.setSeriesStylesByIndex(1,
                          {connectPoints: false,alpha:0.0});
                 chart.series[1].showInLegend = false;
             } else {
                 chart.setSeriesStylesByIndex(1,
                          {connectPoints: true,alpha:1.0});
                 chart.series[1].showInLegend = true;
             }
             chart.refresh();
         }
    }],
    items: [{
        xtype: 'columnchart',
        id:'myChart',
        store: store,
        xField: 'month',
        extraStyle: {
             legend: {
                display: 'right'
             }
        },
    series: [{
        yField: 'sales',
        displayName: 'Sales'
    },{
        yField: 'rev',
        displayName: 'Revenue'
    }]
  }]
});
ExtJS Line Chart showing Sales & Revenue

Well, that's all for now. In the coming weeks we will have some more tutorials on chart and finally build a dashboard. We will also have a look at the new touch UI framework introduced recently.

Read other ExtJS related articles!

June 15, 2010

ExtJS is now Sencha!

The post's heading speaks it all. Yes, Ext JS a javascript UI library has combined forces with jQTouch and Raphael projects. The company's name is being changed to Sencha which is a popular Japanese green tea. It is interesting to see jQtouch and Raphael which are two leading open source projects getting combined.

As a developer using Ext JS, I am very excited to see this merging. I would like to see Ext JS making use of Raphael's graphics capabilities. At the same this, it will be very interesting to see how a jQuery backed mobile web development library is going to fit it. Will they rewrite the library using Ext JS core? Another interesting point is that both Raphael and jQtouch uses MIT license. The company also managed to get hold of Jonathan Stark to maintain jQtouch.

What I would like to see is a better visualization API (charting tools) based on Raphael rather than the YUI charts. It will be also interesting to see how these projects collaborate and how their outcome affects the developer community.

Read other articles and tutorials on ExtJS.

June 03, 2010

Handling Events in ExtJS Charts

After publishing "Getting started with ExtJS Charts" article last week, I got a question on handling event in ExtJS charts. So, in this article we will discuss about the event handling. Before we present the reader’s issue, let’s have a look at how to handle events.


The documentation of chart package is really bad! I wonder why ExtJS team is not updating it. I would actually love to see a java script based chart library (built by ExtJs team) rather than YUI charts being used. Another option for developers would be to use other charting tools available. But for now, let's get back to event handling.

You can attach custom event handlers just like how you do for any other ExtJS component. You can use the listeners property or use methods like on and addListener.

Now if you have a look at the Cart's source code you will find few hidden events:
  • itemmouseover
  • itemmouseout
  • itemclick
  • itemdoubleclick
  • itemdragstart
  • itemdrag
  • itemdragend
Unfortunately, I found some of these not working as it should be. Even forums seem to have less detail about these events.

Item Click Event (itemclick):
Item click event is invoked when a chart item is clicked. With this event you can do drill down, update another chart or do other dynamic effects on the chart. Let’s dive into the code to get a better understanding.

First let’s set up our data store:
var store = new Ext.data.JsonStore({
    fields:['month', 'sales','rev'],
    data: [
            {month:'Jan', sales: 2000, rev: 3000},
            {month:'Feb', sales: 1800, rev: 2900},
            .
            .
            .
     {month:'Dec', sales: 2650, rev: 3300}
 ]
});
We will create a simple column chart using this store:
new Ext.Panel({
    title: 'A Demo Application',
    renderTo: 'container',
    width:600,
    height:350,
    items: [{
 xtype: 'columnchart',     
 id:'myChart',
        store: store,
        xField: 'month',
 yField: 'sales',
 listeners: {
            itemclick: function(o) {
         var record = store.getAt(o.index);
  Ext.Msg.alert('Item Selected',
                    "You Clicked on Sales: " +rec.get('sales') + 
                    " for " + rec.get('month'));
     }
 }      
    }]
});
In the above code, I have used listeners property to specify my itemclick events handler. Using the parameter passed to the event’s method, we will be able to access all the necessary information. Here I am just displaying the value of sales.

Item Mouse Over Event (itemmouseover):
itemmouseover event is fired when user mouse over an item. This can be used for display some dynamic selection. For example, let’s assume we had a data grid with the same values ie sales and revenue and we would like to automatically select the row when use mouse over on an item in the chart.

We will introduce a data grid that will render the same data store. This time, I will make use of the line chart and display both sales and revenue details.
new Ext.Panel({
        title: 'A Demo Application',
        renderTo: 'container',
 layout:'column',
        height: 350,        
        items: [{
     xtype: 'linechart',
     width:600,
          height:350,
     id:'myChart',
            store: store,
     xField: 'month',
     xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
     }),
     yAxis: new Ext.chart.NumericAxis({
  title:'USD', 
         majorUnit: 500
     }),
     series: [{
  yField: 'sales',
  displayName: 'Sales',       
     },{
  yField: 'rev',
  displayName: 'Revenue'
            }],
     listeners: {
  itemmouseover: function(o) {
             var myGrid = Ext.getCmp('myGrid');
      myGrid.selModel.selectRow(o.index);       
  }
     }      
 },{
     xtype: 'grid',
     title:'The Sales Grid',
     id:'myGrid',
     store: store,
     height: 350,
     width: 300,
     stripeRows: true,
     sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
     columns:[
  {header:'Month',dataIndex:'month'},
  {header:'Sales',dataIndex:'sales'},
  {header:'Revenue',dataIndex:'rev'}
     ]
 }]
 });

The area of interest would be to see how we did it. Have a close look at the itemmouseover event handler. Basically, the key to manipulation is the object that is passed to the event handler. Using this you will be able to access not only the index but also the chart object itself. The attributes of this object are:
  • Component – The chart component itself.
  • Index – The index position of the item in store.
  • Item – The row from store corresponding to the index. You can access individual attributes of the row.
  • seriesIndex – The index position of the series. The values starts with 0.
  • type – Name of the event
  • x – x coordinate 
  • y – y coordinate

Drag Events:
itemdrag, itemdragstart and itemdragend are used for drag events. I tried making use of these events to make a graph wherein user will be able to drag the points and modify the values. Unfortunately, I am stuck! If I get it running, I will present it in future.

Double Click Event (itemdoubleclick):
I had very bad time working with this event! It just doesn’t get fired. From the forum discussions I see that this event might not be implemented yet. I wonder why, but It would have been great if user can double click on a specific month’s sales and he get it a detail report to download.

Now, lets tackle the reader's problem.

Reader’s problem:
The reader asked how the click event works and how to know which series was clicked.

Solution:
Now, solving this is very easy. You can handle click using the itemclick event and to identify the series and values you can make use of the values provided by the object. Just modify the as shown below:
itemclick: function(o){
 var rec = store.getAt(o.index);
 if(o.seriesIndex==0)
  Ext.Msg.alert('Item Selected',
                "You Clicked on Sales: " +rec.get('sales') + 
                " for " + rec.get('month'));
 else
  Ext.Msg.alert('Item Selected',
               "You Clicked on Revenue: " +rec.get('rev') +
               " for " + rec.get('month'));
}

Well, thats all for now. Let me know your feedback through comments or my contact form. Enjoy the day and time for me to relax!

Read other ExtJS related articles!

May 29, 2010

Working with ExtJS Pie Charts

In the previous post we saw how to create & customize charts using ExtJS. In this post, we will have a look at Pie charts. Pie charts are little different from other charts as they do not have axis and the data displayed is in percentage.

First Pie Chart

Let’s start with the data store. In this tutorial, I am getting the data from a remote URL. My server returns me a set of JSON object with product name and their sales value. Here is the data store:
var store = new Ext.data.JsonStore({
      fields:['product','sales'],
      root: 'rec',
      url: ‘/piechart/data/’
});
Unlike other charts, pie charts do not have axis. So, instead of using xField and yField properties of charts to pass data, we have dataField and categoryField in pie charts. Here is the code for pie chart:
new Ext.Panel({
title: 'Pie Chart',
      renderTo: 'chartDiv',
      width:400,
      height:300,                        
      items: {
            xtype: 'piechart',
            store: store,
      dataField: 'sales',
            categoryField: 'product'
      }
});
Very simple indeed! ExtJS does all the necessary calculations even if you don’t represent the data in percentage.

Adding Legend

Now, let’s add a legend to this chart. Without it, there is no much use in displaying a chart. An important property for styling is extraStyle. It helps you to add extra styles that will add or override default styles of the chart. Here is the final code for the pie chart and panel:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:400,
       height:300,
items: {
       xtype: 'piechart',
       store: store,
       dataField: 'sales',
       categoryField: 'product',
       extraStyle: {
            legend:{
                display: 'right',
                padding: 10,
                border:{
                   color: '#CBCBCB',
                   size: 1
                }
            }
        }
      }
 });
While displaying the legend,notice that I have also made some beautification to it. I have provided a thin border using a specific color. There is no chart specific code for displaying legend, so the same code will work for other types of charts as well.

Custom Colors in your Pie chart

By default, ExtJS picks out the colors when rendering the chart. You might find these color shade dull. Lets try to brighten up our chart. I am going to apply a color scheme called Esprit_80s. In order to apply, we need to basically modify the style of series. So we will modify seriesStyles property of our pie chart:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:600,
       height:300,
       items: {
           xtype: 'piechart',
           store: store,
           dataField: 'sales',
           categoryField: 'product',
           seriesStyles: {
             colors:['#F8869D','#25CDF2',
                     '#FFAA3C','#DEFE39',
                     '#AB63F6'] //eSprit 80s
            },
           extraStyle: {
                 legend:{
                    display: 'right',
                 padding: 10,
                 border:{
                   color: '#CBCBCB',
                   size: 1
                 }
           }
       }
    }
});

Note that the property colors is used only for pie charts. If you need to change the colors for other charts you will have to use the color property.

Textures & images in your Pie chart

ExtJS also provides us the ability to use images instead of color. So, if you have few texture images or any other images, you can easily substitute them for colors. This is possible through the images property of seriesStyles. I have five simple texture images and here is how I am adding them to our pie chart:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:600,
       height:300,
       items: {
           xtype: 'piechart',
           store: store,
           dataField: 'sales',
           categoryField: 'product',
           seriesStyles: {
           images:['images/one.png',
                'images/three.png',
                'images/two.png',
                'images/four.png',
                'images/five.png']
            },
            extraStyle: {
                legend:{
                display: 'bottom',
                padding: 10,
                border:{
                   color: '#CBCBCB',
                   size: 1
                }
            }
       }
   }
});

Apart from these properties, extraStyle can be used to change the font styles as well. Have a look at the APIs and try out different customizations. I will be back with more customization tutorials on ExtJS charts. Let me know your feedback either through comments or using the contact form.

Learn how to Handle events in ExtJS charts or read other articles on ExtJS.

May 19, 2010

Getting Started with ExtJS Charts

The Charts feature in ExtJS is not a new thing, but recently few Techno Paper readers asked me questions regrading the same. This article is about getting started with ExtJS Charts how to do some basic customizations. For now, we will see what kind of charts ExtJS provide and how to get your first chart displayed.

Prerequisites

I assume you already have knowledge in building the UI (panels at least) and have worked on DataStores ( I will be using JSONStore). If you are not ready with these, may be you can have a look at my basic tutorials like "All about...".

What ExtJS offers
ExtJS offers you Line, Bar, Column, Pie and stacked charts. It also offers good amount of customization options as well. All the chart related classes are under the package Ext.chart and Chart is the base class. Apart from the chart classes, the library also provides classes that can be used to customize the axis, series and even the chart display. But note that, ExtJS makes use of Flash to render the charts and its not pure JavaScript component. Internally ExtJS is making use of YUI charts features and classes. Now, lets get started with coding!

Hello World of Charts

Building charts with ExtJS requires three things. The Datastore, the Chart object and a Panel to display the chart. In our first example i am going to keep things very simple. Lets build a DataStore first:
var store = new Ext.data.JsonStore({
fields:['month', 'sales'],
data: [
    {month:'Jan', sales: 2000},{month:'Feb', sales: 1800},
    {month:'Mar', sales: 1500},{month:'Apr', sales: 2150},
    {month:'May', sales: 2210},{month:'Jun', sales: 2250},
    {month:'Jul', sales: 2370},{month:'Aug', sales: 2500},
    {month:'Sep', sales: 3000},{month:'Oct', sales: 2580},
    {month:'Nov', sales: 2100},{month:'Dec', sales: 2650}
]});
I have a simple JsonStore here with the data hardcoded. In later examples, we will be fetching the data through ajax request. In the JsonStore, I have provided metadata and data. The fields attribute describe the fields in my records. The data attribute actually holds the data in the form of JSON. Instead of using JSON, we could also use XML.

Next, to create the chart object. For this example, I have used the line chart. Here is the code:
var chart = new Ext.chart.LineChart({
    store: store,
    xField: 'month',
    yField: 'sales'
});
Its very clean and simple! I have just provided the data store and what has to be plotted along x and y axis. And finally we need to put the chart into display. Here is our Panel:
var Panel = new Ext.Panel({
    title: 'Yearly Sales',
    renderTo: 'chartDiv',
    width: 400,
    height: 200,
    items:[chart]
});
If you are experienced coder I suggest you define the chart object in the panel rather than declaring it separately. Lets begin dig deeper!

Working with Axis

Chat's axis can be configured using xAsix and yAsix properties. There properties can accept objects of CategoryAsix, NumericAxis or TimeAxis. Lets add titles to our chart's axis:
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
                  }),
                  yAxis: new Ext.chart.NumericAxis({
                  title:'USD',
                  majorUnit: 500
                  })
Note that we have made use of CategoryAxis for y-axis as it hold months. Whereas, we have used NumericAxis for x-axis as it represents sales value in USD. I also changed the units in which the x-axis is represented. Check the API for other properties of these classes.

Working with Series

You don't always plot one parameter on a chart. At times, you have multiple data to be visualized onto the charts. Lets take our example of sales per month and add revenue to it. Now we need to plot both sales and revenue for each month. ExtJS allows you to do this by adding series object to the chart. The framework provides five implementations for different types of charts. Let's modify our chart to show revenue as well:
new Ext.Panel({
       title: 'A Simple Chart',
       renderTo: 'container',
       width:600,
       height:300,
       items: {
           xtype: 'linechart',
           store: store,
           xField: 'month',
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
}),
yAxis: new Ext.chart.NumericAxis({
title:'USD',
majorUnit: 500
}),
series: [{
yField: 'sales'
},{
yField: 'rev'
             }]
}
   });
I have kept the series objects very simple. We have just added the data alone. Upon execution, you will notice that it difficult to interpret the data as we do not have a legend on our chart. And that's exactly our next objective. To start with, lets modify the series as:
series: [{
yField: 'sales',
displayName: 'Sales'
},{
yField: 'rev',
displayName: 'Revenue'
 }]
I have just added the displyName property. To complete our modifications we need to do one final task, i.e display the legend!

Working with Extra Styles

extraSyle is an important property for styling your charts. It helps in modifying the colors, fonts, borders for various parts of your chart like axis, data tips, legends etc. First lets add a legend to our existing chart. Here is the code:
new Ext.Panel({
       title: 'A Simple Chart',
       renderTo: 'container',
       width:600,
       height:300,
       items: {
           xtype: 'linechart',
           store: store,
           xField: 'month',
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
}),
yAxis: new Ext.chart.NumericAxis({
title:'USD',
majorUnit: 500
}),
series: [{
yField: 'sales',
displayName: 'Sales'
},{
yField: 'rev',
displayName: 'Revenue'
             }],
extraStyle: {
legend: {
display: 'right'
}
}
}
   });
If you think of more customizations and styling, you need to have a good look at the extraStyle.
Well, that all for now. Feel free to provide me your feedback on this post. Next, we will have a look at pie charts.