Wednesday 21 September 2011

Dojo Charts Part 1 - Pie Charts

Dreamforce and Cloudforce are now over for another year, so its time to blog some code for a change.  This is the first in a short series of posts detailing how to produce charts in Visualforce using the Dojo Javascript toolkit.

I've been using Dojo Charting for around 18 months now on a variety of projects.  I don't propose to go into the minute detail in this post - there's plenty of information on this at the Sitepen site - a good starting point is: A Beginners Guide to Dojo Charting.  This post is concerned with integrating Dojo Charting into Visualforce pages. 

In view of the upcoming Winter 12 release, and the Developer Preview of Visualforce Charting, I'm sure some people will be wondering if there's any value to a Javascript charting solution.  My view on this is that its another tool in the box - plus Dojo Charting is available for production use now.

And so to the code.  The "parent" page provides the hooks into a cross domain build of Dojo hosted by Google.  There is always the option to upload the Dojo library as a static resource into your Salesforce org, but I prefer not to have to worry about managing this resource across every Salesforce org.  This page also contains sample data that is used to generate the sample pie chart.  The source for the page is shown below:

<apex:page controller="DojoPieChartController">
<script djconfig="parseOnLoad: true,
      modulePaths: { 
          'dojo': 'https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo', 
          'dijit': 'https://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit', 
         'dojox': 'https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojox' 
             }
    " src="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js" type="text/javascript">
</script>

<apex:sectionheader title="Dojo Pie Chart">
<apex:form>
 <apex:pageblock title="Chart Data">
  <table>
    <tbody>
    <tr>
      <td>Value</td>
      <td>Color</td>
      <td>Text</td>
    </tr> 
    <tr>
      <td><apex:inputtext value="{!value1}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!color1}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!text1}">
      </apex:inputtext></td>
    </tr> 
    <tr>
      <td><apex:inputtext value="{!value2}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!color2}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!text2}">
      </apex:inputtext></td>
    </tr>
    <tr>
      <td><apex:inputtext value="{!value3}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!color3}">
      </apex:inputtext></td>
      <td><apex:inputtext value="{!text3}">
      </apex:inputtext></td>
    </tr>
</tbody>
</table>
<apex:commandbutton value="Update">
 </apex:commandbutton></apex:pageblock>
</apex:form>
<c:dojopiechart color1="{!color1}" color2="{!color2}" color3="{!color3}" 
id="piechart" text1="{!text1}" text2="{!text2}" text3="{!text3}" 
title="Example pie chart" value1="{!value1}" value2="{!value2}" 
value3="{!value3}">
</c:dojopiechart>
</apex:sectionheader>
</apex:page>

The real work is done by the dojopiechart component. This takes three sets of parameters, one set per wedge of the pie.  For each wedge, the colour (or color, as Dojo is clearly American!), the text to display in the legend and the value for the wedge - the values should add up to 100.

The component code is shown below.


<apex:component >
<apex:attribute name="value1" type="String" description="The value for slice 1"/>
<apex:attribute name="color1" type="String" description="The colour for slice 1"/>
<apex:attribute name="text1" type="String" description="Text to display against slice 1"/>
<apex:attribute name="value2" type="String" description="The value for slice 2"/>
<apex:attribute name="color2" type="String" description="The colour for slice 2"/>
<apex:attribute name="text2" type="String" description="Text to display against slice 2"/>
<apex:attribute name="value3" type="String" description="The value for slice 3"/>
<apex:attribute name="color3" type="String" description="The colour for slice 3"/>
<apex:attribute name="text3" type="String" description="Text to display against slice 3"/>
<apex:attribute name="divId" type="String" description="ID of the div to store the chart in" default="piechart"/>
<apex:attribute name="title" type="String" description="Title of the chart"/>

<script type="text/javascript">
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.plot2d.Pie");
dojo.require("dojox.charting.widget.Legend");
dojo.require("dojox.charting.themes.MiamiNice");


makeCharts = function(){

		var chart=new dojox.charting.Chart2D("{!divId}");
        chart.addPlot("default", 
                {type: "Pie",
    	        font: "normal normal 11pt Tahoma",
        	    fontColor: "black",
            	labelOffset: -40,
	            radius: 80
                      });
                     
		chart.setTheme(dojox.charting.themes.MiamiNice);
        chart.addSeries("Series A", [
                  {y: {!value1}, text: "{!text1}", color: "{!color1}"},
                  {y: {!value2}, text: "{!text2}", color: "{!color2}"},
                  {y: {!value3}, text: "{!text3}", color: "{!color3}"}
                  ]);
        
        chart.render(); 
};

dojo.addOnLoad(makeCharts);

</script>
<div style="font-family:Verdana; font-size:14px; font-weight:bold;">{!Title}</div>
<div id="{!divId}" style="width: 300px; height: 300px; margin-left:50px;"></div>
</apex:component>
The dojo.require function calls pull in the Dojo modules that are needed to support generation of the chart. You can learn more about dojo.require at the Sitepen web site.

The chart is rendered into the <div> element identified by the divId attribute of the component  - this allows for multiple pie charts to appear in the same page. The wedges of the pie are supplied via the chart.addSeries function.

Below is a screenshot of the default page:


As the chart is "live", Changing the values in the Chart Data table and clicking Update generates an updated chart based on the new data:


I've made this available as a Google Code project, and also submitted it as a developer force code share, but it looks like it takes a while to get accepted and added to the list of projects.

1 comment:

  1. Hi Bob,
    I didn't find controller for this page on google code project.
    Could you please provide controller for same?

    Thanks
    Sachin.

    ReplyDelete