Ext Charting and Mapping with Google Visualizations
October 13, 2008 by Aaron Conran
Creating cross-browser consistent visualizations of data without Adobe’s Flash plugin has always been a difficult issue to address. Google introduced a Visualization API earlier this year which enables you to present tabular data in the form of charts, maps, and other graphical representations without the need for Flash. (Some visualizations actually do use flash, but most are implemented with SVG and/or VML.)
Working with different API’s can present hurdles as we attempt to massage the same data in two different data structures – one for a grid and another for a pie chart. To address this specific challenge, I developed a short user extension Ext.ux.GVisualizationPanel enabling users to integrate visualizations into Ext JS applications without concern for these issues. The GVisualizationPanel adapts any Ext data Store into the google’s format and enables you to embed any type of visualization into a panel.
Adapting google’s DataTable to an Ext Store
All Google Visualization’s are backed by a google.visualization.DataTable. According to Google, “A DataTable is a two dimensional table, with rows and columns and cells. Each column has a defined data type.” Google’s DataTable and Ext’s data Store are analogous and serve similar purposes. Their primary purpose is to enable developers to manipulate data in a single place and drive your GUI from that data. In order to continue changing our data in a single place and avoid having to manually synchronize 2 data structures, we will need to create an adapter to convert any Ext Store to a Google Table.
Differences between Ext.data.Store and google.visualization.DataTable
A key difference between Ext’s Store and Google’s DataTable is that the Ext data Store only handles data & schema information. On the contrary, Google’s DataTable requires presentation information like Label’s. The Ext.ux.GDataTableAdapter eliminates any inconsistencies between the 2 API’s allowing you to apply the same store to a visualization as you would apply to an Ext GridPanel. Ext.data.Store provides the developer with more formats by choosing a JsonReader, XmlReader or ArrayReader. Google’s DataTable is limited to programmatically adding data via methods or loading data from a Google Spreadsheet. This makes the Ext.data.Store a more favorable data structure in most cases. A final difference between Ext.data.Store and Google DataTable is that they each use different data types.
Using the Adapter
By eliminating the differences between Store and Table with the adapter, a single Ext.data.Store can be bound to Ext components and Google Visualizations at the same time. The Organizational Chart sample demonstrates how to synchronize a Google OrganizationChart and an Ext grid by binding them to the same Ext.data.Store. The sample also demonstrates how to consume the ’select’ event exposed by the GVisualizationPanel. 
Adapting your existing Ext Store’s can be done with Ext.ux.GDataTableAdapter’s static adapt method.
var dataTable = Ext.ux.GDataTableAdapter.adapt({ store: myDs, columns: [{ dataIndex: 'yr', label: 'Year' },{ dataIndex: 'sales', label: 'Sales' },{ dataIndex: 'expenses', label: 'Expenses' }] });
Using the GVisualizationPanel
GVisualizationPanel works like any typical Ext.Panel and can partake in the container model and layout management. This means you can integrate it into your existing border layout or as a custom portlet. The class has been registered with the xtype of ‘gvisualization’. To use a visualization you will need to determine the visualizationPkg you’d like to use from Google. Then setup an appropriate store and pass in the visualizationPkg, store and columns configuration to create a new visualization.
For example, to create the Intensity Map used in the demo we can use the following code:
var countryStore = new Ext.data.SimpleStore({ fields: [{ name: 'Country', type: 'string' },{ name: 'pop', type: 'int' },{ name: 'area', type: 'int' }], data: [ ['CN', 1324, 9640821], ['IN', 1134, 3287263], ['US', 304, 9629091], ['ID', 232, 1904569], ['BR', 187, 8514877] ] }); var intensityMap = new Ext.ux.GVisualizationPanel({ id: 'intensityMap', visualizationPkg: 'intensitymap', title: 'Intensity Map Sample', store: countryStore, columns: ['Country',{ dataIndex: 'pop', label: 'Population (mil)' },{ dataIndex: 'area', label: 'Area (km2)' }] });
In Conclusion
Using the GDataTableAdapter to adapt or convert an Ext.data.Store to a google.visualization.DataTable is a good way to allow Ext Developers to use Google Visualizations without worrying about any underlying differences. Some of Google’s Visualizations have additional configuration options which can be used through a visualizationCfg configuration. GVisualizationPanel is a powerful implementation which supports any of the visualizations provided by Google in their gallery by simply setting a visualizationPkg config. Take a look at the many different types of visualizations available in Google’s Visualization Gallery.


Posted on October 13th, 2008 at 6:48 am
Thanks for sharing. I’m l’vin it!
Posted on October 13th, 2008 at 6:59 am
Excellent!
Posted on October 13th, 2008 at 8:02 am
Thanks Aaron Conran for sharing this.
Amjith PS
Googleknoltalk.com
Posted on October 13th, 2008 at 10:37 am
[...] Conran has developed a nice Ext extension to tie that world to the Google Visualization API: Working with different API’s can present hurdles as we attempt to massage the same data in two [...]
Posted on October 13th, 2008 at 1:03 pm
Thanks Aaron, Very cool integration.
Posted on October 13th, 2008 at 1:06 pm
[...] Conran has developed a nice Ext extension to tie that world to the Google Visualization API: Working with different API’s can present hurdles as we attempt to massage the same data in two [...]
Posted on October 13th, 2008 at 2:59 pm
Is is possible to render any of the Google Visualization widgets without sending application data to a Google server?
Posted on October 13th, 2008 at 3:29 pm
This is very nice. I like having the data in just one place. Great blog.
Posted on October 13th, 2008 at 5:00 pm
[...] Ext JS – Ext Charting and Mapping with Google Visualizations – Using the GDataTableAdapter to adapt or convert an Ext.data.Store to a google.visualization.DataTable is a good way to allow Ext Developers to use Google Visualizations without worrying about any underlying differences [...]
Posted on October 13th, 2008 at 5:01 pm
@seasharp2, Yes there are several Visualizations which never send any data to a Google server and generate all of their contents on the client-side. For each specific Visualization you can check out the Data Policy link found at the top of the Visualization page. You can see that the gauges are all generated client-side. Quoting Google “All code and data are processed and rendered in the browser. No data is sent to any server. ” On the flip side, there are certainly Visualizations which DO send data to Google’s servers.You will need to read the Data Policy for each visualization you would like to use.
Posted on October 13th, 2008 at 9:28 pm
thanks very much , this is just i want…
Posted on October 14th, 2008 at 2:28 am
[...] Aaron Conran posted an entry about Ext.ux.GVisualizationPanel, a user extension that takes advantage of the similarities between the Ext data store and Google’s data table to allow reuse of an Ext data store with Google’s Visualization API. [...]
Posted on October 14th, 2008 at 2:46 am
[...] Conran has developed a nice Ext extension to tie that world to the Google Visualization API: Working with different API’s can present hurdles as we attempt to massage the same data in two [...]
Posted on October 14th, 2008 at 6:06 am
@Aaron
Thanks for the Data Policy pointer. After following the Google App Engine project I have become a little circumspect about Google licensing and motives. However after scanning the Google visualizations gallery it seems most of the controls that interest me are client-side only
Annotated Time Line
http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html
Area Chart http://code.google.com/apis/visualization/documentation/gallery/areachart.html
Bar Chart
http://code.google.com/apis/visualization/documentation/gallery/barchart.html
Column Chart
http://code.google.com/apis/visualization/documentation/gallery/columnchart.html#Data_Policy
Gauge
http://code.google.com/apis/visualization/documentation/gallery/gauge.html#Data_Policy
Organizational Chart
http://code.google.com/apis/visualization/documentation/gallery/orgchart.html
Pie Chart
http://code.google.com/apis/visualization/documentation/gallery/piechart.html
Line Chart
http://code.google.com/apis/visualization/documentation/gallery/linechart.html
Scatter Chart
http://code.google.com/apis/visualization/documentation/gallery/scatterchart.html
Posted on October 14th, 2008 at 3:14 pm
Ext Charting and Mapping with Google Visualizations…
[...]Creating cross-browser consistent visualizations of data without Adobe’s Flash plugin has always been a difficult issue to address. Google introduced a Visualization API earlier this year which enables you to present tabular data in the form of ch…
Posted on October 15th, 2008 at 11:28 am
This is fantastic, however, it only works for a once off. I have a use-case where a combo box selects an item and then reloads the store to which the visualization is bound. This is easily (but lazily) fixed by adding the following:
Ext.ux.GVisualizationPanel = Ext.extend(Ext.Panel, {
// These are required by Google API
// To add more visualizations you can extend
// visualizationPkgs
visualizationAPI: ‘visualization’,
visualizationAPIVer: ‘1′,
visualizationPkgs: {
‘intensitymap’: ‘IntensityMap’,
‘orgchart’: ‘OrgChart’,
‘linechart’: ‘LineChart’,
‘gauge’: ‘Gauge’,
’scatterchart’: ‘ScatterChart’,
‘annotatedtimeline’: ‘AnnotatedTimeLine’
},
/**
* visualizationPkg {String}
* (Required) Valid values are intesitymap, orgchart, gauge and scatterchart
* The error “Module: ‘visualization’ with package: ” not found!” will be
* thrown if you do not use this configuration.
*/
visualizationPkg: ”,
/**
* html {String}
* Initial html to show before loading the visualization
*/
html: ‘Loading…’,
/**
* store {Ext.data.Store/String}
* Any valid instance of a store and/or storeId
*/
store: null,
// event handler for store
redraw: function(){
this.datatable = Ext.ux.GDataTableAdapter.adapt({
store: this.store,
columns: this.columns
});
this.visualization.draw(this.datatable, Ext.apply({}, this.visualizationCfg));
},
// Overriden methods
initComponent: function(){
if (typeof this.visualizationPkg === ‘object’) {
Ext.apply(this.visualizationPkgs, this.visualizationPkg);
for (var key in this.visualizationPkg) {
this.visualizationPkg = key;
break;
}
}
google.load(this.visualizationAPI, this.visualizationAPIVer, {
packages: [this.visualizationPkg],
callback: this.onLoadCallback.createDelegate(this)
});
this.store = Ext.StoreMgr.lookup(this.store);
// setup a listener on the store to enable reloading of data
this.store.on({
load: this.redraw,
datachanged: this.redraw,
add: this.redraw,
remove: this.redraw,
update: this.redraw,
clear: this.redraw,
scope: this});
Ext.ux.GVisualizationPanel.superclass.initComponent.call(this);
},
// custom methods
onLoadCallback: function(){
var tableCfg = {
store: this.store,
columns: this.columns
};
this.datatable = Ext.ux.GDataTableAdapter.adapt(tableCfg);
var cls = this.visualizationPkgs[this.visualizationPkg];
if (this.body) {
this.body.update(”);
this.visualization = new google.visualization[cls](this.body.dom);
var relaySelect = function(){
this.fireEvent(’select’, this, this.visualization);
};
google.visualization.events.addListener(this.visualization, ’select’, relaySelect.createDelegate(this));
this.visualization.draw(this.datatable, Ext.apply({}, this.visualizationCfg));
}
}
});
Ext.reg(’gvisualization’, Ext.ux.GVisualizationPanel);
Posted on October 15th, 2008 at 12:11 pm
Aaron-
Very nice work, I can already think of dozens of use for this ux. Thanks for sharing.
Posted on October 16th, 2008 at 8:38 pm
不错~
Posted on October 16th, 2008 at 8:46 pm
EXT的样式风格,看久会产生视觉疲劳。
让然非常的不舒服,最好有简约版本的,一是速度快,二是没有视觉疲劳感。
Posted on October 16th, 2008 at 10:40 pm
Very cool and timely indeed. I needed to use a timeline visualization recently and it made me look at several APIs and libraries and realized that the best way to implement it for my app was to build a ux for it, but with this I no longer have to bother. Very cool, thanks for sharing !!
Posted on October 17th, 2008 at 5:07 am
[...] en charge n’importe quelle type de données et les représenter avec les outils de Google : Ext Charting and Mapping with Google Visualizations. Le résultat est tout à fait intéressant : Ext [...]
Posted on October 17th, 2008 at 3:25 pm
Really, Great!
Conran is the best
Posted on October 29th, 2008 at 4:28 am
Great stuff. But we had to do the following change to get it working.
From:
var fld = store.fields.itemAt(j);
To:
var fld = store.fields.get(cols[j].dataIndex);
Also when working with Google AnnotatedTimeLine, we had to pass the following two additional configs
height: container.getInnerHeight(),
width: container.getInnerWidth(),
during Ext.ux.GVisualizationPanel instantiation.
Thanks
Mat
Posted on November 2nd, 2008 at 1:10 pm
Ext Charting and Mapping with Google Visualizations…
Creating cross-browser consistent visualizations of data without Adobe’s Flash plugin has always been a difficult issue to address. Google introduced a Visualization API earlier this year which enables you to present tabular data in the form of charts,…
Posted on November 5th, 2008 at 2:33 pm
Very cool, thank you for sharing this. I linked back to your blog through Ajax Rain. Wanted to comment here as well.
Posted on November 10th, 2008 at 12:18 pm
[...] Ext Charting and Mapping with Google Visualizations [...]
Posted on November 20th, 2008 at 1:26 am
Можно и поспорить по этому вопросу, ведь только в споре может быть достигнута истина.
Posted on November 27th, 2008 at 8:20 pm
[...] click here to see the complete example [...]
Posted on November 27th, 2008 at 8:44 pm
[...] click here to see the complete example Currently playing: Ext Charting and Mapping with Google Visualizations [...]
Posted on December 5th, 2008 at 3:26 am
И как автору не жалко столько времени на написание статей тратить, мы конечно очень благодарны, но вот я на такой альтруизм не способен
Posted on December 18th, 2008 at 3:00 am
Really, Great!
Conran is the best:)
Posted on January 17th, 2009 at 1:02 pm
Google make great things.
Posted on January 19th, 2009 at 9:42 pm
为什么字体都这么小呢?看起来太费力了!
Posted on January 30th, 2009 at 8:10 pm
[...] by: Flex (various plug-ins and Flex Charting), ExtJs (combined with GWT), Dojo, Google Web Toolkit, Prototype/script.aculo.us, JQuery (SWF/Gauge), MooTools, MochaUI, [...]
Posted on February 6th, 2009 at 6:31 pm
Quick question
I am concerned about this line
what if google decides to discontinue some of services/properties mentioned in it.
question is basically how far should I rely on above line.
NewToExt&LovinIT
Posted on February 6th, 2009 at 6:33 pm
Line is missed in above Q. is related to call to http://www.google.com/jsapi in script look up
Posted on February 21st, 2009 at 12:29 pm
Thanks for sharing
Posted on April 1st, 2009 at 4:07 pm
Is there a way to set the formatted value of an item when using a store instead of a DataTable? For example, when using the google.visualization.DataTable you can add a fourth parameter to setCell to define the formatted value of the cell:
data.setCell(1, 0, ‘Jim’,'jim’);
Posted on April 24th, 2009 at 3:59 am
[...] by: Flex (various plug-ins and Flex Charting), ExtJs (combined with GWT), Dojo, Google Web Toolkit, Prototype/script.aculo.us, JQuery (SWF/Gauge), MooTools, MochaUI, [...]
Posted on June 23rd, 2009 at 4:16 pm
I love Pligg sites, but modifying Pligg templates is always hard for me…
Posted on June 27th, 2009 at 5:57 am
thanks admin iyiydi saol sevdim seni böle adam olun hep :d
Posted on July 5th, 2009 at 12:29 pm
Finally found the info I needed thanks to your great blog, thanks! ^^
Posted on July 22nd, 2009 at 7:31 am
I had to do some hacking to get the class to work with a JsonStore instead of a static store. It seems that the google visualization is being rendered before the store has loaded its data.
To do this, I modified onLoadCallback to:
onLoadCallback: function() {
this.tableCfg = {
store: this.store,
columns: this.columns
};
var delegate = this.storeCallback.createDelegate(this);
this.store.load({ callback: delegate });
}
and put the rest of onLoadCallback’s logic in storeCallback. tableCfg becomes an object attribute instead of a local function variable as well.
Posted on September 7th, 2009 at 6:18 am
This componenet is really what we need… I wander, does it work with EXT 3.0? thank in advance