I would like to show a tooltip in HTML format on a structure with the data of columns 2,3,4 which are hidden.
I can not get the addeventlistener to work when I'm doing an onmouseover on a cell.
I would like the tooltip to be triggered when moving the mouse over the column 'number' (col 1).
<html>
<head>
<style>
div.google-visualization-tooltip {
width: auto;
height:auto;
background-color: red;
color: #000000;
text-align: center;
vertical-align: middle;
}
</style>
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type='text/javascript'>
google.load('visualization', '1', {packages:['table']});
google.setOnLoadCallback(drawTable,);
// start chart
function drawTable() {
var data = new google.visualization.DataTable();
// add columns
data.addColumn('string', 'Name');
data.addColumn('number', 'number');
data.addColumn('number', 'ok');
data.addColumn('number', 'warnning');
data.addColumn('number', 'nok');
// add data
data.addRows([
['Mike',18,10,3,5],
['Jim', 8,5,2,1],
['Alice', 12,6,3,3],
['Bob', 7,2,4,1],
['Sourav',9,1,0,8],
['Sunil', 16,15,0,1],
['Vinod', 19,14,4,1]
]);
var table = new google.visualization.Table(document.getElementById('table_div'));
var view = new google.visualization.DataView(data);
view.setColumns([0,1]);
table.draw(view, {allowHtml: true});
google.visualization.events.addListener(table, 'onmouseover', function(e){
setTooltipContent(data,e.row);
});
}
// set tooltip
function setTooltipContent(data,row) {
if (row != null) {
var content = '<div class="custom-tooltip" ><table border="1"><tr><td>OK</td><td>warnnig</td><td>NOK</td></tr><tr><td>' + data.getValue(row, 2) + '</td><td>' + data.getValue(row, 3) + '</td><td>' + data.getValue(row, 4) + '</td></tr></table></div>'; //generate tooltip content
var tooltip = document.getElementsByClassName("google-visualization-tooltip")[0];
tooltip.innerHTML = content;
}
}
</script>
</head>
<body>
<div id='table_div'></div>
</body>
</html>
the table chart only publishes the following events...
'select', 'page', 'sort', 'ready'
also, no container for google-visualization-tooltip exists for a table chart
to get the desired result, we can wait for the chart's 'ready' event,
then listen for the 'mouseover event on the table's container <div>.
as for google-visualization-tooltip, we can just add our own...
see following working snippet...
google.charts.load('current', {packages:['table']});
google.charts.setOnLoadCallback(drawTable);
// start chart
function drawTable() {
var data = new google.visualization.DataTable();
// add columns
data.addColumn('string', 'Name');
data.addColumn('number', 'number');
data.addColumn('number', 'ok');
data.addColumn('number', 'warnning');
data.addColumn('number', 'nok');
// add data
data.addRows([
['Mike',18,10,3,5],
['Jim', 8,5,2,1],
['Alice', 12,6,3,3],
['Bob', 7,2,4,1],
['Sourav',9,1,0,8],
['Sunil', 16,15,0,1],
['Vinod', 19,14,4,1]
]);
var container = document.getElementById('table_div');
var table = new google.visualization.Table(container);
var view = new google.visualization.DataView(data);
view.setColumns([0,1]);
google.visualization.events.addListener(table, 'ready', function() {
container.addEventListener('mouseover', function (e) {
setTooltipContent(data, e);
});
container.addEventListener('mouseout', function (e) {
setTooltipContent(data, e);
});
});
table.draw(view, {allowHtml: true});
}
// set tooltip
function setTooltipContent(data, e) {
var col = null;
var row = null;
var tooltip = document.getElementsByClassName("google-visualization-tooltip")[0];
if (e.type === 'mouseover') {
if (e.target.tagName === 'TD') {
col = (e.target.cellIndex);
row = (e.target.parentNode.rowIndex - 1);
}
if ((row !== null) && (col === 1)) {
var content = '<div class="custom-tooltip" ><table border="1"><tr><td>OK</td><td>warnnig</td><td>NOK</td></tr><tr><td>' + data.getValue(row, 2) + '</td><td>' + data.getValue(row, 3) + '</td><td>' + data.getValue(row, 4) + '</td></tr></table></div>'; //generate tooltip content
tooltip.innerHTML = content;
tooltip.style.display = 'block';
tooltip.style.left = (e.pageX + 16) + "px";
tooltip.style.top = (e.pageY + 16) + "px";
} else {
tooltip.style.display = 'none';
}
} else {
tooltip.style.display = 'none';
}
}
div.google-visualization-tooltip {
display: none;
position: absolute;
width: auto;
height:auto;
background-color: red;
color: #000000;
text-align: center;
vertical-align: middle;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="table_div"></div>
<div class="google-visualization-tooltip"></div>
notes
1) the script library jsapi should no longer be used.
<script src="https://www.google.com/jsapi"></script>
see the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.
<script src="https://www.gstatic.com/charts/loader.js"></script>
this will only change the load statements, see snippet above.
2) when adding event listeners to any google chart, such as 'ready', they should be assigned before drawing the chart...
Related
This question already has answers here:
Handling colon in element ID with jQuery
(9 answers)
Closed 5 years ago.
I'm trying to hide some element when click on this element(option value for categoryfilter on Google Chart)
<div class="goog-menuitem goog-option" role="menuitemradio" aria-checked="false" style="user-select: none;" id=":4">Middle East</div>
and
<div class="goog-menuitem goog-option" role="menuitemradio" aria-checked="false" style="user-select: none;" id=":0" aria-hidden="false"><div class="goog-menuitem-content" style="user-select: none;"><div class="goog-menuitem-checkbox" style="user-select: none;"></div>Africa</div></div>
So I wrote this code
google.visualization.events.addListener(namePicker, 'statechange', hidediv);
function hidediv() {
$("#:0.goog-menuitem.goog-option").click(function() {
document.getElementById('2000').hide();
document.getElementById('2010').hide();
document.getElementById('2017').hide();
});
$("#:4.goog-menuitem.goog-option").click(function() {
document.getElementById('2000').hide();
document.getElementById('2010').hide();
document.getElementById('2017').hide();
});
}
but I got an error
Syntax error, unrecognized expression: #:0.goog-menuitem.goog-option
Runnable Snippet
<html>
<head>
<link rel="stylesheet" href="styles_timeline.css">
</head>
<body width="880">
<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
google.charts.load('current', {
'packages': ['corechart', 'controls']
});
google.charts.setOnLoadCallback(drawRegionsMap);
function drawRegionsMap() {
var query1 = new google.visualization.Query("https://docs.google.com/spreadsheets/d/1sOyYwL51uWTd7Pv4Sp_bKdxWmH-g6QA2SDHhw93_2s8/edit?usp=sharing");
//all
query1.setQuery('select * where J="Take back policy model" order by F,Y,M,N,L');
query1.send(drawDashboard);
}
function drawDashboard(response1) {
var data1 = response1.getDataTable();
//set year that<2000 to 2000
for (i = 0; i < data1.getNumberOfRows(); i++) {
var startdate = new Date(data1.getValue(i, 12));
var y = startdate.getFullYear();
if (y < 2000) {
r = data1.getValue(i, 12);
//console.log(i);
startdate.setFullYear(2000);
data1.setValue(i, 12, startdate);
}
}
//set start date to previous row end date - groupByRowLabel
for (var row = 1; row < data1.getNumberOfRows(); row++) {
if (data1.getValue(row - 1, 5) == data1.getValue(row, 5) && data1.getValue(row - 1, 6) == data1.getValue(row, 6)) { //if the previous one has the same label
if (data1.getValue(row - 1, 13) > data1.getValue(row, 12)) { // if the previous end date is greater than the start date of current row
data1.setValue(row - 1, 13, data1.getValue(row, 12)) // set the previous end date to the start date of current row
}
}
}
var view1 = new google.visualization.DataView(data1);
view1.setColumns([
//index column 0
{
type: 'string',
id: 'Country',
calc: function(dt, row) {
//return countryname statename - policies // USA New York - WEEE
return dt.getFormattedValue(row, 5) + " " + dt.getFormattedValue(row, 22) + " - " + dt.getFormattedValue(row, 6)
}
},
//index column 1
{
type: 'string',
id: 'region',
calc: function(dt, row) {
return dt.getFormattedValue(row, 8)
}
}
//index column 2
, {
type: 'string',
role: 'tooltip',
properties: {
html: true
},
calc: function(dt, row) {
var country = dt.getFormattedValue(row, 5)
var policy = dt.getFormattedValue(row, 6)
var dataname = dt.getFormattedValue(row, 8)
var dropname = dt.getFormattedValue(row, 11)
var formatter = new google.visualization.DateFormat({
pattern: "MMMM yyyy"
});
var startdate = formatter.formatValue(dt.getValue(row, 12));
//var startdate = dt.getFormattedValue(row, 12)
var comment = dt.getFormattedValue(row, 15)
//colorValues.push(dt.getFormattedValue(row, 6))
return '<br><div id="country">' + country + " - " + policy + '<br><br></div> ' +
'<div id="header1">Dominant (E)PR policy model:<br></div>' +
'<div id="dropname">' + dropname + '<br><br></div>' +
'<div id ="header2">Since : </div><div id="date">' + startdate + " " + 'to current</div><br><br><br>' +
'<div id ="comment">' + comment + '<\/div>'
}
},
//style role
{
type: 'string',
id: 'color',
role: 'style',
calc: function(dt, row) {
return dt.getFormattedValue(row, 25)
}
},
//index column 3,4 start-enddate
12, 13,
]);
var chart1 = new google.visualization.ChartWrapper({
chartType: 'Timeline',
//dataTable: 'data1',
containerId: 'colormap1',
options: {
width: 870,
height: 800,
//colors: colorValues,
timeline: {
groupByRowLabel: true,
rowLabelStyle: {
fontSize: 14,
width: 800,
},
showBarLabels: false
},
hAxis: {
minValue: new Date(2010, 0, 0),
maxValue: new Date(2017, 0, 0)
},
tooltip: {
isHtml: true
},
}
});
var namePicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'filter_div',
'options': {
'filterColumnIndex': '1',
'ui': {
'labelStacking': 'vertical',
'caption': 'Choose a Region',
'cssClass': 'filter',
'selectedValuesLayout': 'aside',
'allowTyping': false,
'allowMultiple': true
}
}
});
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div'));
// Establish dependencies, declaring that 'filter' drives 'pieChart',
// so that the pie chart will only display entries that are let through
// given the chosen slider range.
dashboard.bind(namePicker, chart1);
// Draw the dashboard.
dashboard.draw(view1);
google.visualization.events.addListener(chart1, 'ready', function() {
var svgParent = colormap1.getElementsByTagName('svg')[0];
svgParent.parentNode.style.top = '40px';
Array.prototype.forEach.call(colormap1.getElementsByTagName('text'), function(text) {
if ((text.getAttribute('text-anchor') === 'end') &&
(parseFloat(text.getAttribute('x')) < 200)) {
text.setAttribute("x", "5");
text.setAttribute("text-anchor", "start");
}
if ((text.getAttribute('text-anchor') === 'middle') && (parseFloat(text.getAttribute('x')) < 850)) {
var groupLabel = text.cloneNode(true);
groupLabel.setAttribute('x', '850');
groupLabel.innerHTML = '2017';
groupLabel.setAttribute('y', '971.05');
groupLabel.setAttribute('font-family', 'Arial');
groupLabel.setAttribute('font-size', '13');
svgParent.appendChild(groupLabel);
}
})
})
google.visualization.events.addListener(chart1, 'select', tableSelectHandler);
function tableSelectHandler() {
var selection = chart1.getChart().getSelection()[0];
var chartDataView = chart1.getDataTable();
var rowindex = chartDataView.getTableRowIndex(selection.row);
var cnid = data1.getValue(rowindex, 0);
var polid = data1.getValue(rowindex, 1);
var strid = data1.getValue(rowindex, 2);
//var sid = (strid) - 1;
var statecode = data1.getValue(rowindex, 4);
//if (selection.length > 0) {
//http://www.sagisepr.com/country.php?country=21&polsel=1&sid=17&statecode=AR
window.open("http://www.sagisepr.com/country.php?country=" + cnid + "&polsel=" + polid + "&sid=" + strid + "&statecode=" + statecode);
//}
}
google.visualization.events.addListener(namePicker, 'statechange', hidediv);
function hidediv() {
$("#:0.goog-menuitem.goog-option").click(function() {
document.getElementById('2000').hide();
document.getElementById('2010').hide();
document.getElementById('2017').hide();
});
$("#:4.goog-menuitem.goog-option").click(function() {
document.getElementById('2000').hide();
document.getElementById('2010').hide();
document.getElementById('2017').hide();
});
}
}
</script>
<div id="dashboard_div">
<div id="2000" style="z-index:1;position: fixed;top: 70px;left: 168px;font-family: Arial;font-size: 13;color:red;">2000</div>
<div id="2010" style="z-index:1;position: fixed;top: 70px;left: 556px;font-family: Arial;font-size: 13;color:red;">2010</div>
<div id="2017" style="z-index:1;position: fixed;top: 70px;left: 850px;font-family: Arial;font-size: 13;color:red;">2017</div>
<div id="filter_div"></div>
<!--chart_div!-->
<div id='colormap1' style="position:fixed;">
</div>
</div>
</body>
</html>
anyone know how to make this works? thank you.
According to How do I select an element by an ID that has characters used in CSS notation? you need to write:
$("#\\:0.goog-menuitem.goog-option")
I have created a donut chart from Google Charts API. When clicking on each slice, it should increase by 10 units and decrease the adjacent slice (clockwise) by 10 units. What I have thus far is a alert popup that explains this, but I would like to redraw the chart with the new values.
Here is my code:
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Option');
data.addColumn('number', 'Value');
data.addRows([
['Option A', 40],
['Option B', 30],
['Option C', 30]
]);
// Set chart options
var options = {
height: 300,
fontName: 'Lato, sans-serif',
title: 'Values per option',
titleTextStyle: {
color: '#5a5a5a',
fontSize: 20,
bold: true,
align: 'center'
},
pieHole: 0.6,
slices: {
0: {color: 'red'},
1: {color: 'blue'},
2: {color: 'green'}
},
legend: {
position: 'bottom',
textStyle: {
color: '#5a5a5a',
fontSize: 14
}
},
enableInteractivity: true,
pieSliceText: 'none'
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
function selectHandler() {
var selectedItem = chart.getSelection()[0];
if (selectedItem && selectedItem.row <2) {
var activeTrait = data.getValue(selectedItem.row, 0);
activePerc = data.getValue(selectedItem.row, 1);
activePercNew = parseInt(activePerc)+10
adjaceTrait = data.getValue(selectedItem.row+1, 0);
adjacePerc = data.getValue(selectedItem.row+1, 1);
adjacePercNew = parseInt(adjacePerc)-10
alert(activeTrait + ' has a value of ' + activePerc + '%. The new value will now be set to ' + activePercNew + '% and ' + adjaceTrait + ' will be corrected to ' + adjacePercNew + '%.');
}
if (selectedItem && selectedItem.row == 2) {
var activeTrait = data.getValue(selectedItem.row, 0);
activePerc = data.getValue(selectedItem.row, 1);
activePercNew = parseInt(activePerc)+10
adjaceTrait = data.getValue(selectedItem.row-2, 0);
adjacePerc = data.getValue(selectedItem.row-2, 1);
adjacePercNew = parseInt(adjacePerc)-10
alert(activeTrait + ' has a value of ' + activePerc + '%. The new value will now be set to ' + activePercNew + '% and ' + adjaceTrait + ' will be corrected to ' + adjacePercNew + '%.');
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(data, options);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div id="chart_div" style="width:800; height:300"></div>
</body>
</html>
I would just like to resize the selected and adjacent slices by clicking on a single slice.
I have a page that displays data in a form of a Pie Chart. I use Google Charts to do this. Here's the code:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Goal Name', 'No. of times Requested'],
['Frank.net Life Cover', 226],
['Frank.net Hospital Cash Back', 147],
['Frank.net Salary Protection', 228],
['King Price Car Insurance', 328],
['Momentum Medical Aid', 493],
['Oplan Health Cover', 185],
['Youi Quote', 33],
]);
var options = {
title: 'Most Requested Sponsors'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart2'));
chart.draw(data, options);
}
</script>
<div id="piechart2" style="width: 700px; height: 400px; position: relative;"></div>
And here's a working JS FIDDLE:
http://jsfiddle.net/yRdW3/
Now, I need help on displaying the percentage and total next to each sponsor name on the legend. I have no idea how to achieve this. I want it to look similar to this:
Check this fiddle example. It is your code with attached legend (idea from first comment, total calculation and some minor errors corrected).
Basic idea is to set legend option of chart to none and than you have to build your own legend.
If you load that code into browser the legend will be positioned to the right but you have to set proper CSS rules to get everything right (I'm not so familiar with CSS). But you have the basic idea how to do that.
And for different sets of legend colors you can check color brewer
There is a way to do this utilizing the built-in legend. Essentially you can utilize the fact that the chart is rendered in SVG, and you can select and modify elements in the SVG the same way you select regular HTML elements. The basic idea is you:
Select the labels in the chart's legend, and iterate through the collection. They are text tags, and you can figure out the selector using Firebug or Chrome Developer Tools.
Use the index of the element to select the total of the associated row in the chart's DataTable (or insert your logic here for calculating whatever value you want to display).
Modify the text of the label element to append your calculated value.
See my Codepen for a working example: http://codepen.io/breich/pen/mVPJwo
/**
* Selector for chart element.
*/
var chartSelector = '#chart';
/**
* Selector used to get label elements inside the rendered chart.
* Your mileage may vary if you configure your chart different than
* me. Use Firebug or Developer Tools to step through the SVG and
* determine your label selector.
*/
var labelSelector = '> g:eq(1) g text';
/**
* This is our data. For simplicity sake, doing inline and not AJAX.
*/
var data = [
[ 'Apples', 10],
[ 'Oranges', 20 ],
[ 'Peaches', 30 ],
[ 'Pears', 40 ],
[ 'Bananas', 50 ]
];
// Load Google Charts
google.load('visualization', '1.1', { packages: ['corechart', 'line'] });
// Callback when API is ready
google.setOnLoadCallback(function() {
/*
* Setup the data table with your data.
*/
var table = new google.visualization.DataTable({
cols : [
{ id : 'name', label : 'Name', type : 'string' },
{ id : 'value', label : 'Value', type : 'number' }
]
});
// Add data to the table
table.addRows( data );
// Google Charts needs a raw element. I'm using jQuery to get the chart
// Container, then indexing into it to get the raw element.
var chartContainer = $(chartSelector)[0];
// Create the Google Pie Chart
var chart = new google.visualization.PieChart(chartContainer);
// Draw the chart.
chart.draw(table, { title : 'Classifications' });
/*
* This is the meat and potatoes of the operation. We really require
* two things: #1) A selector that will get us a list of labels in the
* legend, and #2) The DataTable powering the chart. We'll cycle
* through the labels, and use their index to lookup their value.
* If you have some higher-level math you need to do to display a
* different value, you can just replace my logic to get the count
* with your's.
*/
// The <svg/> element rendered by Google Charts
var svg = $('svg', chartContainer );
/*
* Step through all the labels in the legend.
*/
$(labelSelector, svg).each(function (i, v) {
/*
* I'm retrieving the value of the second column in my data table,
* which contains the number that I want to display. If your logic
* is more complicated, change this line to calculate a new total.
*/
var total = table.getValue(i, 1);
// The new label text.
var newLabel = $(this).text() + '(' + total + ')';
// Update the label text.
$(this).text( newLabel );
});
});
You can do this creating a column for tooltip and use your first column as legend. Check this FIDDLE
var dataArray = [
['Frank.net Life Cover', 226],
['Frank.net Hospital Cash Back', 147],
['Frank.net Salary Protection', 228],
['King Price Car Insurance', 328],
['Momentum Medical Aid', 493],
['Oplan Health Cover', 185,],
['Youi Quote', 33],
];
var total = getTotal(dataArray);
// Adding tooltip column
for (var i = 0; i < dataArray.length; i++) {
dataArray[i].push(customTooltip(dataArray[i][0], dataArray[i][1], total));
}
// Changing legend
for (var i = 0; i < dataArray.length; i++) {
dataArray[i][0] = dataArray[i][0] + " " +
dataArray[i][1] + " requests, " + ((dataArray[i][1] / total) * 100).toFixed(1) + "%";
}
// Column names
dataArray.unshift(['Goal Name', 'No. of times Requested', 'Tooltip']);
var data = google.visualization.arrayToDataTable(dataArray);
Using arrayToDataTable, you need to set the role tooltip in "Tooltip" column:
data.setColumnProperty(2, 'role', 'tooltip');
data.setColumnProperty(2, 'html', true);
Note: If you are creating the dataTable dynamically just call addColumn with this signature:
data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
And in options add tooltip: { isHtml: true }:
var options = {
title: 'Most Requested Sponsors',
width: 900,
height: 400,
tooltip: { isHtml: true }
};
function drawChart() {
var dataArray = [['Yes', <?php echo $member_yes_vote;?>],
['No', <?php echo $member_no_vote;?>],
['Total', 0],];
var total = getTotal(dataArray);
for (var i = 0; i < dataArray.length; i++)
{ dataArray[i].push(customTooltip(dataArray[i][0], dataArray[i][1], total));
}
for (var i = 0; i < dataArray.length; i++)
{
if(dataArray[i][0] == "Total")
{
dataArray[i][0] = dataArray[i][0] + " " + total + " Votes, " + ((total/total) * 100).toFixed(1) + "%";
}
else
{
dataArray[i][0] = dataArray[i][0] + " " + dataArray[i][1]+ " Votes, " + ((dataArray[i][1] / total) * 100).toFixed(1) + "%";
}
}
dataArray.unshift(['Vote Type', 'Number of Vote', 'Tooltip']);
var data = google.visualization.arrayToDataTable(dataArray);
data.setColumnProperty(2, 'role', 'tooltip');
data.setColumnProperty(2, 'html', true);
var options = {
chartArea:
{
left:40,top:20,width:'90%',height:'90%'
},
is3D: true,
slices: {0: {color: '#1a8ec5'}, 1:{color: '#da4638'}},
pieSliceText: 'value-and-percentage',
sliceVisibilityThreshold:0,
tooltip: { isHtml: true }
};
var chart = new google.visualization.PieChart(document.getElementById('Question_count_graph'));
chart.draw(data, options);
}
function customTooltip(name, value, total)
{
if(name == "Total")
{
return name + '<br/><b>' + total + ' (' + ((total/total) * 100).toFixed(1) + '%)</b>';
}
else
{
return name + '<br/><b>' + value + ' (' + ((value/total) * 100).toFixed(1) + '%)</b>';
}
}
function getTotal(dataArray)
{
var total = 0;
for (var i = 0; i < dataArray.length; i++)
{
if(dataArray[i][0] == "Total")
{}
else
{
total += dataArray[i][1];
}
}
return total;
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});
Here is the code which i have used to show the legend value with percentage and total field
Can someone tell me how to achieve the following effect:
When I select a slice in the Pie Graph I want to show some kind of
Visual representation of the Slice selection.
Either by moving the selected slice away from the graph so that it
stands out on its own.
or By drawing a white border on the slice to show that the
respective slice was selected.
Has anyone done anything similar, if so can you please post some code.
I did a lot of search in this group and elsewhere but was not able to
find anything. Its hard to believe that core plot cant support this
animation.
JS fiddle link
Pi Chart Code is:
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addRows([
['Mushrooms', 3],
['Onions', 5],
['Olives', 1],
['Zucchini', 1],
['Pepperoni', 6],
['Sausage', 3] ]);
var colors = ["#3366cc","#dc3912","#ff9900","#109618","#990099","#0099c6","#dd4477","#aaaa11","#22aa99","#994499"];
var legend = document.getElementById('legend');
var lis = [];
var total = 0;
for (var i = 0; i < data.getNumberOfRows(); i++) {
// increment the total
total += data.getValue(i, 1);
// get the data
var label = data.getValue(i, 0);
var value = data.getValue(i, 1);
// create the legend entry
lis[i] = document.createElement('li');
lis[i].setAttribute('data-row',i);
lis[i].setAttribute('data-value',value);
lis[i].id = 'legend_' + data.getValue(i, 0);
lis[i].innerHTML = '<div class="legendMarker" style="background-color:' + colors[i] + ';" ></div>' + label + ': ' + value +'</span>';
// append to the legend list
legend.appendChild(lis[i]);
}
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {
title: 'How Much Pizza I Ate Last Night',
width: 300,
height: 300,
colors: colors,
legend: {
position: 'none'
}
});
$('#legend li').click(function(){
chart.setSelection([{row:$(this).data('row'),column:null}]);
})
}
The PieCharts don't have any visual indication of which slice is selected, so you will have to change the chart options and redraw the chart to get the effect you want. Something like this should do it:
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addRows([
['Mushrooms', 3],
['Onions', 5],
['Olives', 1],
['Zucchini', 1],
['Pepperoni', 6],
['Sausage', 3],
['Peppers', 5],
['Tomatoes', 2],
['Meatballs', 4],
['Extra Cheese', 3]
]);
var colors = ["#3366cc","#dc3912","#ff9900","#109618","#990099","#0099c6","#dd4477","#aaaa11","#22aa99","#994499"];
var legend = document.getElementById('legend');
var lis = [];
var total = 0;
for (var i = 0; i < data.getNumberOfRows(); i++) {
// increment the total
total += data.getValue(i, 1);
// get the data
var label = data.getValue(i, 0);
var value = data.getValue(i, 1);
// create the legend entry
lis[i] = document.createElement('li');
lis[i].setAttribute('data-row',i);
lis[i].setAttribute('data-value',value);
lis[i].id = 'legend_' + data.getValue(i, 0);
lis[i].innerHTML = '<div class="legendMarker" style="background-color:' + colors[i] + ';" ></div>' + label + ': ' + value +'</span>';
// append to the legend list
legend.appendChild(lis[i]);
}
var options = {
title: 'How Much Pizza I Ate Last Night',
width: 300,
height: 300,
colors: colors,
legend: {
position: 'none'
}
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
$('#legend li').hover(function () {
options.slices = options.slices || {};
// clear all slice offsets
for (var x in options.slices) {
options.slices[x].offset = 0;
}
// set the offset of the slice associated with the hovered over legend entry
options.slices[$(this).data('row')] = options.slices[$(this).data('row')] || {};
options.slices[$(this).data('row')].offset = 0.1;
chart.draw(data, options);
}, function () {
options.slices = options.slices || {};
// clear all slice offsets
for (var x in options.slices) {
options.slices[x].offset = 0;
}
chart.draw(data, options);
})
//fixing incorrect percent-values
.each(function(i,o){$(o).append(' ('+(Math.round(1000 * $(o).data('value') / total) / 10)+'%)');});
}
see working example in jsfiddle: http://jsfiddle.net/asgallant/2JWQY/31/
I trying to do the map base on geocodezip example http://www.geocodezip.com/geoxml3_test/v3_FusionTables_CountryBrowser.html , but I have always have message on my map "Data may still be loading".
I reduce my map to only 10 polygons but I have same message over and over.
Inside left sidebar; name of the polygons are properly displayed, and when I click "show" map guide me to the exact place of the polygon, but the polygons are not displayed on the map. Does anyone have any suggestions?
My code is below.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Fusion Tables Natural Earth Data Country Browser</title>
<style type="text/css">
html, body, #map_canvas {
width: 750px;
height: 600px;
margin: 0;
padding: 0;
}
.infowindow * {font-size: 90%; margin: 0}
</style>
<!--Load the AJAX API-->
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript" src="geoxml3_kmlStr.js"></script>
<!-- Initialize -->
<script type="text/javascript">
// globals
var map = null;
var infoWindow = null;
var geoXml = null;
var geoXmlDoc = null;
var myLatLng = null;
var myOptions = null;
var mapCenter = null;
var geocodeTheCountry = true;
var gpolygons = [];
var geocoder = null;
// Fusion Table data ID
var FT_TableID = '1-bZhRr6OMbj4NWZcY8XnVjpijvV97yNgSXSf_mE';
var CountryName = "USA"; // "United States of America";
google.load('visualization', '1', {'packages':['corechart', 'table', 'geomap']});
function createSidebar() {
// set the query using the parameters
document.getElementById('sidebar').innerHTML = "querying for data";
var FT_Query2 = "SELECT 'name_0', 'name', 'geometry' FROM "+FT_TableID+" WHERE 'name_0' = '"+CountryName+"' ORDER by 'name'";
document.getElementById("FTquery2").innerHTML = FT_Query2;
var queryText = encodeURIComponent(FT_Query2);
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
//set the callback function
query.send(getData);
}
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(createSidebar);
function getCountryNames() {
// set the query using the parameters
var FT_Query_CountryName = "SELECT 'name_0', count() FROM "+FT_TableID+" GROUP by 'name_0' ORDER by 'name_0'";
document.getElementById("FTquery4").innerHTML = FT_Query_CountryName;
var queryText = encodeURIComponent(FT_Query_CountryName);
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
//set the callback function
query.send(createCountryDropdown);
}
function createCountryDropdown(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
//for more information on the response object, see the documentation
//http://code.google.com/apis/visualization/documentation/reference.html#QueryResponse
numRows = response.getDataTable().getNumberOfRows();
numCols = response.getDataTable().getNumberOfColumns();
var countryNames = {};
for (var i = 0; i < numRows; i++) {
var countryName = response.getDataTable().getValue(i,0);
// countryName = countryName.substring(0,countryName.indexOf('('));
countryNames[countryName] = countryName;
}
var countryNameDropdown = "<select name='country_select' onchange='handleSelected(this)'>"
countryNameDropdown += '<option selected> - Select a country - <\/option>';
for (countryName in countryNames) {
countryNameDropdown += "<option value='"+countryName+"'>"+countryName+"</option>"
// document.getElementById('country_list').innerHTML += countryName+"<br>";
}
countryNameDropdown += "</select>"
document.getElementById('dropdown_menu').innerHTML = countryNameDropdown;
}
// ======= This function handles selections from the select box ====
function handleSelected(opt) {
if (opt.selectedIndex > 0) {
CountryName = geoXML3.nodeValue(opt[opt.selectedIndex]);
DisplayCountry();
} else {
alert("Please pick a country");
}
}
function DisplayCountry() {
// geocode the country
var addressStr = CountryName;
if (addressStr != "Baikonur Cosmodrome") addressStr += " Country";
geocoder.geocode( { 'address': addressStr}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
map.setCenter(results[0].geometry.location);
map.fitBounds(results[0].geometry.viewport);
} else {
alert("No results found");
}
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
FT_Query = "SELECT 'geometry' FROM "+FT_TableID+" WHERE 'name_0' = '"+CountryName+"';";
gpolygons = [];
layer.setQuery(FT_Query);
document.getElementById("FTquery").innerHTML = FT_Query;
createSidebar();
}
</script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var FTresponse = null;
myLatLng = new google.maps.LatLng(37.422104808,-122.0838851);
// these set the initial center, zoom and maptype for the map
// if it is not specified in the query string
var lat = 37.422104808;
var lng = -122.0838851;
var zoom = 18;
var maptype = google.maps.MapTypeId.ROADMAP;
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i=0; i<pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0,pos).toLowerCase();
var value = pairs[i].substring(pos+1);
if (argname == "country") {CountryName = unescape(value);}
value = pairs[i].substring(pos+1).toLowerCase();
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "geocode") {geocodeTheCountry = (value != "false");}
if (argname == "id") {id = unescape(value);}
if (argname == "filename") {filename = unescape(value);}
if (argname == "marker") {index = parseFloat(value);}
if (argname == "lat") {lat = parseFloat(value);}
if (argname == "lng") {lng = parseFloat(value);}
if (argname == "zoom") {
zoom = parseInt(value);
myGeoXml3Zoom = false;
}
if (argname == "type") {
// from the v3 documentation 8/24/2010
// HYBRID This map type displays a transparent layer of major streets on satellite images.
// ROADMAP This map type displays a normal street map.
// SATELLITE This map type displays satellite images.
// TERRAIN This map type displays maps with physical features such as terrain and vegetation.
if (value == "m") {maptype = google.maps.MapTypeId.ROADMAP;}
if (value == "k") {maptype = google.maps.MapTypeId.SATELLITE;}
if (value == "h") {maptype = google.maps.MapTypeId.HYBRID;}
if (value == "t") {maptype = google.maps.MapTypeId.TERRAIN;}
}
}
if (!isNaN(lat) && !isNaN(lng)) {
myLatLng = new google.maps.LatLng(lat, lng);
}
infoWindow = new google.maps.InfoWindow();
//define callback function, this is called when the results are returned
function getData(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
FTresponse = response;
//for more information on the response object, see the documentation
//http://code.google.com/apis/visualization/documentation/reference.html#QueryResponse
numRows = response.getDataTable().getNumberOfRows();
numCols = response.getDataTable().getNumberOfColumns();
if (numRows <= 1) {
document.getElementById('sidebar').innerHTML = "no data";
return;
}
//concatenate the results into a string, you can build a table here
fusiontabledata = "<table><tr>";
// for(i = 0; i < numCols; i++) {
fusiontabledata += "<th colspan='2'>" + response.getDataTable().getValue(1,0) + "</th>";
// }
fusiontabledata += "</tr><tr>";
fusiontabledata += "<tr><td colspan='2' align='left'><a href='javascript:showAll();'>show all</a></td></tr>";
for(i = 0; i < numRows; i++) {
// for(j = 0; j < numCols; j++) {
/*
var kml = response.getDataTable().getValue(i,2);
geoXml.parseKmlString("<Placemark>"+kml+"</Placemark>");
*/
fusiontabledata += "<td><a href='javascript:myFTclick("+i+")'>"+response.getDataTable().getValue(i, 1) + "</a></td><td><a href='javascript:zoomTo("+i+")'>show</a></td>";
// }
fusiontabledata += "</tr><tr>";
}
fusiontabledata += "</table>"
//display the results on the page
document.getElementById('sidebar').innerHTML = fusiontabledata;
}
function infoWindowContent(name, description, id) {
content = '<div class="FT_infowindow"><h3>' + name +
'</h3><div>' + description + '</div>';
if (typeof id != "undefined") {
content += 'zoom to';
}
content += '</div>';
return content;
}
function zoomTo(id) {
loadRow(id);
if (gpolygons[id] && gpolygons[id].bounds) {
map.fitBounds(gpolygons[id].bounds);
var queryStr = "SELECT 'geometry' FROM "+FT_TableID+" WHERE 'name_0' = '"+CountryName+"' AND 'name' = '"+gpolygons[id].name+"';"
layer.setQuery(queryStr);
document.getElementById("FTquery3").innerHTML = queryStr;
}
}
function showAll() {
layer.setQuery("SELECT 'geometry' FROM "+FT_TableID+" WHERE 'name_0' = '"+CountryName+"';");
}
function loadRow(row) {
if (!gpolygons[row]) {
var name = FTresponse.getDataTable().getValue(row,1);
var kml = FTresponse.getDataTable().getValue(row,2);
// create a geoXml3 parser for the click handlers
var geoXml = new geoXML3.parser({
map: map,
zoom: false,
infoWindow: infoWindow,
singleInfoWindow: true
});
geoXml.parseKmlString("<Placemark>"+kml+"</Placemark>");
geoXml.docs[0].gpolygons[0].setMap(null);
gpolygons[row] = new Object();
gpolygons[row].position = geoXml.docs[0].gpolygons[0].bounds.getCenter();
gpolygons[row].bounds = geoXml.docs[0].gpolygons[0].bounds;
gpolygons[row].name = name;
}
}
function myFTclick(row) {
var description = FTresponse.getDataTable().getValue(row,0);
var name = FTresponse.getDataTable().getValue(row,1);
loadRow(row);
var position = gpolygons[row].position;
/*
var lat = FTresponse.getDataTable().getValue(row,4);
var lng = FTresponse.getDataTable().getValue(row,5);
var position = new google.maps.LatLng(lat, lng);
*/
// Set up and create the infowindow
if (!infoWindow) infoWindow = new google.maps.InfoWindow({});
infoWindow.setOptions({
content: infoWindowContent(name, description, row),
pixelOffset: new google.maps.Size(0, 2),
position: position
});
// Infowindow-opening event handler
infoWindow.open(map);
}
function initialize() {
myOptions = {
zoom: zoom,
center: myLatLng,
// zoom: 5,
// center: myLatlng,
mapTypeId: maptype
};
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
google.maps.event.addListener(map, "click", function(event) {
infoWindow.close();
var FT_click_query="SELECT 'name_0' FROM "+FT_TableID+" WHERE ST_INTERSECTS('geometry',CIRCLE(LATLNG"+event.latLng+", 1));";
// alert(event.latLng+"query="+FT_click_query);
// set the query using the parameters
var queryText = encodeURIComponent(FT_click_query);
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
document.getElementById("FTquery5").innerHTML = FT_click_query;
//set the callback function
query.send(getCountryFromClick);
});
geocoder = new google.maps.Geocoder();
if (geocoder && geocodeTheCountry) {
geocoder.geocode( { 'address': CountryName+" Country"}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
map.setCenter(results[0].geometry.location);
map.fitBounds(results[0].geometry.viewport);
} else {
alert("No results found");
}
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
var FT_Query = "SELECT 'geometry' FROM "+FT_TableID+" WHERE 'name_0' = '"+CountryName+"';";
var FT_Options = { suppressInfoWindows: true, query:FT_Query };
document.getElementById("FTquery").innerHTML = FT_Query;
layer = new google.maps.FusionTablesLayer(FT_TableID, FT_Options);
layer.setMap(map);
google.maps.event.addListener(layer, "click", function(event) {
infoWindow.close();
infoWindow.setContent(infoWindowContent(event.row.name.value,event.row.name_0.value));
infoWindow.setPosition(event.latLng);
infoWindow.open(map);
});
getCountryNames();
}
function getCountryFromClick(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
//for more information on the response object, see the documentation
//http://code.google.com/apis/visualization/documentation/reference.html#QueryResponse
numRows = response.getDataTable().getNumberOfRows();
numCols = response.getDataTable().getNumberOfColumns();
if (numRows <= 1) {
return;
}
CountryName = response.getDataTable().getValue(1, 0);
// alert("CountryName="+CountryName);
DisplayCountry();
}
</script>
</head>
<body onload="initialize()">
<table style="width:100%;">
<tr><td colspan="2"><h3>Google Maps JavaScript API v3 Example: Fusion Tables Natural Earth Data Country Browser</h3></td></tr>
<tr><td colspan="2"><div id="dropdown_menu">
</div></td></tr>
<tr>
<td><div id="map_canvas"></div></td>
<td><div id="sidebar" style="width:300px;height:600px; overflow:auto"></div></td>
</tr>
<tr><td colspan="2"><div id="FTquery"></div></td></tr>
<tr><td colspan="2"><div id="FTquery2"></div></td></tr>
<tr><td colspan="2"><div id="FTquery3"></div></td></tr>
<tr><td colspan="2"><div id="FTquery4"></div></td></tr>
<tr><td colspan="2"><div id="FTquery5"></div></td></tr>
</table>
<div id="country_list"></div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-162157-1";
urchinTracker();
</script>
</body>
</html>
With the new encrypted ids, you need to use the new query syntax:
layer.setQuery({select:'geometry',from:FT_TableID,where:"'name_0' = '"+CountryName+"'"});
layer.setQuery({select:'geometry',from:FT_TableID,where:"'name_0' = '"+CountryName+"' AND 'name' = '"+gpolygons[id].name+"'"});
and most important (if you only want the selected polygons to show):
layer = new google.maps.FusionTablesLayer(FT_Options);
The old "string" queries only seem to work with the numeric IDs.
working example
updated original example with new syntax
See answer above, it works for me. Thanks to geocodezip
Non numric fields should be enclosed in single quotes under double quotes, ex: " SELECT 'DATE' <= '2013-11-11' "
For complete example, you can have a look here.