Google Chart Tools like scatter chart and gauge can be accessed as images or by API, and this article describes both approaches. The Google Chart Tools Image Charts let you dynamically generate charts as images using a URL string. You will see how to use the generated images as location markers on the IBM Mashup Center mapping widget. The Google Chart Tools API provides JavaScript classes that can be used to build highly interactive visualization. This article will show how to build a sample widget using the charting API that can display data from enterprise data feeds generated by the IBM Mashup Center.
This article assumes that you are already familiar with building mashups and feeds, as well as the basics of writing a widget. In particular, you should know how to program in JavaScript and have some experience using IBM Mashup Center. The "Creating a feed from an enterprise database" and "Developing widgets for IBM Mashup Center" articles in the Resources section provide introductory information that can help get you up to speed on some of the basics of building mashups.
Using chart images as markers on a map
The Navteq Map widget displays location information on a map. Typically,
the data source for the map is a feed that you either pull from a Web site
or from a feed that you create using the IBM Mashup Center set of feed
generators. The feed should be in RSS or ATOM format and each
entry element corresponds to one location to be
displayed on the map and should contain four elements specifying the
following:
- The Address or location of the marker
- The event data to be sent when the marker is clicked
- The information to display on the marker pop-up bubbles
- The icon (a small image) to be used as marker for this location/address
For the Icon element, the Navteq widget supports the use of simple numbers that refer to predefined icons supplied with the widget. These predefined icons include images typically used in maps to mark locations e.g. house, car, pin etc. However, users are not limited only to those predefined icons. The Navteq widget supports, in addition, the use of a URL in the Icon element that points to an arbitrary image. By using different URLs for different locations, the images could be dynamically generated and vary from location to location. For the images to work well, they should be small in size and have a transparent background. Figure 1 shows an example of using charts as icons in a map.
Figure 1. Charts as map markers
The chart icons identify customer locations. Each bar chart contains the sales amount for each year between 2008 to 2011. Any charting service that can dynamically generate charts as images could be used for this purpose. The following section shows you how to generate the map illustrated in Figure 1 using Google Image Charts.
It is assumed that you already have a feed that displays a list of customers on the Navteq map widget using the built-in static icons. You will use the IBM Mashup Center data Mashup Builder to modify the feed to use Google Image Charts as markers. See the Resources section for links to IBM Mashup Center documentation on the Navteq widget and the Data Mashup Builder.
Generating Google Image Charts URLs using Data Mashup Builder
The Google Chart Tools Image Chart returns a chart image in response to a URL GET or POST request. The API can generate many kinds of charts, from pie or line charts to QR codes and formulas. All the information about the chart such as chart data, size, colors, and labels, are part of the URL. For example, the following is the URL for one of the chart images shown previously in Figure 1. The URL in Listing 1 was split into multiple lines so it can fit on the page.
Listing 1. An example of Google Image Charts URL
http://chart.apis.google.com/chart?chl=|||&chco=ff0000|0000ff|800000|00ff00
&cht=bvs&chs=40x40&chbh=3,2,3
&chds=0,2000&chf=bg,s,FFFFFF00
&chd=t:1735.92,1335.08,1582.08,1555.08
|
The URL parameters used in Listing 1 are explained as follows.
- chl=||| - specifying empty string for labels to suppress them.
- chco=ff0000|0000ff|800000|00ff00 - the color for the four bars corresponding to 2008,2009,2010,2011 respectively.
- cht=bvs - vertical bar chart.
- chs=40x40 - the size of the generated image. This could even be made to vary based on total sales.
- chbh=3,2,3 - the width of each bar, space between bars and space between groups. All in number of pixels. In the example, the last value is not used even though it must still be specified.
- chf=bg,s,FFFFFF00 - the white background is to be made transparent.
- chs=0,2000 - the data range.
- chd=t:1735.92,1335.08,1582.08,1555.08 - the comma-separated list of values to chart.
The URL parameter names are abbreviated, but they are fairly easy to figure out. They all start with the ch prefix. For example, the one specifying label ends with l; the one specifying the chart type ends with t. The Resources section contains links to the Google Charts documentation.
Most of the URL parameters are the same for all chart images appearing in
the previous sample map and they are hard coded. The only part of the URL
which varies from customer to customer is the height of each bar
corresponding to the sales amount for each of the four years from 2008 to
2011. In the URL shown in Listing 1, the sales amounts are the comma
separated numbers in the parameter
chd=t:1735.92,1335.08,1582.08,1555.08. You will
see how the chd parameter could be generated
dynamically.
Data Mashup to generate Chart Images URLs
The data mashup to generate the Google Image Charts URLs is fairly simple and it uses the following two input feeds.
- An ATOM feed in Navteq widget format where each
entryelement corresponds to a customer. As shown in Listing 2, it is also assumed that each entry carries with it the customer ID.
Listing 2. ATOM feed in Navteq widget format<feed xmlns="http://www.w3.org/2005/Atom"> :::::::::: <entry><content> <Info>IBM<br>555 Bailey Avenue San Jose CA</Info> <Data>1060</Data> <Address>-121.7484391,37.1954075</Address> <Icon>1</Icon> </content></entry> ::::::::::::::::: </feed>
Note that in the previous example, the customer ID is carried in theDataelement, and is the event data that is passed to other widgets when the marker is clicked. - An ATOM feed containing yearly sales from 2008 to 2011 parameterized
by customer ID, as shown in Listing 3.
Listing 3. Parameterized ATOM feed for yearly sales<feed xmlns="http://www.w3.org/2005/Atom"> :::::::::: <entry>:::<content><year>2008</year><totalAmt>1735.92</totalAmt></content></entry> <entry>:::<content><year>2009</year><totalAmt>1335.08</totalAmt></content></entry> <entry>:::<content><year>2010</year><totalAmt>1582.08</totalAmt></content></entry> <entry>:::<content><year>2011</year><totalAmt>1555.08</totalAmt></content></entry> </feed>
On a high level, the Data Mashup shown in Figure 2 will add/modify the Icon
element in each entry of the Navteq widget
feed. It will dynamically generate a Google Image Charts URL using the
sales data for each customer. The data from the two input feeds are
brought into the Builder using two Source
operators.
Figure 2. Data Mashup for Chart Images as markers
The default Repeating Entry (on the Advanced Tab
of the Source operator) in the yearly sales feed is changed from
entry to feed. They
are then both connected to a ForEach operator.
Ensure that the Navteq widget formatted feed is the master and the yearly
sales feed is the detail feed. For each entry
element in the master feed, the customer ID is passed as parameter to the
detail feed to retrieve the sales data for that customer. These three
operators are shown on the left of Figure 2, shown previously.
The ForEach operator will inject the complete
sales feed for each customer into each entry
element. The output of the ForEach operator is
then passed to the Transform operator. As shown
in Figure 3, you can see the structure of the
entry element injected by the
ForEach operator on the right (Input) side of
the Transform operator.
Figure 3. Transform operator for each customer location entry
You are now ready to generate the Google Image Charts URLs.
Generating the chd URL parameter
Generating the constant part of the Google Image Charts URLs is simple. Use
the concat function and provide the chart URL
parameters as one or more text strings. Remember, you have injected the
complete feed with multiple entries, each containing the sales amount for
the year from 2008 to 2011. The tricky part is to convert the sales
amounts appearing as text from the four separate
entry elements into a single comma-separated
string. This is done by using the String-join
function as shown in Figure 4. You just need to select the element
containing the sales amount as the first argument to the
String-join function and specify comma as the
second parameter.
Figure 4. String-join function to get sales amount as comma separated list
This completes the data mashup and you can see the output in Listing 4.
Listing 4. Output from data mashup
<feed xmlns="http://www.w3.org/2005/Atom">
::::::::::
<entry><content>
<Info>IBM<br>555 Bailey Avenue San Jose CA</Info>
<Data>1060</Data>
<Address>-121.7484391,37.1954075</Address>
<Icon>
http://chart.apis.google.com/chart?chl=|||& ... &chd=t:1735.92,1335.08,1582.08,1555.08
</Icon>
</content></entry>
:::::::::::::::::
</feed>
|
You can find a version similar to what is previously described built out on Lotus Greenhouse.
The Google Image Chart works great but requires data to be sent to the Google server for rendering. This might not be appropriate for all applications. Google Chart Tools also provide a JavaScript charting API package that, for most of the common chart types, render the visualization on the browser without having to send the data to the Google server.
In addition, the JavaScript charting API package can expose events that enable you to connect them to other widgets to create complex mashup applications. In the Resources section, you can find the link to the Google Charts API documentation. According to the documentation, charts are rendered using HTML5/SVG technology to provide cross-browser compatibility (including VML for older IE versions), and cross platform portability to iPhones, iPads and Android.
For the remainder of the article shows the process of building a very simple widget that wraps the Google Charting JavaScript package. Again, it is assumed that you are familiar with the basics of developing an iWidget. If you are interested in using the widget, you can download the widget from Downloads section, and skip to the next section.
A simple widget that integrates with Google Chart Tools API
A widget is specified by its definition XML file. Listing 5 shows the more important section from the widget definition XML file.
Listing 5. Excerpt from widget definition XML file
<iw:iwidget name="sample.mashupcenter.GoogleChart"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
allowInstanceContent="true"
supportedModes="view edit"
mode="view"
iScope="sample.mashupcenter.GoogleChart"
lang="en">
<iw:resource uri="GoogleChart.js" />
<iw:event id="DataUrl" eventDescName="DataUrlDesc"
handled="true" onEvent="handleDataURL" />
<iw:eventDescription id="DataUrlDesc" payloadType="text"
description="Url to retrieve Data" lang="en" />
<iw:event eventDescName="desc_chartClicked" id="chartClicked"
published="true"/>
<iw:eventDescription lang="en" id="desc_chartClicked"
description="A part of the chart was clicked" payloadType="text"/>
<iw:content mode="view">
<![CDATA[
<div id="_IWID_ChartArea"></div>
]]>
</iw:content>
|
The iWidget's iScope attribute defines the name
of the JavaScript Dojo class that implements the widget. The
iresource element specifies the JavaScript file
containing the Dojo class specified in the
iScope attribute. Files specified using the
iresource element will be loaded before the
widget is instantiated. The following two events are defined.
- DataUrl - the event has the attribute called
handledwhich indicates it as a receive event for changing the charting data URL. The attributeonEventdefines the JavaScript method that handles reloading the data when it receives a new URL. This allows the widget to change what is charted dynamically. - chartClicked - the event has the attribute
publishedwhich indicates that it is a send event. As the name suggests, it will be fired when the chart is clicked.
The content element with mode attribute set to
view defines the HTML area for displaying the chart in view mode. It is
very simple and consists of an empty div. Note that it has an ID attribute
consisting of the string _IWID_ChartArea. The
special _IWID_ prefix will be replaced with the actual widget instance ID
generated by the framework when the widget is instantiated. This covers
the most important part of the definition file. You can see the complete
widget definition XML and JavaScript file by downloading the widget zip
file from the Downloads section.
The following section explains JavaScript implementation.
Downloading Google Chart Tools API packages
The first thing you need to do in the JavaScript implementation of the widget is to download the JavaScript package from Google. There are two libraries involved.
- The Google AJAX API library - This API is used to load other libraries and handle some core functionality such as event handling. This JavaScript library is a common API used to load the Google Visualization library and other Google libraries like Search and Data API as well.
- The Google Visualization libraries - The corechart library includes common classes and methods used to create and handle visualizations. It also includes several common chart classes for Pie and Bar etc. For your purpose, you will also be downloading the additional libraries for geochart and gauge.
The first package, Google AJAX API, is downloaded dynamically by inserting
a script tag to the mashup page, and is not
elaborated upon further here. You can see how this is done by looking at
the GoogleChart.js implementation file. To download the Google
Visualization libraries, as explained previously, you need to download it
using the Google AJAX API. This is done in the
_loadVisualization function shown in Listing
6.
Listing 6. loadVisualization function
_loadVisualization: function()
{
if ( !window[ 'google'] ) {
setTimeout( dojo.hitch( this, this._loadVisualization), 500);
} else {
try {
// Load the Visualization API corechart package developed by Google.
// Set a callback to run when the Google Visualization API is loaded.
google.load( 'visualization', '1'
, { 'callback' : dojo.hitch(this, this._doneLoading)
, 'packages':['corechart', 'geochart' , 'gauge']}
);
// google.setOnLoadCallback( dojo.hitch(this, this._doneLoading) );
} catch ( e ) {
this.debugTrace("GoogleChart _loadVisualization exception=" + e.message );
}
}
},
|
First thing to note in the previous function is that you have to test and
make sure the Google AJAX API
(if ( !window[ 'google'] )) has been loaded
before you could use google.load to download
the visualization libraries. If not, you need to set a timer and wait for
the downloading to complete before trying again. The other thing to note
is that you need to specify the callback in your call to
google.load rather than making a separate call
to google.setOnLoadCallback.
Widget configuration and rendering
Once all the necessary libraries have been loaded, creating the visualization is fairly straightforward. you just need to know the type of visualization, where to get the input data and customizations like title, color, and so on. Figure 5 shows the HTML form for collecting this configuration information in Edit mode. The HTML fragment that generates the form is contained in the widget definition file, which was part of the detail that was skipped over.
Figure 5. Configuration gathered in Edit settings
Most charting package provides a wide range of options for customizing the visualization. Google Chart Tools API is no different. Given the large number of options available, you can choose to provide individual UI controls for entering these values. Instead, a text box is provided here to enter the charting options as a JSON string. Consult the documentation for each chart type to determine what options are available. You can find links to the charting documentation and the JSON format in the Resources section.
Assuming that the configuration information is provided, you render the
desired visualization in the _drawChart
function shown in Listing 7. It first calls the convenience function
createVisualizationObj to create an instance of
the Google visualization object of the specified chart type. According to
the Google Chart API documentation, "There is one event that any
selectable chart should fire: the select event." To listen to the select
event, register _cbSelectHandler to the Google
visualization object as the select event callback function. Next, the
chart options JSON string is parsed by calling the
dojo.fromJson function to convert it into a
JavaScript object. Finally, the chart is rendered by calling the draw
method with the data and the chart options as parameters.
Listing 7. _drawChart function
// called when data received or onSizeChange
_drawChart: function( )
{
::::::::::::::::::::
this.googleVisObj = this.createVisualizationObj( this.ChartType );
// "select" is the only event common to all visualization
google.visualization.events.addListener( this.googleVisObj
, 'select'
, dojo.hitch(this,this._cbSelectHandler));
:::::::::::::::::::::
var options = dojo.fromJson( this.ChartOption );
options.width = this.width;
options.height = this.height;
::::::::::::::::::::
this.googleVisObj.draw(this.gDataTable, options );
::::::::::::::::::::
},
|
The select handler function _cbSelectHandler is
called whenever a selectable part of the chart is clicked. Unlike other
Google Chart events, the handler function is not called with any
parameter. To find out what has been selected, the
getSelection() on the Google Visualization
object needs to be called to retrieve an array of objects describing the
selected data elements. Besides the pies in a Pie chart or the bars in a
Bar chart, other components such as the legend could be selectable as
well. In the current implementation, only a selection of visual elements
corresponding to a single cell in the data is supported. As shown in
Listing 8, cell refers to a cell in a table which is the input
data format for all chart types.
Listing 8. Handler function
// The select event does not pass any properties or objects to the handler
_cbSelectHandler: function( ) {
this.debugTrace( "GoogleChart select event" );
var selections = this.googleVisObj.getSelection();
if ( !selections || selections.length < 1 ) return; // ignore if nothing selected
// pick first of returned object array describing the selected data elements
var selection = selections[0];
// If both row and column are specified, the selected element is a cell.
// If only row is specified, the selected element is a row. If only column
// is specified, the selected element is a column.
// we will only handle cell i.e. not legend selection which returns the column
// use typeof to handle 0 being a legitimate return value!
if ( typeof( selection.row ) != undefined
&& typeof( selection.column ) != undefined ) {
// first column, index 0, is always x value
var eventData = this.gDataTable.getValue( selection.row, 0 );
this.iContext.iEvents.fireEvent( "chartClicked", null, eventData );
}
},
|
To determine if a cell is clicked or selected, verify that the returned
selection object has both row and
column property. In this implementation, the
first column from the row identified by the selection object is returned
as event data of the chartClicked event.
As mentioned in the preceding section, all charts accept their data in a
table. Each column is of a single data type which must be explicitly
specified. Consistent with all other out-of-the-box widgets, the Google
Chart widget described here will accept any Atom feed as input. What is
different here is the requirement of an additional
metadata element added to the root
feed element. The child elements of the
metadata element must be a subset of the
elements contained in each entry/content
element of the feed. Listing 9 shows the input feed for the GeoMap example
that is described in the Using the Google Chart widget
to create a GeoMap section.
Listing 9. ATOM feed for the GeoMap
<feed xmlns="http://www.w3.org/2005/Atom">
::::::::::::::::::::
<metadata>
<Country>string</Country>
<Popularity>number</Popularity>
</metadata>
<entry>
<content>
<Country>United States</Country>
<Popularity>430</Popularity>
</content>
</entry>
::::::::::::::::::::::::::::::
</feed>
|
Note that the order of occurrence of the child elements must be the same,
and the value can be either string or
number. Additional data types like
date or time are
currently not supported. The data type information and the actual data in
each entry of the ATOM feed needs to be extracted and converted into a
Google DataTable object, the format required by the Google Visualization
package. This is done in the function
dataFromNodeList which is partially shown in
Listing 10. Since the logic is fairly straight forward, it will not be
elaborated further here.
Listing 10. dataFromNodeList
dataFromNodeList: function( nodeList, columnList )
{
var dataTab = new google.visualization.DataTable();
for ( var k = 0 ; k < columnList.length ; k++ )
dataTab.addColumn( columnList[k].type, columnList[k].name );
:::::::::::::
}
|
You can find the complete implementation by downloading the widget zip file from the Downloads section. The widget zip file also contains a readme file with additional usage information. This completes the brief description of the internals of the Google Chart widget. The next section describes how to use the widget.
Using the Google Chart widget to create a GeoMap
In this section, you want to display data related to coffee consumption in selected countries using the Google Chart widget. The sample data is contained in a CSV file called Coffee_Popularity.csv, included in the Downloads section.
- Upload the CSV file and create an ATOM feed using the IBM Mashup Center (IMC). To use the ATOM feed as input to the Google Chart widget, you need to add a metadata section as previously shown in Listing 9. You can easily do this using the Data Mashup Builder.
- As shown in Figure 6, to create the data mashup, use a Source operator
to bring the CSV feed that you created earlier into the editor.
Connect the Source operator to the Publish operator, where the
required <metadata> section for the Google
Chart widget can be created.
Figure 6. Simple Data Mashup to create the ATOM feed required for the Google Chart widget
- Starting with IMC v3.0, the Publish operator allows you to create any
desired XML formats, either by manually adding elements to the final
output tree or importing an existing template. In this exercise, since
only three elements and the corresponding text nodes need to be
created, you can do them manually. As shown in Figure 7, click
Publish properties and select
Custom for Header, and ATOM for
Feed Type sections. Right-click the root element, in this case
<feed>, and select New
Element to create the <metadata>
element. Press Enter.
Figure 7. Publish operator, create a <metadata> element
- Follow the same pattern to create the child elements. Right-click the
<metadata> element and create the child
elements <Country> and
<Popularity> as shown in Figure 8.
Figure 8. Publish operator, create child elements under <metadata> element
- As shown in Figure 9, right-click the <Country>
and <Popularity> elements, select New
Text, and add a text node under each of them.
Figure 9. Publish operator, create text nodes under child elements
- As shown in Figure 10, create text node string for
<Country>, and for
<Popularity> create it as
number.
Figure 10. Publish operator, text node creation
- The <metadata> section in the feed header has
now been created. You now need to attach the repeating elements coming
from the previous operator to complete the feed. This can be done by
right-clicking the <feed> (root element) and
selecting Attach repeating element, as shown in
Figure 11. Select the entry element in the subsequent
dialog, and then click Attach to complete the task.
The repeating elements are now attached and are part of the final
feed.
Figure 11. Publish operator, attach repeating element
Furthermore, you may choose to update the <title> element under the <feed> element to give a name for the ATOM feed. This completes the feed creation, and the generated output was shown previously in Listing 9.
Note: For large feeds with many elements, it is a good idea to execute the feed first and copy one of the entries into a text editor, and then use that to create a XML template first with the <metadata> section. Then import this XML template into the Publish operator and attach the repeating entries from the previous operator to complete the feed. - Now that the feed is ready, it is time to render the feed in the
Google Chart widget. Create a page in the Mashup Builder and add the
Google Chart widget to the page. Go to the widget settings and add the
URL for the data mashup created previously to the Data
URL section. From the Chart Type
drop-down, select Geo Chart. Finally in the
Chart Options section, add the required JSON to
customize the Geo Map and save the widget settings. Use
{backgroundColor:"#CFECEC"}as the JSON to provide a background color to the chart. There are many chart options that could be provided as JSON. Please refer to the Google Geo Chart docs in the Resources section for more details. Figure 12 shows what the rendered widget will look like.
Figure 12. Geo map rendered in Google Chart widget
As seen previously, creating the ATOM feed to render in a Google Chart widget is simple. Moreover, the same format can be used to render other chart types. Figure 13 shows additional charting examples using the same data mashup feed.
Figure 13. Different chart types rendered in Google Chart widget using the same feed
These charts are created just by selecting a different chart type in theEdit settingsdialog of the widget!
This article took you through the basic steps of using the Data Mashup Builder to generate Google Chart Image URLs as well as data feeds for the Google Chart widget. You now have additional visualization options beyond what is available with the out-of-the-box widgets.
For those who would like to try widget development, there are many potential areas for improving the widget. As a start, the Google Chart Tools API has additional visualization libraries not included in this package. The widget could be changed to load them in. Another improvement would be the inclusion of charting options in the data feed allowing for dynamic generation. This would allow attributes like title to vary with input parameters.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample for this article | GoogleChartDownloadPkg.zip | 10KB | HTTP |
Information about download methods
Learn
- Review the Google Geo Chart docs to see the chart options for JSON.
- Visit Google Chart Tools:
Image Charts to find out what image chart types are supported and
the URL parameters for each type.
- Learn how to use the Navteq widget to display markers on a map using an ATOM feed
- Read the IBM Mashup Center and the InfoSphere MashupHub, Part 2: In-depth look
at Feed Mashup Editor within IBM Mashup Center's InfoSphere
MashupHub article for a detailed introduction on how to use the
data mashup editor.
- Visit Google Chart Tools: API
to learn how to invoke the API and interact with the chart object.
- The Wikipedia JSON page is a
good introduction to the JSON format.
- Read Mashup, beyond Reporting to learn how to build light-weight
widgets.
- For a good introduction to writing a
custom widget, read the article Developing widgets for IBM Mashup Center 1.0.
- To learn about Dojo, see The Official Dojo Documentation
Web page.
- Follow the link to the latest widget programming and API documentation.
- Get the resources you need in the Information Management
area on developerWorks, to advance your skills on a wide variety
of IBM Information Management products.
- Learn more about Information Management at
the developerWorks
Information Management zone. Find technical documentation, how-to
articles, education, downloads, product information, and more.
- Follow developerWorks on
Twitter.
- Watch developerWorks on-demand demos
ranging from product installation and setup demos for beginners, to
advanced functionality for experienced developers.
Get products and technologies
- To get hands-on
experience with IBM Mashup Center, visit Lotus
greenhouse.
- Download a free
trial version of IBM Mashup Center from developerWorks.
- Build your next
development project with IBM trial
software, available for download directly from developerWorks, or
spend a few hours in the SOA Sandbox learning how to
implement Service Oriented Architecture efficiently.
Discuss
- Check out the developerWorks
blogs and get involved in the developerWorks
community.
Louis Mau is part of the InfoSphere MashupHub development team. His current focus is to help customers build situational applications using the IBM Mashup Center. Prior to this role, he was the architect for DB2 Everyplace Sync Server, which helps synchronize data from enterprise databases onto a small foot print database running on mobile devices.




