Dynamic Vertical Axis to Accommodate Trendline(s) in Google Line Chart - javascript

I'm new to coding but over the last several months I've managed to fumble my way through creating a web site that utilises a Google Line Chart and embedded linear trendline to display historical Mean Sea Level and the rate of Mean Sea Level rise for various locations around New Zealand and the Pacific. Each location has it's own Google Line Chart with a linear trendline to show the rate of Mean Sea Level Change for a user selected period. I now want to extend the functionality of each Google Line Chart such that both a linear and polynomial trendline extend to the year 2120 (they currently only show up to the year 2018) even though the available data from which they are calculated uses observed data up to the year 2018. This will allow the user to predict the sea level height up to the year 2020. I realise this explanation may be confusing, so please see my web site www.sealevel.nz to see the existing charts which I hope will aid in understanding my problem.
Below is the code for the extended version of the chart that shows both a linear and second degree polynomial trendline with the x axis of the Google Line Chart now showing up the year 2120. My problem is that I need the y axis to adjust dynamically to show the entirety of both trendlines no matter which time period the user selects. For example if you select the years 1971 and 2018 from the date range slider, then both trendlines are cut off at the years 2017 (linear) and 2031 (polynomial) respectively. I need to be able to see both trendlines and their values up to the year 2120.
Please excuse my novice coding skills. My Code:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://unpkg.com/mathjs/dist/math.min.js"></script>
<script type="text/javascript">
google.load('visualization', 'current', {'packages':['controls','corechart']});
google.setOnLoadCallback(initialize);
function initialize() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1vn1iuhsG33XzFrC4QwkTdUnxOGdcPQOj-cuaEZeX-eA/edit#gid=0');
query.send(drawDashboard);
}
function drawDashboard(response) {
var data = response.getDataTable();
//Asign units of 'mm' to data.
var formatMS = new google.visualization.NumberFormat({
pattern: '# mm'
});
// format into data mm..
for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {
formatMS.format(data, colIndex);
}
var YearPicker = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'filter_div',
'options': {
'filterColumnLabel': 'Year',
'ui': {
cssClass: 'filter-date',
'format': { pattern: '0000' },
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
},
});
var MSLChart = new google.visualization.ChartWrapper({
'chartType': 'LineChart',
'containerId': 'chart_div',
'options': {
'fontSize': '14',
'title': 'Timbucktoo Annual Mean Sea Level Summary',
hAxis: {title: 'Year', format:'0000', maxValue: 2120},
vAxis: {title: 'Height above Chart Datum (mm)', format:'0000'},
'height': 600,
chartArea: {height: '81%', width: '85%', left: 100},
'legend': {'position': 'in', 'alignment':'end', textStyle: {fontSize: 13} },
colors: ['blue'],
trendlines: {
0: {
type: 'polynomial',
degree: 2,
color: 'green',
visibleInLegend: true,
},
1: {
type: 'linear',
color: 'black',
visibleInLegend: true,
},
},
series: {
0: { visibleInLegend: true },
1: { visibleInLegend: false },
},
},
'view': {'columns': [0,1,2]}
});
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_div')).
bind(YearPicker, MSLChart).
draw(data)
</script>

first, I'm not sure why the chart would draw a trend line that isn't visible
which makes this a bit tricky, because we first have to draw the chart,
in order to find the min & max y-axis values.
but there are chart methods we can use to find the max value.
first, we get the chart's layout interface.
var chartLayout = MSLChart.getChart().getChartLayoutInterface();
since we're using a ChartWrapper, we have to get the chart from the wrapper (MSLChart.getChart()).
next, we use method getBoundingBox to find the min & max values of each line.
var yAxisCoords = {min: null, max: null};
var lineIndex = 0;
var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
do {
yAxisCoords.max = yAxisCoords.max || boundsLine.top;
yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
lineIndex++;
boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
} while (boundsLine !== null);
then we use method getVAxisValue to determine what each y-axis value should be,
set the viewWindow on the y-axis, and re-draw the chart.
MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
MSLChart.draw();
we do all this in a function.
we use a one time 'ready' event on the chart wrapper for the first calculation.
then again, on the chart.
google.visualization.events.addOneTimeListener(MSLChart, 'ready', filterChange);
function filterChange() {
// get chart layout
var chartLayout = MSLChart.getChart().getChartLayoutInterface();
// get y-axis bounds
var yAxisCoords = {min: null, max: null};
var lineIndex = 0;
var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
do {
yAxisCoords.max = yAxisCoords.max || boundsLine.top;
yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
lineIndex++;
boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
} while (boundsLine !== null);
// re-draw chart
MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
MSLChart.draw();
google.visualization.events.addOneTimeListener(MSLChart.getChart(), 'ready', filterChange);
}
see following working snippet...
(when you run the snippet, click "full page" at the top right)
google.charts.load('current', {
packages: ['controls']
}).then(initialize);
function initialize() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1vn1iuhsG33XzFrC4QwkTdUnxOGdcPQOj-cuaEZeX-eA/edit#gid=0');
query.send(drawDashboard);
}
function drawDashboard(response) {
var data = response.getDataTable();
//Asign units of 'mm' to data.
var formatMS = new google.visualization.NumberFormat({
pattern: '# mm'
});
// format into data mm..
for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {
formatMS.format(data, colIndex);
}
var YearPicker = new google.visualization.ControlWrapper({
controlType: 'NumberRangeFilter',
containerId: 'filter_div',
options: {
filterColumnLabel: 'Year',
ui: {
cssClass: 'filter-date',
format: {pattern: '0000'},
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: false
}
},
});
var MSLChart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart_div',
dataTable: data,
options: {
fontSize: '14',
title: 'Timbucktoo Annual Mean Sea Level Summary',
hAxis: {title: 'Year', format: '0000', maxValue: 2120},
vAxis: {title: 'Height above Chart Datum (mm)', format:'###0'},
height: 600,
chartArea: {height: '81%', width: '85%', left: 100},
legend: {position: 'in', alignment: 'end', textStyle: {fontSize: 13}},
colors: ['blue'],
trendlines: {
0: {
type: 'polynomial',
degree: 2,
color: 'green',
visibleInLegend: true,
},
1: {
type: 'linear',
color: 'black',
visibleInLegend: true,
},
},
series: {
0: { visibleInLegend: true },
1: { visibleInLegend: false },
},
},
view: {columns: [0,1,2]}
});
google.visualization.events.addOneTimeListener(MSLChart, 'ready', filterChange);
function filterChange() {
// get chart layout
var chartLayout = MSLChart.getChart().getChartLayoutInterface();
// get y-axis bounds
var yAxisCoords = {min: null, max: null};
var lineIndex = 0;
var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
do {
yAxisCoords.max = yAxisCoords.max || boundsLine.top;
yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
lineIndex++;
boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
} while (boundsLine !== null);
// re-draw chart
MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
MSLChart.draw();
google.visualization.events.addOneTimeListener(MSLChart.getChart(), 'ready', filterChange);
}
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div')
).bind(YearPicker, MSLChart).draw(data);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_div">
<div id="chart_div"></div>
<div id="filter_div"></div>
</div>
note: it appears you're using an old load statement, to load google chart.
see above snippet for update...

Related

Prevent some items to be filtered in Google Combochart view

I have a category filtering combochart, which is perfectly working with the following code:
var columnsTable = new google.visualization.DataTable();
columnsTable.addColumn('number', 'colIndex');
columnsTable.addColumn('string', 'colLabel');
var initState= {selectedValues: []};
// put the columns into this data table (skip column 0)
for (var i = 1; i < data.getNumberOfColumns(); i++) {
columnsTable.addRow([i, data.getColumnLabel(i)]);
// you can comment out this next line if you want to have a default selection other than the whole list
initState.selectedValues.push(data.getColumnLabel(i));
}
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'myPieChart2',
dataTable: data,
options: {
height: 300,
hAxis: {
title: 'Time'
},
vAxis: {
title: 'Flight Hours (min)'
},
title: 'Annual Flight Times by Pilot',
bar: {groupWidth: '90%'},
seriesType: 'bars',
series: {
0: {type: 'line',
lineDashStyle: [4, 4]},
1: {type: 'line',
lineDashStyle: [14, 2, 2, 7]},
}
//theme: 'material'
}
});
var columnFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'colFilter_div2',
dataTable: columnsTable,
options: {
filterColumnLabel: 'colLabel',
ui: {
label: 'Pilots',
allowTyping: false,
allowMultiple: true,
allowNone: false,
//selectedValuesLayout: 'belowStacked'
}
},
state: initState
});
function setChartView () {
var state = columnFilter.getState();
var row;
var view = {
columns: [0]
};
for (var i = 0; i < state.selectedValues.length; i++) {
row = columnsTable.getFilteredRows([{column: 1, value: state.selectedValues[i]}])[0];
view.columns.push(columnsTable.getValue(row, 0));
}
// sort the indices into their original order
view.columns.sort(function (a, b) {
return (a - b);
});
chart.setView(view);
chart.draw();
}
google.visualization.events.addListener(columnFilter, 'statechange', setChartView);
setChartView();
columnFilter.draw();
});
In my data, first two columns (Series 0 and Series 1) belongs to Total and Average of the relevant months. So, I would like to make them constant, which means that they can not be closed (See the image).
Alternatively, if there is a method to exclude them from dropdown & filtering options, but still show at the chart, this can be accepted. In the end, I would like to prevent user to close these items.
How can I do that? I spent two hours for it but still I am stucked.
Thanks for your help in advance.

Continuous Axis Chart with Slider Range won't draw?

I'm finding myself in over my head on this web development project, and was hoping someone could help me better understand why one of my google charts will not draw on my page.
I have a working test page with the chart drawing how I want it, this is the jsfiddle for it so you can have the exact code if you wish to test
http://jsfiddle.net/dlaliberte/pfTqP/
I pulled the code directly from this page where it works, and put it into my page that already has 4 other working google charts on it. Now when I add in this chart it doesn't give me any errors but it just will not draw.
I'm going to post the javascript for the first chart that works and the chart I'm trying to fix (separated with '###'), and the spot on my page where it's set to draw, I'm hoping someone with more experience could help me spot where the issue is coming from, as after several hours of tweaking and running over it I'm still not sure what's going wrong.
//################################### UPDATED JAVASCRIPT ####################################
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery.csv.min.js"></script>
<script type="text/javascript"> // load the visualisation API
google.charts.load('visualization', 'current', '1.1',
{
callback: drawCharts,
packages: ['corechart', 'controls']
});
/* Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawLineChart);
google.charts.setOnLoadCallback(drawBarChart);
google.setOnLoadCallback(drawVisualization);
*/
function drawCharts() {
drawLineChart();
drawBarChart();
drawBarVisualization();
drawPieVisualization();
drawVisualization();
}
function drawLineChart() {
var jsonData = $.ajax({
url: "getData.php",
dataType: "json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
var options = {
title: 'Average Ratings',
'vAxis': { title: "Average Rating" },
'width': 1100,
'height': 540,
'legend': { position: 'bottom'},
'is3D':true,
'padding': 20,
'backgroundColor': 'Ivory',
'color':'Black',
hAxis: {
textStyle:{color: 'Black', weight: 'bold'}
},
series:
{
0: { color: 'Black', pointShape: 'square'},
}
}
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
google.visualization.events.addListener('testBtn', 'click',
function(event) {
data.sort({column: 0, desc: false});
chart.draw(data, options);
});
changeLineRange = function() {
data.sort({column: 0, desc: false});
chart.draw(data, options);
};
changeLineRangeBack = function() {
data.sort({column: 0, desc: true});
chart.draw(data, options);
};
}
function drawBarChart() {
var jsonData = $.ajax({
url: "getData.php",
dataType: "json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
var options = {
title: 'Average Ratings',
'vAxis': { title: "Average Rating" },
'width': 700,
'height': 540,
'legend':{position:'top',alignment:'start'},
'is3D':true,
'padding': 20,
'backgroundColor': 'Ivory',
series: {
0: { color: 'Black' },
},
'hAxis': {
title: "Date",
gridlines: { count: 3, color: '#CCC' },
format: 'dd-MMM-yyyy'
}
}
// Instantiate and draw our chart, passing in some options.
var chart2 = new google.visualization.ColumnChart(document.getElementById('bar_chart_div'));
chart2.draw(data, options);
changeOptions = function() {
chart2.setOption('is3D', true);
chart2.draw();
};
}
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
});
$('#myTabs a').click(function (e) {
e.preventDefault()
$(this).tab('show')
})
//Triple Line Chart
function drawVisualization() {
$.get("MockWeek.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
// CAPACITY - En-route ATFM delay - YY - CHART
var crt_ertdlyYY = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'crt_ertdlyYY',
dataTable: data,
options:{
'title': 'Average Ratings',
'vAxis': { title: "Average Rating" },
'width': 1100,
'height': 540,
'backgroundColor': 'Ivory',
'color':'Black',
'hAxis': {
title: "Date",
gridlines: { count: 3, color: '#CCC' },
format: 'dd-MMM-yyyy'
},
title: 'KWh Usage - Temperature Projected',
titleTextStyle : {color: 'Black', fontSize: 14},
curveType: 'function'
}
});
crt_ertdlyYY.draw();
changeRange = function() {
data.sort({column: 0, desc: false});
crt_ertdlyYY.draw();
};
changeRangeBack = function() {
data.sort({column: 0, desc: true});
crt_ertdlyYY.draw();
};
});
}
google.setOnLoadCallback(drawVisualization)
//Triple Pie Chart
function drawPieVisualization() {
$.get("Thornton.M2.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
// CAPACITY - En-route ATFM delay - YY - CHART
var pieMain = new google.visualization.ChartWrapper({
chartType: 'BarChart',
containerId: 'pieMain',
dataTable: data,
options:{
title: 'Bar Chart Test',
'vAxis': { title: "Bar Chart Test" },
'width': 1100,
'height': 530,
'backgroundColor': 'Ivory',
'color':'Black',
'hAxis': {
title: "Date",
gridlines: { count: 3, color: '#CCC' },
format: 'dd-MMM-yyyy'
},
title: 'Bar Chart Test',
titleTextStyle : {color: 'Black', fontSize: 16},
}
});
pieMain.draw();
});
}
google.setOnLoadCallback(drawPieVisualization)
changeRange = function() {
pieMain.sort({column: 0, desc: false});
pieMain.draw();
};
changeRangeBack = function() {
pieMain.sort({column: 0, desc: true});
pieMain.draw();
};
function drawVisualization() {
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard'));
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control',
'options': {
// Filter by the date axis.
'filterColumnIndex': 0,
'ui': {
'chartType': 'LineChart',
'chartOptions': {
'chartArea': {'width': '90%'},
'hAxis': {'baselineColor': 'none' }
},
// Display a single series that shows the closing value of the stock.
// Thus, this view has two columns: the date (axis) and the stock value (line series).
'chartView': {
'columns': [0, 3]
},
// 1 day in milliseconds = 24 * 60 * 60 * 1000 = 86,400,000
'minRangeSize': 86400000
}
},
// Initial range: 2012-02-09 to 2012-03-20.
'state': {'range': {'start': new Date(2012, 1, 9), 'end': new Date(2012, 2, 20)}}
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'CandlestickChart',
'containerId': 'chart',
'options': {
// Use the same chart area width as the control for axis alignment.
'chartArea': {'height': '80%', 'width': '90%'},
'hAxis': {'slantedText': false},
'vAxis': {'viewWindow': {'min': 0, 'max': 2000}},
'legend': {'position': 'none'}
},
// Convert the first column from 'date' to 'string'.
'view': {
'columns': [
{
'calc': function(dataTable, rowIndex) {
return dataTable.getFormattedValue(rowIndex, 0);
},
'type': 'string'
}, 1, 2, 3, 4]
}
});
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Stock low');
data.addColumn('number', 'Stock open');
data.addColumn('number', 'Stock close');
data.addColumn('number', 'Stock high');
// Create random stock values, just like it works in reality.
var open, close = 300;
var low, high;
for (var day = 1; day < 121; ++day) {
var change = (Math.sin(day / 2.5 + Math.PI) + Math.sin(day / 3) - Math.cos(day * 0.7)) * 150;
change = change >= 0 ? change + 10 : change - 10;
open = close;
close = Math.max(50, open + change);
low = Math.min(open, close) - (Math.cos(day * 1.7) + 1) * 15;
low = Math.max(0, low);
high = Math.max(open, close) + (Math.cos(day * 1.3) + 1) * 15;
var date = new Date(2012, 0 ,day);
data.addRow([date, Math.round(low), Math.round(open), Math.round(close), Math.round(high)]);
}
dashboard.bind(control, chart);
dashboard.draw(data);
}
</script>
And here is the spot I'm drawing the chart on my page, it's in a set of 4 tabs so the user can tab through different charts, so far it's worked perfectly.
<div class="col-md-12">
<h2 align="center" class="featurette-heading">Current Demand -<span style="color: Ivory;"> Hourly Usage</span></h2>
<br/>
<ul class="nav nav-tabs" role="tablist" data-tabs="tabs">
<li role="presentation" class="active">Usage</li>
<li role="presentation">Demand</li>
<li role="presentation">Daily</li>
<li role="presentation">Monthly</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade in active" align="center" id="home"> <div class="chart" id="chart_div"></div>
<button class="btn btn-primary raised" onclick="changeLineRange();">
Ascending
</button>
<button class="btn btn-primary raised" onclick="changeLineRangeBack();">
Descending
</button><br /></div>
<div role="tabpanel" class="tab-pane fade" align="center" id="profile"><div class="chart" id="crt_ertdlyYY"></div>
<button class="btn btn-primary raised" onclick="changeRange();">
Ascending
</button>
<button class="btn btn-primary raised" onclick="changeRangeBack();">
Descending
</button><br /></div>
// ############################## THIS IS THE TAB PANEL WHERE I'M DRAWING THE NEW CHART ############################
<div role="tabpanel" class="tab-pane fade">
<div class="chart" id="dashboard">
<div id="chart" style='width: 915px; height: 300px;'></div>
<div id="control" style='width: 915px; height: 50px;'></div>
</div>
</div>
<div role="tabpanel" class="tab-pane fade" id="settings"><div class="chart" id="pieMain"></div></div>
</div>
</div>
I'm not sure what else you might need to see, again I'm out of my element here and trying to get a grasp on how to achieve this, thanks!
there are a couple issues here...
first, code is mixed from both the old and new versions of google charts
the old library uses jsapi to load the library
<script src="http://www.google.com/jsapi"></script>
the new library uses the gstatic library
<script src="https://www.gstatic.com/charts/loader.js"></script>
according to 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 from now on.
next, the load statement and callback should only be used once per page
once the callback fires, you can draw as many charts as needed
the callback can also be placed directly in the load statement
try setup similar to the following...
google.charts.load('current', {
callback: drawCharts,
packages: ['controls', 'corechart']
});
function drawCharts() {
drawLineChart();
drawVisualization();
}
function drawLineChart() {
...
}
function drawVisualization() {
...
}

Continuous Axis Google Chart Loaded with CSV?

I've managed to implement a continuous axis google chart on my page and got it formatted the way I want it. Now my requirements have changed and I'm trying to load this chart from a CSV as opposed to hard coded and randomly generated data.
I've confused myself and gotten in over my head on how to convert my working chart into pulling from a CSV. I'm going to post a few things here,
One of my other charts that utilizes a CSV, this is what I was trying to recreate
My working continuous axis chart running off hard coded data
My current state of the chart now that I've tried to implement the change.
Here is #1:
function drawPieVisualization() {
$.get("Thornton.M2.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
// CAPACITY - En-route ATFM delay - YY - CHART
var pieMain = new google.visualization.ChartWrapper({
chartType: 'BarChart',
containerId: 'pieMain',
dataTable: data,
options:{
title: 'Bar Chart Test',
'vAxis': { title: "Bar Chart Test" },
'width': 1100,
'height': 540,
'backgroundColor': 'Ivory',
'color':'Black',
'hAxis': {
title: "Date",
gridlines: { count: 3, color: '#CCC' },
format: 'dd-MMM-yyyy'
},
title: 'Bar Chart Test',
titleTextStyle : {color: 'Black', fontSize: 16},
}
});
pieMain.draw();
});
}
google.setOnLoadCallback(drawPieVisualization)
changeRange = function() {
pieMain.sort({column: 0, desc: false});
pieMain.draw();
};
changeRangeBack = function() {
pieMain.sort({column: 0, desc: true});
pieMain.draw();
};
Here is #2:
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Value');
// add 100 rows of pseudo-random-walk data
for (var i = 0, val = 50; i < 100; i++) {
val += ~~(Math.random() * 5) * Math.pow(-1, ~~(Math.random() * 2));
if (val < 0) {
val += 5;
}
if (val > 100) {
val -= 5;
}
data.addRow([new Date(2014, 0, i + 1), val]);
}
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
containerId: 'slider_chart_div',
options: {
'title': 'Average Ratings',
'vAxis': { title: "Average Rating" },
'backgroundColor': 'Ivory',
'color':'Black',
width: 1100,
height: 400,
// omit width, since we set this in CSS
chartArea: {
width: '75%' // this should be the same as the ChartRangeFilter
}
}
});
var control = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control_div',
options: {
filterColumnIndex: 0,
ui: {
chartOptions: {
'backgroundColor': 'Ivory',
'color':'Black',
width: 1100,
height: 50,
// omit width, since we set this in CSS
chartArea: {
width: '75%' // this should be the same as the ChartRangeFilter
}
}
}
}
});
var dashboard = new google.visualization.Dashboard(document.querySelector('#dashboard_div'));
dashboard.bind([control], [chart]);
dashboard.draw(data);
function zoomLastDay () {
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth(), range.max.getDate() - 1),
end: range.max
}
});
control.draw();
}
function zoomLastWeek () {
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth(), range.max.getDate() - 7),
end: range.max
}
});
control.draw();
}
function zoomLastMonth () {
// zoom here sets the month back 1, which can have odd effects when the last month has more days than the previous month
// eg: if the last day is March 31, then zooming last month will give a range of March 3 - March 31, as this sets the start date to February 31, which doesn't exist
// you can tweak this to make it function differently if you want
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth() - 1, range.max.getDate()),
end: range.max
}
});
control.draw();
}
var runOnce = google.visualization.events.addListener(dashboard, 'ready', function () {
google.visualization.events.removeListener(runOnce);
if (document.addEventListener) {
document.querySelector('#lastDay').addEventListener('click', zoomLastDay);
document.querySelector('#lastWeek').addEventListener('click', zoomLastWeek);
document.querySelector('#lastMonth').addEventListener('click', zoomLastMonth);
}
else if (document.attachEvent) {
document.querySelector('#lastDay').attachEvent('onclick', zoomLastDay);
document.querySelector('#lastWeek').attachEvent('onclick', zoomLastWeek);
document.querySelector('#lastMonth').attachEvent('onclick', zoomLastMonth);
}
else {
document.querySelector('#lastDay').onclick = zoomLastDay;
document.querySelector('#lastWeek').onclick = zoomLastWeek;
document.querySelector('#lastMonth').onclick = zoomLastMonth;
}
});
}
And Here is #3:
function drawVisualization() {
$.get("Source7Days.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
containerId: 'slider_chart_div',
dataTable: data,
options: {
'title': 'Average Ratings',
'vAxis': { title: "Average Rating" },
'backgroundColor': 'Ivory',
'color':'Black',
width: 1100,
height: 400,
// omit width, since we set this in CSS
chartArea: {
width: '75%' // this should be the same as the ChartRangeFilter
}
}
});
var control = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control_div',
options: {
filterColumnIndex: 0,
ui: {
chartOptions: {
'backgroundColor': 'Ivory',
'color':'Black',
width: 1100,
height: 50,
// omit width, since we set this in CSS
chartArea: {
width: '75%' // this should be the same as the ChartRangeFilter
}
}
}
}
});
var dashboard = new google.visualization.Dashboard(document.querySelector('#dashboard_div'));
dashboard.bind([control], [chart]);
dashboard.draw(data);
function zoomLastDay () {
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth(), range.max.getDate() - 1),
end: range.max
}
});
control.draw();
}
function zoomLastWeek () {
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth(), range.max.getDate() - 7),
end: range.max
}
});
control.draw();
}
function zoomLastMonth () {
// zoom here sets the month back 1, which can have odd effects when the last month has more days than the previous month
// eg: if the last day is March 31, then zooming last month will give a range of March 3 - March 31, as this sets the start date to February 31, which doesn't exist
// you can tweak this to make it function differently if you want
var range = data.getColumnRange(0);
control.setState({
range: {
start: new Date(range.max.getFullYear(), range.max.getMonth() - 1, range.max.getDate()),
end: range.max
}
});
control.draw();
}
var runOnce = google.visualization.events.addListener(dashboard, 'ready', function () {
google.visualization.events.removeListener(runOnce);
if (document.addEventListener) {
document.querySelector('#lastDay').addEventListener('click', zoomLastDay);
document.querySelector('#lastWeek').addEventListener('click', zoomLastWeek);
document.querySelector('#lastMonth').addEventListener('click', zoomLastMonth);
}
else if (document.attachEvent) {
document.querySelector('#lastDay').attachEvent('onclick', zoomLastDay);
document.querySelector('#lastWeek').attachEvent('onclick', zoomLastWeek);
document.querySelector('#lastMonth').attachEvent('onclick', zoomLastMonth);
}
else {
document.querySelector('#lastDay').onclick = zoomLastDay;
document.querySelector('#lastWeek').onclick = zoomLastWeek;
document.querySelector('#lastMonth').onclick = zoomLastMonth;
}
});
}
)}
And here is a sample of the CSV Data I'm utilizing
Time,Value
2017/05/22 00:05:00,6710.4305066168
2017/05/22 00:10:00,6667.5043776631
2017/05/22 00:15:00,6615.6655550003
2017/05/22 00:20:00,6554.988194257
2017/05/22 00:25:00,6532.4164219201
2017/05/22 00:30:00,6520.8965539932
The bottom part 'runOnce' in both #2 and #3 are to change the slider control on the chart from 1 day - 1 week - or 1 month of range on the chart, for clarification.
My chart is currently giving me the errors:
One or more participants failed to draw(). (Two of these)
And
The filter cannot operate on a column of type string. Column type must
be one of: number, date, datetime or timeofday. Column role must be
domain, and correlate to a continuous axis.
the second error message reveals that arrayToDataTable
creates the first column as --> type: 'string'
instead of --> type: 'date'
use a DataView to convert the string to a date
you can create calculated columns in a data view using method --> setColumns
use view in place of data when drawing the dashboard
see following snippet...
$.get("Source7Days.csv", function(csvString) {
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}, {onParseValue: $.csv.hooks.castToScalar});
// this is a static method, "new" keyword should not be used here
var data = google.visualization.arrayToDataTable(arrayData);
// create view
var view = new google.visualization.DataView(data);
view.setColumns([
// first column is calculated
{
calc: function (dt, row) {
// convert string to date
return new Date(dt.getValue(row, 0));
},
label: data.getColumnLabel(0),
type: 'date'
},
// just use index # for second column
1
]);
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
containerId: 'slider_chart_div',
options: {
title: 'Average Ratings',
vAxis: { title: 'Average Rating' },
backgroundColor: 'Ivory',
color: 'Black',
width: 1100,
height: 400,
chartArea: {
width: '75%'
}
}
});
var control = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control_div',
options: {
filterColumnIndex: 0,
ui: {
chartOptions: {
backgroundColor: 'Ivory',
color: 'Black',
width: 1100,
height: 50,
chartArea: {
width: '75%'
}
}
}
}
});
var dashboard = new google.visualization.Dashboard(document.querySelector('#dashboard_div'));
dashboard.bind([control], [chart]);
// use data view
dashboard.draw(view);
...

Google chart api explorer vs. selecthandler

I have problem with using Google.charts api... i have chart drawing function like this:
function columnDraw(sectionname) {
var data = google.visualization.arrayToDataTable(array);
var view = new google.visualization.DataView(data);
var options = {
title: "Activity of users",
bar: {groupWidth: "100%"},
legend: {position: "top"},
height: 300,
// explorer: {
//maxZoomOut:0
//maxZoomIn: 50,
// keepInBounds: true,
// axis: 'horizontal'
// },
hAxis: {
title: 'Amount of activity',
minValue : 0,
format: '0'
},
vAxis: {
title: 'Amount of users',
minValue : 0,
format: '0'
}
};
var chart = new google.visualization.ColumnChart(document.getElementById(sectionname));
function selectHandler() {
var selectedItem = chart.getSelection()[0];
if (selectedItem) {
document.getElementById("input0").value = data.getValue(selectedItem.row, 0);
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(view, options);
}
I want to choose parts of chartcolumn by cklicing on them, but i have a problem with zooming. This code works but once I uncomment the explorer part, selectHandler function wont work properly. Can anyone tell me whats wrong with it?
You're missing a ","
maxZoomOut:0,

Is it possible to create a dropdown controlwrapper from values in a row?

Is it possible to create a category filter that gets it's values from certain parts of the horizontal axis of a table. For instance in a table:
Heading 1|Heading 2|Heading 3|Heading 4|Heading 5
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AValue 1|AValue 2|AValue 3|AValue 4|AValue 5
BValue 1|BValue 2|BValue 3|BValue 4|BValue 5
CValue 1|CValue 2|CValue 3|CValue 4|CValue 5
Instead of having a dropdown with Heading1's Values, is it possible create dropdown with only Heading3,Heading4,Heading5 as values and then the chart data displayed is only the data underneath the particular heading selected?
var CountryPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'control3',
options: {
filterColumnLabel: 'Location',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: true,
caption: 'Country',
label: ''
}
}
});
EDIT:
Here is an image of the data table, I wish to be able to filter by Male, Female and Total through the dropdown.
CSV function for geochart:
function drawVisualization() {
$.get("Data_Actual_V2.csv", function(csvString) {
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
for (var i = 1; i < arrayData[0].length; i++) {
$("select").append("<option value='" + i + "'>" + arrayData[0][i] + "</option");
}
$("#range option[value='1']").attr("selected","selected");
var data = new google.visualization.arrayToDataTable(arrayData);
var geoChart = new google.visualization.ChartWrapper({
chartType: 'GeoChart',
containerId: 'chart1',
options: {
title: 'A',
displayMode: 'regions',
width: 1000,
datalessRegionColor: 'C0C0C0',
colorAxis: {
values: [0, 12.5, 25, 37.5, 50, 62.5, 75, 87.5, 100],
colors: ['#3366FF','#33CCCC', '#00FFFF', '#CCFFFF', '#00FF00', '#FFFF99','#FFCC00','#FF9900','#FF0000'],
minValue: 0,
maxValue: 100,
}
},
view: { // Defines data to show in geoChart
columns: [0, 4]
}
});
EDIT2: I have the chart working with the single filter as first asked, but intially had more than one filter available. eg, select country, then select by method above. An example of how I did this before getting the above working is below, but how can I incorporate this with the method described in the fiddle below?
var CountryPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'control3',
options: {
filterColumnLabel: 'Location',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: true,
caption: 'Country',
label: ''
}
}
});
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));
dashboard.bind([CountryPicker, GenderPicker, slider2],[geoChart]). // consolidated all of the bind calls
// Draw the dashboard
draw(data);

Categories