My target is to build a event listener that loops through the visualization's defined pickers to call setState() and draw() for each one.
My initial thought was something like this:
for (var i = 0; i < 2; i++) { // 2 is hard coded for simplicity
categoryPicker[i].setState({selectedValues: []});
categoryPicker[i].draw();
}
I've tried following to access the picker via it's method getState() as a test but can't seem get results unless I hard code it:
//This works when hard coded
console.log(categoryPicker1.getState());
//ERROR temp.picker.getState is not a function
temp = { picker: "categoryPicker" + i };
//console.log(temp.picker.getState());
//ERROR temp.picker.getState is not a function
temp2 = ["categoryPicker" + i];
//console.log(temp2[i].getState());
I need some guidance in figuring out how to call the pickers dynamically? I don't want to resort to using eval() for security reasons.
Your assistance is appreciated.
Full working example:
// Load the Visualization API and the corechart package.
google.charts.load('current', {
'packages': ['corechart', 'table', 'gauge', 'controls']
});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(gChart0);
function gChart0() {
drawChart();
}
function drawChart() {
var result = [{
"calendarWeek": "2017-W30",
"partId": '1234567890xxx',
"someNumber": 0
}, {
"calendarWeek": "2017-W30",
"partId": '1234567890yyy',
"someNumber": 0
}, {
"calendarWeek": "2017-W30",
"partId": '1234567890111',
"someNumber": 0
}];
//Create DataTable
var data = new google.visualization.DataTable();
data.addColumn('string', 'Calendar Week');
data.addColumn('string', 'Part Id');
data.addColumn('number', 'Some Number');
var dataArray = [];
$.each(result, function(i, obj) {
dataArray.push([
obj.calendarWeek,
obj.partId,
obj.someNumber
]);
});
data.addRows(dataArray);
//Options
var dashboard = new google.visualization.Dashboard(document.getElementById('div_dashboard'));
var categoryPicker0 = new google.visualization.ControlWrapper({
controlType: 'StringFilter',
containerId: 'div_categoryPicker1',
options: {
filterColumnIndex: 0,
matchType: 'any',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: false,
allowNone: true
}
}
});
var categoryPicker1 = new google.visualization.ControlWrapper({
controlType: 'StringFilter',
containerId: 'div_categoryPicker2',
options: {
filterColumnIndex: 1,
matchType: 'any',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: false,
allowNone: true
}
}
});
//ADDED THIS after suggestion from WhiteHat
var pickerArr = [categoryPicker0 , categoryPicker1 ];
var table = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'div_table',
options: {
width: '100%',
height: 'auto',
page: 'enable',
pageSize: '15',
sort: 'enable',
allowHtml: true
}
});
google.visualization.events.addOneTimeListener(dashboard, 'ready', function() {
// reset the category picker when clicked.
var reset = document.getElementById('categoryPicker_resetBtn');
reset.addEventListener('click', function() {
//categoryPicker0.setState({
//selectedValues: []
//});
//categoryPicker0.draw();
//categoryPicker1.setState({
//selectedValues: []
//});
//categoryPicker1.draw();
//ADDED THIS after suggestion from WhiteHat
for (var i = 0; i < pickerArr.length; ++i) {
pickerArr[i].setState({selectedValues: []}); //This resets pickers dynamically
pickerArr [i].draw();
}
});
});
dashboard.bind([categoryPicker0, categoryPicker1], [table]);
dashboard.draw(data);
} //END function drawChart()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="div_dashboard"></div>
<div id="div_categoryPicker1"></div>
<div id="div_categoryPicker2"></div><br>
<button id="categoryPicker_resetBtn">Reset</button><div id="div_table"></div>
UPDATE:
I was able to update my snippet above by adding the following code as suggested by WhiteHat.
This is set just after the pickers are defined:
//ADDED THIS after suggestion from WhiteHat
var pickerArr = [categoryPicker0 , categoryPicker1 ];
This replaces code I had in the event listener for the reset button:
//ADDED THIS after suggestion from WhiteHat
for (var i = 0; i < pickerArr.length; ++i) {
pickerArr[i].setState({selectedValues: []}); //This resets pickers dynamically
pickerArr [i].draw();
}
you could store them in an array...
var pickers = [];
pickers.push(new google.visualization.ControlWrapper({
controlType: 'StringFilter',
containerId: 'div_categoryPicker1',
options: {
filterColumnIndex: 0,
matchType: 'any',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: false,
allowNone: true
}
}
}));
pickers.push(new google.visualization.ControlWrapper({
controlType: 'StringFilter',
containerId: 'div_categoryPicker2',
options: {
filterColumnIndex: 1,
matchType: 'any',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: false,
allowNone: true
}
}
}));
then loop through the array...
pickers.forEach(function (picker) {
console.log(picker.getState());
});
Related
I'd like to draw google line chart with trending however type mismatch occurred because of date format.
The below is my code.gs which to return the date value to string from spreadsheet in the first column.
I'd tried to put new Date() in JS to draw the line chart with trending however i don't know how to put this date value in datatable.
In the JS, the columns can be dynamically added which it works. But i could not solve the date problem so please help.
Code.gs
function getSpreadsheetData() {
var ssID = "1994YM4uwB1mQORl-HLNk6o10-0ADLNQPgUxKGW6iW_8",
data = SpreadsheetApp.openById(ssID).getSheets()[0].getDataRange().getValues();
for(var i=1; i<data.length; i++){
var date = new Date(data[i][0]);
data[i][0] = Utilities.formatDate(date, "GMT+9", "M/dd");
}
return data;
}
JS
google.charts.load('current', {'packages':['corechart','controls']});
google.charts.setOnLoadCallback(getSpreadsheetData);
function getSpreadsheetData() {
google.script.run.withSuccessHandler(drawChart).getSpreadsheetData();
}
function drawChart(rows) {
var data = google.visualization.arrayToDataTable(rows, false);
var columnsTable = new google.visualization.DataTable();
columnsTable.addColumn('number', 'colIndex'); // numbrer to date then error
columnsTable.addColumn('string', 'colLabel');
var initState= {selectedValues: []}
for (var i = 1; i < data.getNumberOfColumns(); i++) {
columnsTable.addRow([i, data.getColumnLabel(i)]);
}
var chart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart_div',
dataTable: data,
options: {
explorer: { axis: 'horizontal' },
pointSize: 3,
vAxis : { format: '#.#',
viewWindow:{
max:0.6,
min:0
},
},
hAxis: {format: 'M/dd'},
legend: 'none',
chartArea: {width: '90%'},
crosshair: { trigger: 'both', orientation: 'both' },
trendlines: {
0: {
type: 'polynomial',
lineWidth: 5,
color: 'orange',
labelInLegend: 'Trend',
degree: 5,
visibleInLegend: true,
},
}
}
});
var columnFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'colFilter_div',
dataTable: columnsTable,
options: {
filterColumnLabel: 'colLabel',
filterColumnIndex: 1,
useFormattedValue: true,
ui: {
allowTyping: false,
allowMultiple: false, // when true then filters stacked
caption : 'Choose your values',
allowNone: true,
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);
});
if (state.selectedValues.length > 0) {
chart.setView(view);
} else {
chart.setView(null);
}
chart.draw();
}
google.visualization.events.addListener(columnFilter, 'statechange', setChartView);
setChartView();
columnFilter.draw();
}
you could use a data view, to convert the date string to an actual date.
here, create the data table as normal.
then create the data view, using a calculated column for the date column.
assuming the first data table column is the date string
function drawChart(rows) {
// create data table
var data = google.visualization.arrayToDataTable(rows, false);
// create data view
data = new google.visualization.DataView(data);
// create view columns with calculated column
var viewColumns = [{
calc: function (dt, row) {
return new Date(dt.getValue(row, 0));
},
label: data.getColumnLabel(0),
type: 'date'
}];
// add remaining columns
for (var = 1; i < data.getNumberOfColumns(); i++) {
viewColumns.push(i);
}
// set view columns
data.setColumns(viewColumns);
...
I can define each category picker using a for loop. However, each picker variable ends up hard coded for the Google API to work:
var categoryPickerArray = [];
for (var i = 0; i < categoryPickers.length; i++) {
categoryPickerArray.push(
new google.visualization.ControlWrapper(categoryPicker_default(categoryPickers[i])),
);
//eval(`var categoryPicker${i} = categoryPickerArray[i];`);//works but uses eval
}
var categoryPicker0 = categoryPickerArray[0];
var categoryPicker1 = categoryPickerArray[1];
I can of use eval() but would prefer not to for all the security concerns.
My goal is to define the picker variables dynamically based on what I've pushed into categoryPickerArray. I'm trying to avoid the need for hard coding each var categoryPicker0 = categoryPickerArray[0] #1, #2, etc.
Hoping someone has an idea about how this can be accomplished. Thanks as always!
Here is my working code:
// Load the Visualization API and the corechart package.
google.charts.load('current', {
'packages': ['corechart', 'table', 'gauge', 'controls']
});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(gChart0);
function gChart0() {
drawChart();
}
function drawChart() {
var result = [{
"calendarWeek": "2017-W30",
"partId": '1234567890xxx',
"someNumber": 0
}, {
"calendarWeek": "2017-W30",
"partId": '1234567890yyy',
"someNumber": 0
}, {
"calendarWeek": "2017-W30",
"partId": '1234567890111',
"someNumber": 0
}];
//Create DataTable
var data = new google.visualization.DataTable();
data.addColumn('string', 'Calendar Week');
data.addColumn('string', 'Part Id');
data.addColumn('number', 'Some Number');
var dataArray = [];
$.each(result, function(i, obj) {
dataArray.push([
obj.calendarWeek,
obj.partId,
obj.someNumber
]);
});
data.addRows(dataArray);
//Options
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));
const categoryPicker_default = (categoryPicker) => {
var id = categoryPicker.id;
var controlType = categoryPicker.controlType;
var filterColumnIndex = categoryPicker.filterColumnIndex;
const picker_options = `
{
"controlType": "${controlType}",
"containerId": "categoryPicker${id}",
"options": {
"filterColumnIndex": ${filterColumnIndex},
"matchType": "any",
"ui":{
"labelStacking": "vertical",
"allowTyping": false,
"allowMultiple": false,
"allowNone": true
}
}
}
`;
return JSON.parse(picker_options);
};
const categoryPickers = [{
"id": 0,
"controlType": "StringFilter",
"filterColumnIndex": 0
},
{
"id": 1,
"controlType": "StringFilter",
"filterColumnIndex": 1
}
];
var categoryPickerArray = [];
for (var i = 0; i < categoryPickers.length; i++) {
categoryPickerArray.push(
new google.visualization.ControlWrapper(categoryPicker_default(categoryPickers[i])),
);
//eval(`var categoryPicker${i} = categoryPickerArray[i];`);//works but uses eval
}
// Commented out per suggestion from WhiteHat - See bind below
//var categoryPicker0 = categoryPickerArray[0];
//var categoryPicker1 = categoryPickerArray[1];
var table = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'table',
options: {
width: '100%',
height: 'auto',
page: 'enable',
pageSize: '15',
sort: 'enable',
allowHtml: true
}
});
// Picker reset
google.visualization.events.addOneTimeListener(dashboard, 'ready', function() {
var reset = document.getElementById('categoryPicker_resetBtn');
reset.addEventListener('click', function() {
for (var i = 0; i < categoryPickerArray.length; ++i) {
categoryPickerArray[i].setState({
selectedValues: []
});
categoryPickerArray[i].draw();
}
});
});
//dashboard.bind([categoryPicker0, categoryPicker1], [table]); //Old call using hard coded values
dashboard.bind(categoryPickerArray, [table]);//New call using array
dashboard.draw(data);
} //END function drawChart()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard"></div>
<div id="categoryPicker0"></div>
<div id="categoryPicker1"></div><br>
<button id="categoryPicker_resetBtn">Reset</button>
<div id="table"></div>
UPDATE:
Made changes in snippet per suggestion from Mr. WhiteHat to use categoryPickerArray in place of hard coded values in the dashboard binding.
dashboard.bind(categoryPickerArray, [table]);
if you're hard coding for the bind method,
you can simply pass the array of pickers directly...
dashboard.bind(categoryPickerArray, [table]);
I'm having trouble displaying google sheets info on the dashboard. The x and y-axis labels show up like Generalxxx . The data is from here .
var laptimeChart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart_div',
'width': '500',
'height': '500',
'view': { 'columns': [1,2] }
});
the chart seems to be using the "General" format by default
to correct, set a specific format for each axis...
options: {
hAxis: {
format: '0'
},
vAxis: {
format: '#,##0'
}
},
see following working snippet...
google.charts.load('current', {
packages: ['controls', 'corechart', 'table']
}).then(function () {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1PlT8k6qXsCkOCEEJFn7apKYgDunLi1Lzmnmo_AKQBXc/edit#gid=0');
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {
console.log('Error: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var control = new google.visualization.ControlWrapper({
controlType: 'NumberRangeFilter',
containerId: 'control',
options: {
filterColumnIndex: 1,
ui: {
format: {
pattern: '0'
}
}
}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart',
options: {
hAxis: {
format: '0'
},
vAxis: {
format: '#,##0'
}
},
view: {
columns: [1, 2]
}
});
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));
dashboard.bind(control, chart);
dashboard.draw(data);
}
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard">
<div id="control"></div>
<div id="chart"></div>
</div>
I am fairly new to Google Charts and was trying to create a bar chart with % of total, along with the ability to filter the data by using Google Dashboard Controls... I followed this (thanks to #asgallant for this!) google.visualization.ChartWrapper Group Columns View and was able to get a bar chart which picks up data from a google sheet, and draws the chart with counts and also have the ability to filter the data using Google Category filters.
However, this is where I am stuck - when I try to add another columns (dataview) for calculating the total (so that I can draw the chart using the percentage and also show the percentage in the bar labels) - my chart is still drawing using the counts.. Can anyone please let me know what am I going wrong here:
function drawVisualization() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {return; }
var data = response.getDataTable();
// Define category pickers for All Filters
var CardTier = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control1',
'options': {
'filterColumnLabel': 'CardTier Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
var Campaign = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Campaign Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
// Define a bar chart to show 'Population' data
var barChart = new google.visualization.ChartWrapper({
'chartType': 'BarChart',
'containerId': 'chart1',
'options': {
'width': 400,
'height': 300,
'chartArea': {top: 0, right: 0, bottom: 0}
},
// Configure the barchart to use columns 0 (Card Tier) and 1 (Campaign Filter) (Basically the filters)
'view': {'columns': [0, 1]}
});
var proxyTable = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'proxyTable',
options: {
// minimize the footprint of the table in HTML
page: 'enable',
pageSize: 1
},
view: {
columns: [0]
}
});
// create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
// Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
google.visualization.events.addListener(proxyTable, 'ready', function () {
var dt = proxyTable.getDataTable();
var groupedData = google.visualization.data.group(dt, [2], [{
column: 3,
type: 'number',
label: dt.getColumnLabel(2),
aggregation: google.visualization.data.count
}]);
var view = new google.visualization.DataView(groupedData);
view.setColumns([0, 1, {
calc: function (dt, row) {
var amount = formatShort.formatValue(dt.getValue(row, 1));
var percent = formatPercent.formatValue(dt.getValue(row, 1) / groupedData.getValue(0, 1));
return amount + ' (' + percent + ')';
},
type: 'string',
role: 'annotation'
}]);
// after grouping, the data will be sorted by column 0, then 1, then 2
// if you want a different order, you have to re-sort
barChart.setDataTable(view);
barChart.draw();
});
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure the controls :
bind(CardTier, Campaign).
bind(Campaign, proxyTable).
// Draw the dashboard
draw(data);
}
}
google.load('visualization', '1', {packages:['corechart', 'controls', 'table'], callback: drawVisualization});
</script>
</head>
<body>
<div id="dashboard">
<table>
<tr style='vertical-align: top'>
<td style='width: 300px; font-size: 0.9em;'>
<div id="control1"></div>
<div id="control2"></div>
</td>
<td style='width: 600px'>
<div style="float: left;" id="chart1"></div>
<div style="float: left;" id="chart2"></div>
</td>
</tr>
</table>
<div id="proxyTable" style="display: none;"></div>
</div>
</body>
</html>
for starters, recommend using the newer library loader.js
<script src="https://www.gstatic.com/charts/loader.js"></script>
instead of jsapi, 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.
this will only change the load statement, see following working snippet...
next, didn't see the definitions for the number formatters
formatShort and formatPercent
need to add those
groupedData will give you the total for each status
to get the the total for all the rows,
need to use the modifier function
this will change the value to 'Total' for the first column of all rows
allowing the group method to aggregate all rows
var totalData = google.visualization.data.group(
dataTable,
[{column: 0, type: 'string', modifier: function () {return 'Total';}}],
[{
column: 3,
type: 'number',
label: dataTable.getColumnLabel(2),
aggregation: google.visualization.data.count
}]
);
finally, remove the view option from barChart
since we're providing the view we want drawn
see following working snippet...
google.charts.load('current', {
callback: drawVisualization,
packages: ['corechart', 'controls', 'table']
});
function drawVisualization() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {return; }
var data = response.getDataTable();
// Define category pickers for All Filters
var CardTier = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control1',
'options': {
'filterColumnLabel': 'CardTier Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
var Campaign = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Campaign Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
// Define a bar chart to show 'Population' data
var barChart = new google.visualization.ChartWrapper({
'chartType': 'BarChart',
'containerId': 'chart1',
'options': {
'width': 400,
'height': 300,
'chartArea': {top: 0, right: 0, bottom: 0}
}
});
var proxyTable = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'proxyTable',
options: {
// minimize the footprint of the table in HTML
page: 'enable',
pageSize: 1
},
view: {
columns: [0]
}
});
// create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
// Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
google.visualization.events.addListener(proxyTable, 'ready', function () {
var formatShort = new google.visualization.NumberFormat({
pattern: 'short'
});
var formatPercent = new google.visualization.NumberFormat({
pattern: '0.0%'
});
var dataTable = proxyTable.getDataTable();
// group by status
var groupedData = google.visualization.data.group(
dataTable,
[2],
[{
column: 3,
type: 'number',
label: dataTable.getColumnLabel(2),
aggregation: google.visualization.data.count
}]
);
// status total
var totalData = google.visualization.data.group(
dataTable,
[{column: 0, type: 'string', modifier: function () {return 'Total';}}],
[{
column: 3,
type: 'number',
label: dataTable.getColumnLabel(2),
aggregation: google.visualization.data.count
}]
);
var view = new google.visualization.DataView(groupedData);
view.setColumns([0, 1, {
calc: function (dt, row) {
var amount = dt.getValue(row, 1);
var total = totalData.getValue(0, 1);
var percent = 0;
if (total > 0) {
percent = amount / total;
}
return formatShort.formatValue(amount) + ' (' + formatPercent.formatValue(percent) + ')';
},
type: 'string',
role: 'annotation'
}]);
// after grouping, the data will be sorted by column 0, then 1, then 2
// if you want a different order, you have to re-sort
barChart.setDataTable(view);
barChart.draw();
});
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure the controls :
bind(CardTier, Campaign).
bind(Campaign, proxyTable).
// Draw the dashboard
draw(data);
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control1"></div>
<div id="control2"></div>
<div id="chart1"></div>
<div id="proxyTable"></div>
UPDATE
to draw the percentages instead of counts,
just need to add another calculated column to the view
as for showing zero values,
use the original data table to get a distinct list of status values
check if the status exists in groupedData
if not, add a row for the status
// add back missing status
var statusValues = data.getDistinctValues(2);
statusValues.forEach(function (status) {
var statusRow = groupedData.getFilteredRows([{
column: 0,
value: status
}]);
if (statusRow.length === 0) {
groupedData.addRow([
status,
0
]);
}
});
groupedData.sort([{column: 0}]);
see following working snippet...
google.charts.load('current', {
callback: drawVisualization,
packages: ['corechart', 'controls', 'table']
});
function drawVisualization() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {return; }
var data = response.getDataTable();
// Define category pickers for All Filters
var CardTier = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control1',
'options': {
'filterColumnLabel': 'CardTier Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
var Campaign = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Campaign Filter',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
// Define a bar chart to show 'Population' data
var barChart = new google.visualization.ChartWrapper({
'chartType': 'BarChart',
'containerId': 'chart1',
'options': {
'width': 400,
'height': 300,
'chartArea': {top: 0, right: 0, bottom: 0}
}
});
var proxyTable = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'proxyTable',
options: {
// minimize the footprint of the table in HTML
page: 'enable',
pageSize: 1
},
view: {
columns: [0]
}
});
// create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
// Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
google.visualization.events.addListener(proxyTable, 'ready', function () {
var formatShort = new google.visualization.NumberFormat({
pattern: 'short'
});
var formatPercent = new google.visualization.NumberFormat({
pattern: '0.0%'
});
var dataTable = proxyTable.getDataTable();
// group by status
var groupedData = google.visualization.data.group(
dataTable,
[2],
[{
column: 3,
type: 'number',
label: dataTable.getColumnLabel(2),
aggregation: google.visualization.data.count
}]
);
// add back missing status
var statusValues = data.getDistinctValues(2);
statusValues.forEach(function (status) {
var statusRow = groupedData.getFilteredRows([{
column: 0,
value: status
}]);
if (statusRow.length === 0) {
groupedData.addRow([
status,
0
]);
}
});
groupedData.sort([{column: 0}]);
// status total
var totalData = google.visualization.data.group(
dataTable,
[{column: 0, type: 'string', modifier: function () {return 'Total';}}],
[{
column: 3,
type: 'number',
label: dataTable.getColumnLabel(2),
aggregation: google.visualization.data.count
}]
);
var view = new google.visualization.DataView(groupedData);
view.setColumns([0, {
calc: function (dt, row) {
var amount = dt.getValue(row, 1);
var total = totalData.getValue(0, 1);
var percent = 0;
if (total > 0) {
percent = amount / total;
}
return {
v: percent,
f: formatPercent.formatValue(percent)
};
},
type: 'number',
label: 'Percent'
}, {
calc: function (dt, row) {
var amount = dt.getValue(row, 1);
var total = totalData.getValue(0, 1);
var percent = 0;
if (total > 0) {
percent = amount / total;
}
return formatPercent.formatValue(percent) + ' (' + formatShort.formatValue(amount) + ')';
},
type: 'string',
role: 'annotation'
}]);
// after grouping, the data will be sorted by column 0, then 1, then 2
// if you want a different order, you have to re-sort
barChart.setDataTable(view);
barChart.draw();
});
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure the controls :
bind(CardTier, Campaign).
bind(Campaign, proxyTable).
// Draw the dashboard
draw(data);
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control1"></div>
<div id="control2"></div>
<div id="chart1"></div>
<div id="proxyTable"></div>
UPDATE 2
to find the total of a multiple choice question,
create a view with a calculated column
the new column should test that all question columns are not blank
then total the view on the calculated column
see following working snippet...
google.charts.load('current', {
callback: drawVisualization,
packages: ['corechart', 'controls', 'table']
});
function drawVisualization() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/19VWNZkHG5GEuYCibDmtOlKblKiOWcx94Wi9jyuhvEUo/edit#gid=0');
query.setQuery('select A,B,C,D,E,F,G');
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {return;}
var data = response.getDataTable();
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, 2, 3, 4, 5, 6, {
calc: function (dt, row) {
var answered = 0;
var q1_1 = dt.getValue(row, 3) || '';
var q1_2 = dt.getValue(row, 4) || '';
var q1_3 = dt.getValue(row, 5) || '';
var q1_4 = dt.getValue(row, 6) || '';
if ((q1_1 !== '') || (q1_2 !== '') || (q1_3 !== '') || (q1_4 !== '')) {
answered = 1;
}
return answered;
},
label: 'Answered',
type: 'number'
}]);
var totalAnswered = google.visualization.data.group(
view,
[{column: 0, type: 'string', modifier: function () {return 'Total';}}],
[{
column: view.getNumberOfColumns() - 1,
type: 'number',
label: view.getColumnLabel(view.getNumberOfColumns() - 1),
aggregation: google.visualization.data.sum
}]
);
var proxyTable = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'proxyTable',
dataTable: view
});
proxyTable.draw();
document.getElementById('proxyTableTotal').innerHTML = 'Total Answered = ' + totalAnswered.getValue(0, 1);
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="proxyTable"></div>
<div id="proxyTableTotal"></div>
Before today all work fine with this code:
var slider;
var ajdi = '';
function drawVisualization() {
var cssClassNames = {
'headerRow': 'zaglavlje',
'tableRow': 'red',
'oddTableRow': 'red1',
'selectedTableRow': 'orange-background large-font',
'hoverTableRow': 'prekoreda',
'headerCell': 'gold-border',
'tableCell': 'cell',
'rowNumberCell': 'underline-blue-font'
};
var json = $.ajax({
url: 'getzadaci.php', // make this url point to the data file
dataType: 'json',
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(json);
//dodajemo kolonu sa kontrolama
//dodajemo kolonu sa kontrolama
data.addColumn('string', '');
for (var y = 0, maxrows = data.getNumberOfRows(); y < maxrows; y++) {
if (data.getValue(y, 11) != 'a') {
data.setValue(y, 11, '<div style="text-align:right;"><a data-toggle="modal" data-target="#update" href="#" class="btn btn-info openRes"><i class="fa fa-edit"></i> Details</a> <a id="hm" data-toggle="modal" data-target="#troskovnik" href="#" class="btn btn-danger"><i class="fa fa-flask"></i> Troskovnik</a> <i data-toggle="modal" data-target="#delete" href="#" class="fa fa-trash-o"></i></div>');
}
}
data.addColumn('string', '');
for (var y = 0, maxrows = data.getNumberOfRows(); y < maxrows; y++) {
if (data.getValue(y, 3) === 'U toku') {
data.setValue(y, 12, '<span class="bg-warning" style="display: inline-block;">U toku</span>');
}
else if (data.getValue(y, 3) === 'U planu') {
data.setValue(y, 12, '<span class="bg-danger" style="display: inline-block;">U planu</span></span>');
}
else {
data.setValue(y, 12, '<span class="bg-success" style="display: inline-block;">Zavrseno</span>');
}
}
// Define a category picker control for the Gender column
var categoryPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control1',
'options': {
'filterColumnLabel': 'Status',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': true,
'caption': 'Status'
}
}
});
var categoryPicker1 = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnIndex': 8,
'ui': {
'labelStacking': 'horizontal',
'allowTyping': false,
'allowMultiple': true,
'caption': 'Parcela'
}
}
});
var categoryPicker2 = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control4',
'options': {
'filterColumnIndex': 2,
'ui': {
'labelStacking': 'horizontal',
'allowTyping': false,
'allowMultiple': true,
'caption': 'Vrsta zadatka'
}
}
});
var stringFilter1 = new google.visualization.ControlWrapper({
'controlType': 'StringFilter',
'containerId': 'control3',
'options': {
'matchType': 'any',
'filterColumnIndex': 1,
'ui': {'labelStacking': 'vertical'}
}
});
var slider = new google.visualization.ControlWrapper({
'controlType': 'DateRangeFilter',
'containerId': 'control5',
'options': {
'filterColumnLabel': 'Pocetak',
'ui': {'labelStacking': 'vertical'}
}
});
// Define a Pie chart
// Define a table
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'chart2',
'cssClassNames': 'cssClassNames',
'view': { 'columns': [1,2,12,5,6,8,11] },
'options': {
cssClassNames: cssClassNames,
allowHtml: true
}
});
var timeline = new google.visualization.ChartWrapper({
chartType: 'Timeline',
containerId: 'chart5',
options: {
height: '350',
timeline: { colorByRowLabel: true },
//timeline.barLabelStyle: {color: '#000', fontName: 'Arial', fontSize: '13px'},
backgroundColor: '#fff',
colors: ['#55c2a2', '#89d168', '#d3eb87','#8ec63e', '#FFF0BA','#FF542E', '#CFD6DE', '#ADC1D6', '#7297BA']
//timeline: { rowLabelStyle: {fontName: 'Helvetica', fontSize: 24, color: '#603913' },
// barLabelStyle: { fontName: 'Garamond', fontSize: 14 } }
},
view: {
// as an example, use columns "Naziv", "Vrsta", "Pocetak", and "Zavrsetak" for the timeline
columns: [8, 2, 5, 6]
},
});
var formatter_short = new google.visualization.DateFormat({formatType: 'short'});
formatter_short.format(data, 5);
formatter_short.format(data, 6);
new google.visualization.events.addListener(table, 'ready', function () {
google.visualization.events.addListener(table.getChart(), 'select', function () {
var selection = table.getChart().getSelection();
// iterate over all selected rows
for (var i = 0; i < selection.length; i++) {
//$("#edit").removeClass("edit btn btn-success")
//$('#edit').addClass('edit btn btn-success');
ajdi = table.getDataTable().getValue(selection[i].row,0);
openResource();
$("#vrednostid").val(table.getDataTable().getValue(selection[i].row,0));
$("#naziv1").val(table.getDataTable().getValue(selection[i].row,1));
$("#vrsta_rada1").val(table.getDataTable().getValue(selection[i].row,2));
$("#status1").val(table.getDataTable().getValue(selection[i].row,3));
$("#opis1").val(table.getDataTable().getValue(selection[i].row,4));
$("#usluzno1").val(table.getDataTable().getValue(selection[i].row,9));
var p = new Date(table.getDataTable().getValue(selection[i].row,5));
$("#dp31").datepicker("setDate", p);
var z = new Date(table.getDataTable().getValue(selection[i].row,6));
$("#dp41").datepicker("setDate", z);
//$("#parcele1").val(table.getDataTable().getValue(selection[i].row,8));
//$("#parcele1").select2("val", ["3","19"]);
var id = table.getDataTable().getValue(selection[i].row,10);
var naziv = table.getDataTable().getValue(selection[i].row,8);
var idArr = (id.lastIndexOf(',') == (id.length - 1) ? id.substr(0, id.length - 1) : id).split(', ');
var nazivArr = (naziv.lastIndexOf(',') == (naziv.length - 1) ? naziv.substr(0, naziv.length - 1) : naziv).split(', ');
var objHold = [];
for(var j=0,length=idArr.length;j<length;j++)
{
if(idArr[j] && nazivArr[j]) // make sure both arrays have a value
objHold.push({id: idArr[j], naziv: nazivArr[j]});
}
$("#parcele1").select2("data", objHold);
}
});
});
// Create a dashboard
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Establish bindings, declaring the both the slider and the category
// picker will drive both charts.
bind([categoryPicker, categoryPicker1, categoryPicker2, slider, stringFilter1], [table, timeline]).
// Draw the entire dashboard.
draw(data, {'allowHtml':true, 'cssClassNames': 'cssClassNames'});
//table.draw(data, {'allowHtml':true, 'cssClassNames': cssClassNames});
}
function dashboardReady() {
// The dashboard is ready to accept interaction. Configure the buttons to
// programmatically affect the dashboard when clicked.
// Change the slider selected range when clicked.
document.getElementById('rangeButton').onclick = function() {
slider.setState({'lowValue': 2, 'highValue': 5});
slider.draw();
};
// Change the pie chart rendering options when clicked.
document.getElementById('optionsButton').onclick = function() {
piechart.setOption('is3D', true);
piechart.draw();
};
}
google.setOnLoadCallback(drawVisualization);// JavaScript Document
but today I just get this error: You called the draw() method with the wrong type of data rather than a DataTable or DataView×
Why? I'm so nervous ith google viz api...
Is there any change to make it workable? Is there any option to disable google visualisation error for dashboard, becouse when I dont have data Google show me an error
UPDATE:
I had the same problem on chrome v. 35 after the recent charts update.
Cleared my browsing history (shift + ctl + del) and it fixed the problem.
Must have been something to do with a cookie from the previous version of the google charts.