I am attempting to create multiple Google Charts, but I can't get it to work. I've tried everything I could find on Stack Overflow. I most recently attempted this fix, but it didn't work. I think I may be missing something. Can anyone see anything wrong with the code as it stands now?
Expected Behavior:
Page displays bar graph. Then, a line graph is displayed underneath the bar graph.
Current Behavior:
Page displays bar graph. Line graph does not display.
Here is JSFiddle. On a side note, the JavaScript only seems to work inline on JSFiddle. If I moved it into the JavaScript section, it did not function properly. Maybe this has something to do with the external resource that was called?
Regardless, I am currently doing this all inline for this experiment.
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="https://www.google.com/jsapi" type="text/javascript">
</script>
<script type="text/javascript">
// Load the Visualization API and the chart packages.
google.load('visualization', '1.1', {
packages: ['line', 'bar', '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 charts, passes in the data and
// draws them.
function drawChart() {
// Create the data table.
var BarData = new google.visualization.arrayToDataTable([
['', 'Customer', 'Segment Avg'],
['TTM Sales', 4, 2],
['TTM Orders', 5, 3],
['TTM Categories', 7, 4]
]);
// Create the data table.
var LineData = new google.visualization.arrayToDataTable([
['Year', 'Customer', 'Segment Avg'],
['2011', 4, 5],
['2012', 5, 3],
['2013', 4, 2]
]);
// Set chart options
var BarOptions = {
chart: {
title: 'Performance',
},
width: 900,
height: 500
};
// Set chart options
var LineOptions = {
chart: {
title: 'Sales History'
},
width: 900,
height: 500
};
// Instantiate and draw our chart, passing in some options.
var BarChart = new google.charts.Bar(document.getElementById(
'bar_chart'));
BarChart.draw(BarData, BarOptions);
var LineChart = new google.charts.Line(document.getElementById(
'line_chart'));
LineChart.draw(LineData, LineOptions);
};
</script>
<title>Test Chart Page</title>
</head>
<body>
<!--Divs that will hold the charts-->
<div id="bar_chart"></div>
<div id="line_chart"></div>
</body>
</html>
It seems some changes have been made in the latest version of Google Charts API that causes this behavior, but there is a reliable way to render multiple charts on a single page. The idea is to render the next chart once the previous one is rendered, for that purpose you could utilize ready event handler.
Having said that, replace
var barChart = new google.charts.Bar(document.getElementById('bar_chart'));
barChart.draw(barData, barOptions);
var lineChart = new google.charts.Line(document.getElementById('line_chart'));
lineChart.draw(lineData, lineOptions);
with
var barChart = new google.charts.Bar(document.getElementById('bar_chart'));
google.visualization.events.addOneTimeListener(barChart, 'ready', function () {
var lineChart = new google.charts.Line(document.getElementById('line_chart'));
lineChart.draw(lineData, lineOptions);
});
barChart.draw(barData, barOptions);
Working example
google.load('visualization', '1.1', {
packages: ['line', 'bar', 'corechart']
});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawCharts);
function drawCharts() {
// Create the data table.
var barData = new google.visualization.arrayToDataTable([
['', 'Customer', 'Segment Avg'],
['TTM Sales', 4, 2],
['TTM Orders', 5, 3],
['TTM Categories', 7, 4]
]);
// Create the data table.
var lineData = new google.visualization.arrayToDataTable([
['Year', 'Customer', 'Segment Avg'],
['2011', 4, 5],
['2012', 5, 3],
['2013', 4, 2]
]);
// Set chart options
var barOptions = {
chart: {
title: 'Performance',
},
width: 900,
height: 500
};
// Set chart options
var lineOptions = {
chart: {
title: 'Sales History'
},
width: 900,
height: 500
};
var barChart = new google.charts.Bar(document.getElementById('bar_chart'));
google.visualization.events.addOneTimeListener(barChart, 'ready', function () {
var lineChart = new google.charts.Line(document.getElementById('line_chart'));
lineChart.draw(lineData, lineOptions);
});
barChart.draw(barData, barOptions);
};
<script src="https://www.google.com/jsapi" type="text/javascript"></script>
<div id="bar_chart"></div>
<div id="line_chart"></div>
Works with setTimeout:
// Instantiate and draw our chart, passing in some options.
var BarChart = new google.charts.Bar(document.getElementById(
'bar_chart'));
setTimeout(function() {
BarChart.draw(BarData, BarOptions);
}, 0);
var LineChart = new google.charts.Line(document.getElementById(
'line_chart'));
setTimeout(function() {
LineChart.draw(LineData, LineOptions);
}, 1e3);
Updated JSFiddle
The code below works by creating the second chart inside of setTimeout.
I don't know what is causing the problem,
but at least you have a workaround.
fiddle
<script type="text/javascript">
// Load the Visualization API and the chart packages.
google.load('visualization', '1.1', {
packages: ['line', 'bar', '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 charts, passes in the data and
// draws them.
function drawChart() {
// Create the data table.
var BarData = new google.visualization.arrayToDataTable([
['', 'Customer', 'Segment Avg'],
['TTM Sales', 4, 2],
['TTM Orders', 5, 3],
['TTM Categories', 7, 4]
]);
// Create the data table.
var LineData = new google.visualization.arrayToDataTable([
['Year', 'Customer', 'Segment Avg'],
['2011', 4, 5],
['2012', 5, 3],
['2013', 4, 2]
]);
// Set chart options
var BarOptions = {
chart: {
title: 'Performance',
},
width: 900,
height: 500
};
// Set chart options
var LineOptions = {
chart: {
title: 'Sales History'
},
width: 900,
height: 500
};
// Instantiate and draw our chart, passing in some options.
var BarChart = new google.charts.Bar(document.getElementById(
'bar_chart'));
var LineChart = new google.charts.Line(document.getElementById(
'line_chart'));
LineChart.draw(LineData, LineOptions);
setTimeout(function(){
BarChart.draw(BarData, BarOptions);
},50);
};
</script>
<body>
<!--Divs that will hold the charts-->
<div id="bar_chart"></div>
<div id="line_chart"></div>
</body>
Google fixed this timing issue in a recent release, available with the frozen version loader: https://developers.google.com/chart/interactive/docs/library_loading_enhancements#frozen-versions
Relevant thread: https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/google-visualization-api/KulpuT418cg/yZieM8buCQAJ
Related
I have a "vertical" material designed bar chart that receives values like this:
[1, 10],
[580, 12],
[10000, 1]
So it renders the xAxis like this:
Is there any way for me to remove the empty values of the hAxis and just leave the numbers that have values (i.e. 5000, 10000 and the smaller ones).
try using string values for the x-axis, instead of numbers...
['1', 10],
['580', 12],
['10000', 1]
see following working snippet...
google.charts.load('current', {
packages:['bar']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['1', 10],
['580', 12],
['10000', 1]
], true);
var options = {
bars: 'vertical',
chart: {
title: 'Number of payments by amount',
},
hAxis: {
title: 'Amount'
}
};
var chart = new google.charts.Bar(document.getElementById('chart'));
chart.draw(data, google.charts.Bar.convertOptions(options));
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
I'm working on a small HTML application for my website that does some simulations and plots it to a graph (using Google Charts). All of the data will originate in the JavaScript code on the page (i.e. I'm not trying to pull in data from a database or anything like that). For this reason, I would like to have access to the data table from other functions so the data can be updated when a new simulation is run.
What I'm running into is that if I build a data table (and data view) inside of the drawChart() function, everything works fine. See this jsfiddle or the following code:
//Google charts stuff
google.charts.load('current', { 'packages': ['line', 'corechart'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -.5, 5.7],
[0.1, .4, 8.7],
[0.2, .5, 12]
]);
var forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
But if I move the code for the creation of the data table and data view outside of the function scope, it doesn't work. See this jsfiddle or the following code:
var sim_data;
var forceDataView;
//Google charts stuff
google.charts.load('current', { 'packages': ['line', 'corechart'] });
sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -0.5, 5.7],
[0.1, 0.4, 8.7],
[0.2, 0.5, 12]
]);
forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
Both of these examples use the following HTML:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="force_chart_div"></div>
I thought it might have something to do with the execution order of the callback function. But putting it in different spots in the code doesn't seem to change anything. In my full project, I went so far as to add a button that called the drawChart() function just to check, but that didn't help either.
Depending on where I put the callback function call, I'll get a red "Data Table is not Defined" alert showing up where the chart is supposed to be on the webpage. That pretty much tells me what I already suspected, but I don't know how to fix it. Any help would be appreciated. I'm a huge JS noob, by the way, so go easy on me.
your instinct was correct, you must wait on the callback to finish,
before using the google.visualization or google.charts namespaces.
it has to do more with timing, than placement of the code.
instead of using the callback statement, we can use the promise that the load statement returns.
as in the following snippet...
var sim_data;
var forceDataView;
//Google charts stuff
google.charts.load('current', {
packages: ['line', 'corechart']
}).then(function () {
sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -0.5, 5.7],
[0.1, 0.4, 8.7],
[0.2, 0.5, 12]
]);
forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
});
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
In my PHP application I'm using 2 php files.
chart.php - Page contains a google chart.
<div id="chart_div" style="height:100%;width:100%">
</div>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Opening Move', 'Percentage'],
["King's pawn (e4)", 44],
["Queen's pawn (d4)", 31],
["Knight to King 3 (Nf3)", 12],
["Queen's bishop pawn (c4)", 10],
['Other', 3]
]);
var options = {
title: 'Chess opening moves',
width: 900,
legend: { position: 'none' },
chart: { title: 'Chess opening moves',
subtitle: 'popularity by percentage' },
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
0: { side: 'top', label: 'Percentage'} // Top x-axis.
}
},
bar: { groupWidth: "90%" }
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, options);
google.visualization.events.addListener(chart, 'select', selectHandler);
};
function selectHandler() {
window.location.href = "chart.php";
}
</script>
2. index.php - Home page where I'm including chart.php in a div
<div style="width:40%">
require_once 'chart.php';
</div>
On clicking the chart in index.php page , it will call selectHandler() and redirect to chart.php.
The issue is, the chart in chart.php (after redirecting from index.php) is showing in small size similar to the chart display in index.php. Once I refreshes the chart.php it will display the chart in correct size.
Is there any function in jquery to refresh a page by reloading other than using location.reload().
Can anyone help me to fix this issue? Thanks in advance.
try redrawing the chart,
use an inline function on your select handler,
so you can still access your chart, data, and options.
google.visualization.events.addListener(chart, 'select', function () {
window.location.href = "chart.php";
chart.draw(data, options);
});
So, I have two Google bar charts displayed on the same page.I tried creating one event handler for both of them and passing in the chart and data into the selectHandler. Can someone tell me what I'm doing wrong?
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawBasic);
function drawBasic() {
var data1 = google.visualization.arrayToDataTable([
['Condition', 'Frequency'],
['Dementia', 6081],
['Hypertension', 6055],
['Hypercholesterolemia', 6035],
]);
var data2 = google.visualization.arrayToDataTable([
['Medication', 'Frequency'],
['Naproxen', 7632],
['Plavix', 7486]
]);
var options1 = {
title: 'Medical Conditions',
};
var options2 = {
title: 'Medications',
};
var conditionbarchart = new google.charts.Bar(
document.getElementById('conditions_chart'));
conditionbarchart.draw(data1, options1);
var medchart = new google.visualization.ColumnChart(
document.getElementById('medications_chart'));
medchart.draw(data2, options2);
google.visualization.events.addListener(conditionbarchart, 'select', selectHandler(conditionbarchart, data1));
google.visualization.events.addListener(medchart, 'select', selectHandler());
}
function selectHandler(mychart, mydata){
var selectedItem = mychart.getSelection()[0];
if(selectedItem){
var selection = mydata.getValue(selectedItem.row, 0);
alert('The user selected' + selection);
}
}
Here's the complete solution to answer my question:
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.charts.load('current', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.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', 'Condition');
data.addColumn('number', 'Frequency');
data.addRows([
['Dementia', 3],
['Hypertension', 1],
['Hypercholesterolemia', 1],
['Coronary artery disease', 1],
['Heaches', 2]
]);
// Create the data table.
var data2 = new google.visualization.DataTable();
data2.addColumn('string', 'Medication');
data2.addColumn('number', 'Frequency');
data2.addRows([
['Naproxen', 3],
['Plavix', 1],
['Lasix', 1],
['Insulin', 1],
['Neurontin', 2]
]);
// Set chart options
var options = {
bars: 'vertical', // Required for Material Bar Charts.
hAxis: {
slantedText:true,
slantedTextAngle:90
},
height: 400,
backgroundColor: {fill: 'transparent'},
legend: {position: 'none'},
colors: ['#1b9e77']
};
// Set chart options
var options2 = {
bars: 'vertical', // Required for Material Bar Charts.
hAxis: {
slantedText:true,
slantedTextAngle:90
},
height: 400,
backgroundColor: {fill: 'transparent'},
legend: {position: 'none'},
colors: ['#1b9e77']
};
// Instantiate and draw our chart, passing in some options.
var conditionsbarchart = new google.visualization.ColumnChart(document.getElementById('conditions_chart'));
var medchart = new google.visualization.ColumnChart(document.getElementById('medications_chart'));
function selectHandler(mychart, mydata) {
var selectedItem = mychart.getSelection()[0];
if (selectedItem) {
var topping = mydata.getValue(selectedItem.row, 0);
alert('The user selected ' + topping);
}
}
google.visualization.events.addListener(conditionsbarchart, 'select', function(){
selectHandler(conditionsbarchart, data);
});
conditionsbarchart.draw(data, options);
google.visualization.events.addListener(medchart, 'select', function(){
selectHandler(medchart, data2);
});
medchart.draw(data2, options2);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div id="conditions_chart" style="width:400; height:300"></div>
<div id="medications_chart" style="width: 400; height: 300"></div>
</body>
</html>
I'm trying to create an HTML rendered title in Google Charts. I want to create a string variable that contains HTML code and then pass it on as the title of the chart. Here's a jsFiddle. Here's what I'm trying to do:
HTML
<div id="chart_div" style="width: 900px; height: 500px;"></div>
JS
google.load("visualization", "1", {
packages: ["corechart"]
});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var ch = "<span>Hello World!</span>";
ch = $($.parseHTML(ch));
var options = {
title: ch
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
When I try outputting the string as a title, I get [object object]. I tried doing $($.parseHTML(ch)).html(); but it looks like this strips the HTML tags because when I add styling to the span element it doesn't style the title. What should I do to get an HTML string to be displayed as a title with styling?
the titleTextStyle option applies to the entire chart title,
it is not possible using standard config options to style only part of the title
it will also not accept html, since it is drawn using svg
you could use an adjacent <div> and leave the title out of the options,
or change the title's svg once the chart's 'ready' event fires...
the title will be in a svg <text> element,
to separate the title from the other <text> elements on the chart,
use an initial value that can be used to find it...
var options = {
title: 'chartTitle'
};
in the ready handler, find the element...
google.visualization.events.addListener(chart, 'ready', function () {
var chartTitle = $('#chart text').filter(':contains("chartTitle")')[0];
});
use the <tspan> element to style different parts of the <text> element
result may look something like this...
<text><tspan style="font-weight: bold;">Chart</tspan> Title</text>
see following working snippet...
google.charts.load('current', {
callback: function () {
var data = new google.visualization.DataTable({
cols: [
{label: 'x', type: 'string'},
{label: 'y0', type: 'number'},
],
rows: [
{c:[{v: 'row 0'}, {v: 10}]},
{c:[{v: 'row 1'}, {v: 5}]},
{c:[{v: 'row 2'}, {v: 1}]},
{c:[{v: 'row 3'}, {v: 2}]},
{c:[{v: 'row 4'}, {v: 8}]}
]
});
var options = {
title: 'chartTitle'
};
var container = document.getElementById('chart');
var chart = new google.visualization.LineChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var svgNS = $('#chart svg')[0].namespaceURI;
var chartTitle = $('#chart text').filter(':contains("chartTitle")')[0];
$(chartTitle).text('');
var textStyle = document.createElementNS(svgNS, 'tspan');
$(textStyle).attr('fill', '#ff0000');
$(textStyle).attr('font-weight', 'bold');
$(textStyle).text('Chart ');
$(chartTitle).append(textStyle);
var textStyle = document.createElementNS(svgNS, 'tspan');
$(textStyle).attr('fill', '#0000ff');
$(textStyle).attr('font-weight', 'normal');
$(textStyle).text('Title');
$(chartTitle).append(textStyle);
});
chart.draw(data, options);
},
packages: ['corechart']
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
I'm not sure about editing it with HTML/CSS but you can use something that google-charts offers with titleTextStyle
var options = {
titleTextStyle: {
color: <string>, // any HTML string color ('red', '#cc00cc')
fontName: <string>, // i.e. 'Times New Roman'
fontSize: <number>, // 12, 18 whatever you want (don't specify px)
bold: <boolean>, // true or false
italic: <boolean> // true of false
}
}
Comes from this stack answer: Stack
Google Documentation here: Chart Customization