代码示例

以下是一些代码示例,演示了如何使用 Google Visualization API。

表示例

function drawTable() {
 
var data = new google.visualization.DataTable();
  data
.addColumn('string', 'Name');
  data
.addColumn('number', 'Salary');
  data
.addColumn('boolean', 'Full Time');
  data
.addRows(5);
  data
.setCell(0, 0, 'John');
  data
.setCell(0, 1, 10000, '$10,000');
  data
.setCell(0, 2, true);
  data
.setCell(1, 0, 'Mary');
  data
.setCell(1, 1, 25000, '$25,000');
  data
.setCell(1, 2, true);
  data
.setCell(2, 0, 'Steve');
  data
.setCell(2, 1, 8000, '$8,000');
  data
.setCell(2, 2, false);
  data
.setCell(3, 0, 'Ellen');
  data
.setCell(3, 1, 20000, '$20,000');
  data
.setCell(3, 2, true);
  data
.setCell(4, 0, 'Mike');
  data
.setCell(4, 1, 12000, '$12,000');
  data
.setCell(4, 2, false);

 
var table = new google.visualization.Table(document.getElementById('table_div'));
  table
.draw(data, {showRowNumber: true, width: '100%', height: '100%'});

  google
.visualization.events.addListener(table, 'select', function() {
   
var row = table.getSelection()[0].row;
    alert
('You selected ' + data.getValue(row, 0));
 
});
}

自定义表格示例


<style>
 
.bold-green-font {
   
font-weight: bold;
   
color: green;
 
}

 
.bold-font {
   
font-weight: bold;
 
}

 
.right-text {
   
text-align: right;
 
}

 
.large-font {
   
font-size: 15px;
 
}

 
.italic-darkblue-font {
   
font-style: italic;
   
color: darkblue;
 
}

 
.italic-purple-font {
   
font-style: italic;
   
color: purple;
 
}

 
.underline-blue-font {
   
text-decoration: underline;
   
color: blue;
 
}

 
.gold-border {
   
border: 3px solid gold;
 
}

 
.deeppink-border {
   
border: 3px solid deeppink;
 
}

 
.orange-background {
   
background-color: orange;
 
}

 
.orchid-background {
   
background-color: orchid;
 
}

 
.beige-background {
   
background-color: beige;
 
}

</style>

...

function drawTable() {
  var cssClassNames = {
    'headerRow': 'italic-darkblue-font large-font bold-font',
    'tableRow': '',
    'oddTableRow': 'beige-background',
    'selectedTableRow': 'orange-background large-font',
    'hoverTableRow': '',
    'headerCell': 'gold-border',
    'tableCell': '',
    'rowNumberCell': 'underline-blue-font'};

  var options = {'showRowNumber': true, 'allowHtml': true, 'cssClassNames': cssClassNames};

  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Name');
  data.addColumn('number', 'Salary');
  data.addColumn('boolean', 'Full Time');
  data.addRows(5);
  data.setCell(0, 0, 'John');
  data.setCell(0, 1, 10000, '$10,000', {'className': 'bold-green-font large-font right-text'});
  data.setCell(0, 2, true, {'style': 'background-color: red;'});
  data.setCell(1, 0, 'Mary', null, {'className': 'bold-font'});
  data.setCell(1, 1, 25000, '$25,000', {'className': 'bold-font right-text'});
  data.setCell(1, 2, true, {'className': 'bold-font'});
  data.setCell(2, 0, 'Steve', null, {'className': 'deeppink-border'});
  data.setCell(2, 1, 8000, '$8,000', {'className': 'deeppink-border right-text'});
  data.setCell(2, 2, false, null);
  data.setCell(3, 0, 'Ellen', null, {'className': 'italic-purple-font large-font'});
  data.setCell(3, 1, 20000, '$20,000');
  data.setCell(3, 2, true);
  data.setCell(4, 0, 'Mike');
  data.setCell(4, 1, 12000, '$12,000');
  data.setCell(4, 2, false);
  var container = document.getElementById('table');
  var table = new google.visualization.Table(container);
  table.draw(data, options);
  table.setSelection([{'row': 4}]);
}

采样平均值示例

温度:

<html>
 
<head>
 
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
 
<script type="text/javascript">
    google
.charts.load('current', {'packages':['gauge']});
    google
.charts.setOnLoadCallback(drawGauge);

   
var gaugeOptions = {min: 0, max: 280, yellowFrom: 200, yellowTo: 250,
      redFrom
: 250, redTo: 280, minorTicks: 5};
   
var gauge;

   
function drawGauge() {
      gaugeData
= new google.visualization.DataTable();
      gaugeData
.addColumn('number', 'Engine');
      gaugeData
.addColumn('number', 'Torpedo');
      gaugeData
.addRows(2);
      gaugeData
.setCell(0, 0, 120);
      gaugeData
.setCell(0, 1, 80);

      gauge
= new google.visualization.Gauge(document.getElementById('gauge_div'));
      gauge
.draw(gaugeData, gaugeOptions);
   
}

   
function changeTemp(dir) {
      gaugeData
.setValue(0, 0, gaugeData.getValue(0, 0) + dir * 25);
      gaugeData
.setValue(0, 1, gaugeData.getValue(0, 1) + dir * 20);
      gauge
.draw(gaugeData, gaugeOptions);
   
}
 
</script>
 
</head>
 
<body>
 
<div id="gauge_div" style="width:280px; height: 140px;"></div>
 
<input type="button" value="Go Faster" onclick="changeTemp(1)" />
 
<input type="button" value="Slow down" onclick="changeTemp(-1)" />
 
</body>
</html>


互动示例

此示例演示了如何结合使用可视化图表来实现更复杂的互动。
该示例演示了以下功能:

  • 如何使用 DataView 对象限制 DataTable 中的数据并为其设置格式,
  • 如何将两个可视化图表与相同的数据相关联,
  • 如何使用表格可视化图表的 'sort' 事件,
  • 如何使用格式设置工具重新设置显示的数据的格式。

点击表格的标题,查看系统同样对柱形图进行排序。

请注意,通过控件和信息中心,您可以将多个图表与控件结合使用,从而对图表中显示的数据进行操控。

function drawSort() {
 
var data = new google.visualization.DataTable();
  data
.addColumn('string', 'Name');
  data
.addColumn('number', 'Salary');
  data
.addColumn('boolean', 'Full Time');
  data
.addRows(5);
  data
.setCell(0, 0, 'John');
  data
.setCell(0, 1, 10000);
  data
.setCell(0, 2, true);
  data
.setCell(1, 0, 'Mary');
  data
.setCell(1, 1, 25000);
  data
.setCell(1, 2, true);
  data
.setCell(2, 0, 'Steve');
  data
.setCell(2, 1, 8000);
  data
.setCell(2, 2, false);
  data
.setCell(3, 0, 'Ellen');
  data
.setCell(3, 1, 20000);
  data
.setCell(3, 2, true);
  data
.setCell(4, 0, 'Mike');
  data
.setCell(4, 1, 12000);
  data
.setCell(4, 2, false);

 
var view = new google.visualization.DataView(data);
  view
.setColumns([0, 1]);

 
var formatter = new google.visualization.NumberFormat({prefix: '$'});
  formatter
.format(data, 1); // Apply formatter to second column

 
var table = new google.visualization.Table(document.getElementById('table_sort_div'));
  table
.draw(data, {width: '100%', height: '100%'});

 
var chart = new google.visualization.BarChart(document.getElementById('chart_sort_div'));
  chart
.draw(view);

  google
.visualization.events.addListener(table, 'sort',
     
function(event) {
        data
.sort([{column: event.column, desc: !event.ascending}]);
        chart
.draw(view);
     
});
}

完整 HTML 网页示例

介绍如何创建嵌入可视化图表的网页的端到端示例。 还演示了一个关联到 Google 电子表格的图表,以及两个使用可视化事件互动的图表。

该示例显示了一家虚构的连锁电影院的热门电影和电影院地点的简单统计信息页面。

该页面包含一个地图表格可视化图表,它们会相互交互以显示电影院的位置。此页面包含一个柱形图,显示每个营业地点的每部电影售票数量。它的数据源自 Google 电子表格。 您可以查看此电子表格的已发布版本,以确保完整性。

<html>
 
<head>
   
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
   
<script type="text/javascript">
      google
.charts.load('current', {
       
'packages': ['table', 'map', 'corechart'],
       
// Note: you will need to get a mapsApiKey for your project.
       
// See: https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings
       
'mapsApiKey': 'AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY'
     
});
      google
.charts.setOnLoadCallback(initialize);

     
function initialize() {
       
// The URL of the spreadsheet to source data from.
       
var query = new google.visualization.Query(
           
'https://spreadsheets.google.com/pub?key=pCQbetd-CptF0r8qmCOlZGg');
        query
.send(draw);
     
}

     
function draw(response) {
       
if (response.isError()) {
          alert
('Error in query');
       
}

       
var ticketsData = response.getDataTable();
       
var chart = new google.visualization.ColumnChart(
            document
.getElementById('chart_div'));
        chart
.draw(ticketsData, {'isStacked': true, 'legend': 'bottom',
           
'vAxis': {'title': 'Number of tickets'}});

       
var geoData = google.visualization.arrayToDataTable([
         
['Lat', 'Lon', 'Name', 'Food?'],
         
[51.5072, -0.1275, 'Cinematics London', true],
         
[48.8567, 2.3508, 'Cinematics Paris', true],
         
[55.7500, 37.6167, 'Cinematics Moscow', false]]);

       
var geoView = new google.visualization.DataView(geoData);
        geoView
.setColumns([0, 1]);

       
var table =
           
new google.visualization.Table(document.getElementById('table_div'));
        table
.draw(geoData, {showRowNumber: false, width: '100%', height: '100%'});

       
var map =
           
new google.visualization.Map(document.getElementById('map_div'));
        map
.draw(geoView, {showTip: true});

       
// Set a 'select' event listener for the table.
       
// When the table is selected, we set the selection on the map.
        google
.visualization.events.addListener(table, 'select',
           
function() {
              map
.setSelection(table.getSelection());
           
});

       
// Set a 'select' event listener for the map.
       
// When the map is selected, we set the selection on the table.
        google
.visualization.events.addListener(map, 'select',
           
function() {
              table
.setSelection(map.getSelection());
           
});
     
}
   
</script>
 
</head>

 
<body>
   
<table align="center">
     
<tr valign="top">
       
<td style="width: 50%;">
         
<div id="map_div" style="width: 400px; height: 300;"></div>
       
</td>
       
<td style="width: 50%;">
         
<div id="table_div"></div>
       
</td>
     
</tr>
     
<tr>
       
<td colSpan=2>
         
<div id="chart_div" style="align: center; width: 700px; height: 300px;"></div>
       
</td>
     
</tr>
   
</table>

 
</body>
</html>

查询封装容器示例

此示例演示了如何创建可为您发送查询的许多方面的 JavaScript 对象。该对象名为 QueryWrapper,使用查询字符串、可视化图表句柄和一组可视化图表选项进行实例化。它向外部调用方公开一种方法,即 sendAndDraw(),该调用会发送查询字符串、处理响应,并针对可视化图表调用 draw(),或者在查询返回错误时显示错误消息。此处的托管页面会以组织结构图可视化图表显示结果。

以下是托管网页的代码:

<!DOCTYPE html>
<html>
<head>
 
<title>Query Wrapper Example</title>
 
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
 
<script type="text/javascript" src="querywrapper.js"></script>
 
<script type="text/javascript">
    google
.charts.load('current', {'packages' : ['orgchart']});
    google
.charts.setOnLoadCallback(function() { sendAndDraw('') });

   
var dataSourceUrl = 'https://spreadsheets.google.com/tq?key=rCaVQNfFDMhOM6ENNYeYZ9Q&pub=1';
   
var query;

    function sendAndDraw(queryString) {
     
var container = document.getElementById('orgchart');
     
var orgChart = new google.visualization.OrgChart(container);
      query
&& query.abort();
      query
= new google.visualization.Query(dataSourceUrl + queryString);
     
var queryWrapper = new QueryWrapper(query, orgChart, {'size': 'large'}, container);
      queryWrapper
.sendAndDraw();
   
}


 
</script>
</head>

<body>
<h1>Query Wrapper Example</h1>
<form action="">
 
<span> This example uses the following spreadsheet: <br />
   
<a href="https://spreadsheets.google.com/pub?key=rCaVQNfFDMhOM6ENNYeYZ9Q">
      https://spreadsheets.google.com/pub?key=rCaVQNfFDMhOM6ENNYeYZ9Q
   
</a></span>
 
<br /><br />
 
<select onChange="sendAndDraw(this.value)">
   
<option value="">No query string</option>
   
<option value="&tq=limit 3">query=limit 3</option>
   
<option value="&tq=select G,H">(Error) query=select G,H</option>
 
</select>
</form>
<br />
<div id="orgchart"></div>
</body>
</html>

以下是 QueryWrapper 对象的 JavaScript。

/**
 * A google.visualization.Query Wrapper. Sends a
 * query and draws the visualization with the returned data or outputs an
 * error message.
 *
 * DISCLAIMER: This is an example code which you can copy and change as
 * required. It is used with the google visualization API which is assumed to
 * be loaded to the page. For more info see:
 * https://developers.google.com/chart/interactive/docs/reference#Query
 */



/**
 * Constructs a new query wrapper with the given query, visualization,
 * visualization options, and error message container. The visualization
 * should support the draw(dataTable, options) method.
 * @constructor
 */

var QueryWrapper = function(query, visualization, visOptions, errorContainer) {

 
this.query = query;
 
this.visualization = visualization;
 
this.options = visOptions || {};
 
this.errorContainer = errorContainer;
 
this.currentDataTable = null;

 
if (!visualization || !('draw' in visualization) ||
     
(typeof(visualization['draw']) != 'function')) {
   
throw Error('Visualization must have a draw method.');
 
}
};


/** Draws the last returned data table, if no data table exists, does nothing.*/
QueryWrapper.prototype.draw = function() {
 
if (!this.currentDataTable) {
   
return;
 
}
 
this.visualization.draw(this.currentDataTable, this.options);
};


/**
 * Sends the query and upon its return draws the visualization.
 * If the query is set to refresh then the visualization will be drawn upon
 * each refresh.
 */

QueryWrapper.prototype.sendAndDraw = function() {
 
var query = this.query;
 
var self = this;
  query
.send(function(response) {self.handleResponse(response)});
};


/** Handles the query response returned by the data source. */
QueryWrapper.prototype.handleResponse = function(response) {
 
this.currentDataTable = null;
 
if (response.isError()) {
   
this.handleErrorResponse(response);
 
} else {
   
this.currentDataTable = response.getDataTable();
   
this.draw();
 
}
};


/** Handles a query response error returned by the data source. */
QueryWrapper.prototype.handleErrorResponse = function(response) {
 
var message = response.getMessage();
 
var detailedMessage = response.getDetailedMessage();
 
if (this.errorContainer) {
    google
.visualization.errors.addError(this.errorContainer,
        message
, detailedMessage, {'showInTooltip': false});
 
} else {
   
throw Error(message + ' ' + detailedMessage);
 
}
};


/** Aborts the sending and drawing. */
QueryWrapper.prototype.abort = function() {
 
this.query.abort();
};

表查询封装容器示例

此示例演示了如何以分页表格可视化图表显示大型数据集,而不用通过单个请求获取所有数据。如果存在大量数据,并且您希望避免在网页上一次性请求或存储所有数据的开销,那么该方法会非常有用。

JavaScript 定义了一个对象 TableQueryWrapper,该对象管理发出请求的 google.visualization.Query 对象以及表格可视化图表,用于处理排序和分页。该对象已使用 google.visualization.Query 实例、用于保存可视化图表及其抛出的任何错误的页面元素的句柄以及要传递给 draw() 方法的任何选项(包括要提取的行数,作为 pageSize 选项)进行实例化。此对象通过捕获和处理分页和排序事件来管理表的可视化。

当用户向前或向后翻页时,TableQueryWrapper 会创建和发送具有相应 LIMITOFFSET 值的新查询以重新填充表页面,从而处理该事件。同样,当用户点击某个列以更改排序顺序时,TableQueryWrapper 会使用相应的 ORDER BY 子句创建和发送新查询来处理该事件,然后会重置为偏移量 0。

在以下示例中,您可以使用下拉框选择要显示的表格行数。如果更改,托管页面将创建一个新的 TableQueryWrapper 实例,然后发送一个新查询,该查询包含反映所选行数的 LIMIT 子句,而不包含 OFFSET 子句(即跳回第一行)。

以下是托管网页的代码:

<!DOCTYPE html>
<html>
<head>
<title>Table Query Wrapper Example</title>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="tablequerywrapper.js"></script>
<script type="text/javascript">
    google
.charts.load('current', {'packages' : ['table']});
    google
.charts.setOnLoadCallback(init);

   
var dataSourceUrl = 'https://spreadsheets.google.com/tq?key=rh_6pF1K_XsruwVr_doofvw&pub=1';
   
var query, options, container;

    function init() {
      query
= new google.visualization.Query(dataSourceUrl);
      container
= document.getElementById("table");
      options
= {'pageSize': 5};
      sendAndDraw
();
   
}

   
function sendAndDraw() {
      query
.abort();
     
var tableQueryWrapper = new TableQueryWrapper(query, container, options);
      tableQueryWrapper
.sendAndDraw();
   
}


   
function setOption(prop, value) {
      options
[prop] = value;
      sendAndDraw
();
   
}

 
</script>
</head>
<body>
<p>This example uses the following spreadsheet: <br />
 
<a href="https://spreadsheets.google.com/pub?key=rh_6pF1K_XsruwVr_doofvw">
    https://spreadsheets.google.com/pub?key=rh_6pF1K_XsruwVr_doofvw
 
</a>
</p>
<form action="">
  Number of rows to show:
 
<select onChange="setOption('pageSize', parseInt(this.value, 10))">
   
<option value="0">0</option>
   
<option value="3">3</option>
   
<option selected=selected value="5">5</option>
   
<option value="8">8</option>
   
<option value="-1">-1</option>
 
</select>
</form>
<br />
<div id="table"></div>
</body>
</html>

以下是 TableQueryWrapper 对象的 JavaScript 代码:

/**
 * A wrapper for a query and a table visualization.
 * The object only requests 1 page + 1 row at a time, by default, in order
 * to minimize the amount of data held locally.
 * Table sorting and pagination is executed by issuing
 * additional requests with appropriate query parameters.
 * E.g., for getting the data sorted by column 'A' the following query is
 * attached to the request: 'tq=order by A'.
 *
 * Note: Discards query strings set by the user on the query object using
 * google.visualization.Query#setQuery.
 *
 * DISCLAIMER: This is an example code which you can copy and change as
 * required. It is used with the google visualization API table visualization
 * which is assumed to be loaded to the page. For more info see:
 * https://developers.google.com/chart/interactive/docs/gallery/table
 * https://developers.google.com/chart/interactive/docs/reference#Query
 */



/**
 * Constructs a new table query wrapper for the specified query, container
 * and tableOptions.
 *
 * Note: The wrapper clones the options object to adjust some of its properties.
 * In particular:
 *         sort {string} set to 'event'.
 *         page {string} set to 'event'.
 *         pageSize {Number} If number <= 0 set to 10.
 *         showRowNumber {boolean} set to true.
 *         firstRowNumber {number} set according to the current page.
 *         sortAscending {boolean} set according to the current sort.
 *         sortColumn {number} set according to the given sort.
 * @constructor
 */

var TableQueryWrapper = function(query, container, options) {

 
this.table = new google.visualization.Table(container);
 
this.query = query;
 
this.sortQueryClause = '';
 
this.pageQueryClause = '';
 
this.container = container;
 
this.currentDataTable = null;

 
var self = this;
 
var addListener = google.visualization.events.addListener;
  addListener
(this.table, 'page', function(e) {self.handlePage(e)});
  addListener
(this.table, 'sort', function(e) {self.handleSort(e)});

  options
= options || {};
  options
= TableQueryWrapper.clone(options);

  options
['sort'] = 'event';
  options
['page'] = 'event';
  options
['showRowNumber'] = true;
 
var buttonConfig = 'pagingButtonsConfiguration';
  options
[buttonConfig] = options[buttonConfig] || 'both';
  options
['pageSize'] = (options['pageSize'] > 0) ? options['pageSize'] : 10;
 
this.pageSize = options['pageSize'];
 
this.tableOptions = options;
 
this.currentPageIndex = 0;
 
this.setPageQueryClause(0);
};


/**
 * Sends the query and upon its return draws the Table visualization in the
 * container. If the query refresh interval is set then the visualization will
 * be redrawn upon each refresh.
 */

TableQueryWrapper.prototype.sendAndDraw = function() {
 
this.query.abort();
 
var queryClause = this.sortQueryClause + ' ' + this.pageQueryClause;
 
this.query.setQuery(queryClause);
 
this.table.setSelection([]);
 
var self = this;
 
this.query.send(function(response) {self.handleResponse(response)});
};


/** Handles the query response after a send returned by the data source. */
TableQueryWrapper.prototype.handleResponse = function(response) {
 
this.currentDataTable = null;
 
if (response.isError()) {
    google
.visualization.errors.addError(this.container, response.getMessage(),
        response
.getDetailedMessage(), {'showInTooltip': false});
 
} else {
   
this.currentDataTable = response.getDataTable();
   
this.table.draw(this.currentDataTable, this.tableOptions);
 
}
};


/** Handles a sort event with the given properties. Will page to page=0. */
TableQueryWrapper.prototype.handleSort = function(properties) {
 
var columnIndex = properties['column'];
 
var isAscending = properties['ascending'];
 
this.tableOptions['sortColumn'] = columnIndex;
 
this.tableOptions['sortAscending'] = isAscending;
 
// dataTable exists since the user clicked the table.
 
var colID = this.currentDataTable.getColumnId(columnIndex);
 
this.sortQueryClause = 'order by `' + colID + (!isAscending ? '` desc' : '`');
 
// Calls sendAndDraw internally.
 
this.handlePage({'page': 0});
};


/** Handles a page event with the given properties. */
TableQueryWrapper.prototype.handlePage = function(properties) {
 
var localTableNewPage = properties['page']; // 1, -1 or 0
 
var newPage = 0;
 
if (localTableNewPage != 0) {
    newPage
= this.currentPageIndex + localTableNewPage;
 
}
 
if (this.setPageQueryClause(newPage)) {
   
this.sendAndDraw();
 
}
};


/**
 * Sets the pageQueryClause and table options for a new page request.
 * In case the next page is requested - checks that another page exists
 * based on the previous request.
 * Returns true if a new page query clause was set, false otherwise.
 */

TableQueryWrapper.prototype.setPageQueryClause = function(pageIndex) {
 
var pageSize = this.pageSize;

 
if (pageIndex < 0) {
   
return false;
 
}
 
var dataTable = this.currentDataTable;
 
if ((pageIndex == this.currentPageIndex + 1) && dataTable) {
   
if (dataTable.getNumberOfRows() <= pageSize) {
     
return false;
   
}
 
}
 
this.currentPageIndex = pageIndex;
 
var newStartRow = this.currentPageIndex * pageSize;
 
// Get the pageSize + 1 so that we can know when the last page is reached.
 
this.pageQueryClause = 'limit ' + (pageSize + 1) + ' offset ' + newStartRow;
 
// Note: row numbers are 1-based yet dataTable rows are 0-based.
 
this.tableOptions['firstRowNumber'] = newStartRow + 1;
 
return true;
};


/** Performs a shallow clone of the given object. */
TableQueryWrapper.clone = function(obj) {
 
var newObj = {};
 
for (var key in obj) {
    newObj
[key] = obj[key];
 
}
 
return newObj;
};

鼠标悬停提示示例

此示例演示了如何监听鼠标悬停事件以在图表中显示提示。

 

<script>
 
// barsVisualization must be global in our script tag to be able
 
// to get and set selection.
 
var barsVisualization;

 
function drawMouseoverVisualization() {
   
var data = new google.visualization.DataTable();
    data
.addColumn('string', 'Year');
    data
.addColumn('number', 'Score');
    data
.addRows([
     
['2005',3.6],
     
['2006',4.1],
     
['2007',3.8],
     
['2008',3.9],
     
['2009',4.6]
   
]);

    barsVisualization
= new google.visualization.ColumnChart(document.getElementById('mouseoverdiv'));
    barsVisualization
.draw(data, null);

   
// Add our over/out handlers.
    google
.visualization.events.addListener(barsVisualization, 'onmouseover', barMouseOver);
    google
.visualization.events.addListener(barsVisualization, 'onmouseout', barMouseOut);
 
}

 
function barMouseOver(e) {
    barsVisualization
.setSelection([e]);
 
}

 
function barMouseOut(e) {
    barsVisualization
.setSelection([{'row': null, 'column': null}]);
 
}

</script>