I want to show some dashboard charts (like these ones), for example one PieChart and one BarChart.
The issue I have found is that these charts aren't displayed unless, I right click on Inspect element. And viceversa, if I have the inspect element tools already open, the charts aren't display either until I close the inspect elements tools.
I am using bootstrap, slim framework and eloquent orm.
In the case of the pieChart, the sample data displayed is the following:
[
{
Area: "Actores y Procesos Sociales",
Cantidad: 49
},
{
Area: "Población y Estudios Demográficos",
Cantidad: 41
},
{
Area: "Estudios Agrarios",
Cantidad: 40
},
{
Area: "Instituciones Políticas",
Cantidad: 35
},
{
Area: "Sociedad y Cultura",
Cantidad: 30
},
{
Area: "Estudios Urbanos y Regionales",
Cantidad: 26
},
{
Area: "Estudios de la Educación y la Ciencia",
Cantidad: 23
}
]
Here is the code for both the PieChart and the BarChart:
In the html:
<head>
<link href="http://132.248.234.17/sica15/public/assets/css/bootstrap-3.3.6-dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/metisMenu/dist/metisMenu.min.css" rel="stylesheet">
<link href="/assets/css/font-awesome-4.6.0/css/font-awesome.min.css" rel="stylesheet">
<link href="/assets/css/sbadmin2-sidebar-toggle.css" rel="stylesheet" />
</head>
<body>
<div id="page-wrapper">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
<div id="projectresearcher">
<div id="numberRangeFilter_control_div"></div> <div id="numberRangeFilter_chart_div"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
<div id="institucionesPporproyecto_div">
<div id="numberRangeFilter_control_div_2"></div> <div id="numberRangeFilter_chart_div_2"></div>
</div>
</div>
</div>
</div>
</div>
In the script:
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="http:/assets/js/bootstrap-hover-dropdown/bootstrap-hover-dropdown.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart','table','controls'],'language': 'es'});
google.charts.setOnLoadCallback(proyectosporarea);
google.charts.setOnLoadCallback(institucionesPporproyecto);
function proyectosporarea() {/*PROYECTOS POR ÁREA*/
var data = new google.visualization.DataTable();
var proyectosporarea = {{proyectosporarea|json_encode|raw}};
var totalproyectos = 0;
data.addColumn('string', 'Área');
data.addColumn('number', 'Cantidad');
$.each(proyectosporarea, function(index, value){
var Cantidad = parseInt(value.Cantidad);
totalproyectos += Cantidad;
data.addRow([value.Area,Cantidad]);
});
var dashboard = new google.visualization.Dashboard(document.getElementById('projectarea'));//var chart = new google.visualization.PieChart(document.getElementById('projectarea'));
// Create a range slider, passing some options
var donutRangeSlider = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'numberRangeFilter_control_div',
'options': {
'filterColumnLabel': 'Cantidad'
}
});
// Create a pie chart, passing some options
var pieChart = new google.visualization.ChartWrapper({
'chartType': 'PieChart',
'containerId': 'numberRangeFilter_chart_div',
'options': {
title: 'Número de proyectos vigentes por área de investigación (total: '+totalproyectos+')',
backgroundColor: { fill:'transparent'},
height: 500,
}
});
dashboard.bind(donutRangeSlider, pieChart);
function resizeHandler () {
dashboard.draw(data);//chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de drawChart() Proyectos por área*/
function institucionesPporproyecto() {/*INSTITUCIONES POR NÚMERO DE PROYECTOS*/
var data = new google.visualization.DataTable();
var proyectosporarea = {{institucionesPporproyecto|json_encode|raw}};
var total = 0;
var totalInvestigadores = 0;
data.addColumn('string', 'Institución');
data.addColumn('number', 'Cantidad');
data.addColumn({type: 'string', role: 'annotation'});
//Sumando los totales para después calcular el porcentaje
$.each(proyectosporarea, function(indice,valor){
var Cantidad = parseInt(valor.Cantidad);
var Total = parseInt(Cantidad);
total += Total;
});
$.each(proyectosporarea, function(index, value){
var Cantidad = parseInt(value.Cantidad);
var Porcentaje = ((Cantidad/total)*100);
if(Porcentaje % 1 != 0){
Porcentaje = Porcentaje.toFixed(0)+'%';
}else{
Porcentaje = Porcentaje + '%';
}
totalInvestigadores=totalInvestigadores+1;
data.addRow([value.Institucion,Cantidad,Porcentaje]);
});
var view = new google.visualization.DataView(data); view.setColumns([0, 1]);
var table = new google.visualization.Table(document.getElementById('institucionesPporproyecto_t'));
table.draw(view, {width: '100%', height: '100%'});
var dashboard2 = new google.visualization.Dashboard(document.getElementById('institucionesPporproyecto_div'));/*Cambie chart por dashboard*/
var control2 = new google.visualization.ControlWrapper({
'controlType':'NumberRangeFilter',
'containerId':'numberRangeFilter_control_div_2',
'options':{
'filterColumnIndex':1,
'minValue':0,
//'maxValue':60,
}
});
var chart = new google.visualization.ChartWrapper({
'chartType':'BarChart',
'containerId':'numberRangeFilter_chart_div_2',
'options':{
title: 'Número de proyectos por institución participante (Total de Instituciones: '+totalInvestigadores+').',
chartArea: {width: '45%'},
hAxis: {
title: 'Cantidad de proyectos',
minValue: 0
},
vAxis: {
title: 'Instituciones'
},
height: 1400,
//width: 1200,
}
});
dashboard2.draw(view);//chart.draw(view);
google.visualization.events.addListener(table, 'sort',
function(event) {
data.sort([{column: event.column, desc: !event.ascending}]);
dashboard2.draw(view);//chart.draw(view);
});
//chart.draw(data, options); Aquí ando
dashboard2.bind(control2,chart);
function resizeHandler () {
dashboard2.draw(data);//chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de drawChart() Tabla Instituciones por número de proyectos*/
</script>
Why is this happening? What should I fix so that those charts are displayed just after opening the URI in the browser?
Solved
The problem was in this part where there is this function resizeHandler():
I had:
dashboard2.bind(control2,chart);
/*http://stackoverflow.com/a/18984903/1883256*/
function resizeHandler () { /*This helps make the chart responsive*/
dashboard2.draw(data);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
Instead of:
dashboard2.bind(control2,chart);
dashboard2.draw(data);
/*http://stackoverflow.com/a/18984903/1883256*/
function resizeHandler () {/*This helps make the chart responsive*/
dashboard2.draw(data);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
So, I had to repeat the call of the dashboard.draw(data); both inside the function resizeHandler() and outside it, below the dashboard.bind() function.
first, setOnLoadCallback should only be called once per page load
and you can include the 'callback' in google.charts.load
try replacing this...
google.charts.load('current', {'packages':['corechart','table','controls'],'language': 'es'});
google.charts.setOnLoadCallback(proyectosporarea);
google.charts.setOnLoadCallback(institucionesPporproyecto);
with this...
google.charts.load('current', {
'callback': function () {
proyectosporarea();
institucionesPporproyecto();
},
'packages': ['corechart','table','controls'],
'language': 'es'
});
next, each wrapper object needs a dom element
in function proyectosporarea, the objects appear to have the wrong containerId
see comments in the following snippet...
var donutRangeSlider = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'filter_div', //<-- should = numberRangeFilter_control_div
'options': {
'filterColumnLabel': 'Cantidad'
}
});
// Create a pie chart, passing some options
var pieChart = new google.visualization.ChartWrapper({
'chartType': 'PieChart',
'containerId': 'chart_div', //<-- should = numberRangeFilter_chart_div
'options': {
title: 'Número de proyectos vigentes por área de investigación (total: '+totalproyectos+')',
backgroundColor: { fill:'transparent'},
height: 500,
}
});
Related
I am using a google timeline similar to the code snippet below. I want my chart to look like the one below. I have managed to get everything to work expect how to add the dashed lines and text notation. Unfortunately, when I am searching for annotations I keep getting the AnnotatedTimeline, which is a different google chart.
Is there a simple way to do this?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'President' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson', new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable);
}
</script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
</body>
</html>
I was able to get this to work by finding the position of the rects. I started by drawing divs for each line I would want to show. Then after the timeline is draw I repositions those divs based on the location of the rectangle. I was not able to get a good minimal working snippet here because of the window positions used in the snippet code, but I got pretty close. In my own code I have it working perfectly.
.hline {
border-left: 5px solid black;
height: 100px;
position:absolute;
visibility:hidden;
top:144px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
<div id = "Hline1" class= "hline" > <div style = "position: relative; top:-18px">HLine1</div>
<div id = "Hline2" class= "hline" > <div style = "position: relative; top:-18px">HLine2</div>
<div id = "Hline3" class= "hline" > <div style = "position: relative; top:-18px">HLine3</div>
</div>
</body>
<script>
var options = {
timeline: { showRowLabels: false }
};
const lime="#00ff00" //color for average time
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project Stage', });
dataTable.addColumn({ type: 'string', id: 'Bar'});
dataTable.addColumn({ type: 'string', role: 'style'});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington','Washington',lime, new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', 'Adams',lime, new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson','Jefferson',lime, new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable,options);
function redraw (){
var rects = $('rect') //get all rectangles on plot.
function checkColor(arr){
var results = [];
for (let i of arr){
var colorCheck=$(i).attr('fill')
var x =$(i).attr('x')
var width = $(i).attr('width')
var x2 =parseFloat(x)+parseFloat(width)
if(colorCheck == lime){results.push(x2)}
};
return results
};
var linPositions = checkColor(rects) //get x coordinates for vertical lines
var yStart = $('rect')
//console.log(linPositions)
yStart = $(yStart[0]).offset().top;
xMargin=$("#timeline").offset().left;
var yHeight = $('rect')
yHeight = $(yHeight[0]).attr('height');
var lineNames=['Hline1','Hline2','Hline3']
for (let i = 0; i < linPositions.length; i++) {
var position = linPositions[i]+xMargin+"px"
var newTop = i*yHeight + yStart
/* set line information based on current chart positions */
document.getElementById(lineNames[i]).style.left = position;
document.getElementById(lineNames[i]).style.visibility = "visible";
document.getElementById(lineNames[i]).style.top = newTop;
document.getElementById(lineNames[i]).style.height = yHeight;
};
};
redraw()
function resizeChart () {
chart.draw(dataTable, options);
}
if (document.addEventListener) {
window.addEventListener('resize', resizeChart);
window.addEventListener('resize', redraw)
}
else if (document.attachEvent) {
window.attachEvent('onresize', resizeChart);
window.attachEvent('onresize', redraw);
}
else {
window.resize = resizeChart;
window.resize = redraw;
}
}
</script>
</html>
I wanted to create a context menu on my line graph. When the user hovers across a point, they can right click and will see a context menu so that they can trigger more action.
Is this possible with chart.js?
Thanks,
Derek
AFAIK there is no native support for context menu from Chart.js, but you can create it using HTML and handle it.
This is an example:
var timestamp = [],
speed = [10, 100, 20, 30, 40, 100, 40, 60];
for (var k = speed.length; k--; k>0) {
timestamp.push(new Date().getTime()-60*60*1000*k);
}
var canvas = document.getElementById('chart');
var BB = canvas.getBoundingClientRect(),
offsetX = BB.left,
offsetY = BB.top;
var ctx = canvas.getContext("2d");
var data = {
labels: timestamp,
datasets: [{
data: speed,
label: "speed",
backgroundColor: ['rgba(0, 9, 132, 0.2)'],
borderColor: ['rgba(0, 0, 192, 1)'],
borderWidth: 1,
}
]
};
var options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}],
xAxes: [{
type: 'time',
}]
}
};
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: options
});
var $menu = $('#contextMenu');
canvas.addEventListener('contextmenu', handleContextMenu, false);
canvas.addEventListener('mousedown', handleMouseDown, false);
function handleContextMenu(e){
e.preventDefault();
e.stopPropagation();
var x = parseInt(e.clientX-offsetX);
var y = parseInt(e.clientY-offsetY);
$menu.css({left:x,top:y});
$menu.show();
return(false);
}
function handleMouseDown(e){
$menu.hide();
}
menu = function(n){
console.log("select menu "+n);
$menu.hide();
}
#chart {
width: 100%;
height: 100%;
}
#contextMenu{
position:absolute;
border:1px solid red;
background:white;
list-style:none;
padding:3px;
}
.menu-item:hover {
background: #dddddd;
text-decoration: underline;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=canvasContainer>
<canvas id="chart"></canvas>
<ul id="contextMenu" style="display:none;">
<li class="menu-item" onclick="menu(1)">Menu 1</li>
<li class="menu-item" onclick="menu(2)">Menu 2</li>
</ul>
</div>
For anyone looking for this, #beaver's answer does not have access to the clicked item (data point), you can save the state in onHover and use it in contextmenu.
options: {
events: ['click', 'mousemove'],
onHover: function(e, fields){
const lx = e.layerX;
const bars = fields.filter(({_view: {x,width}}) => (x - width/2) <= lx && lx <= (x + width/2));
const data = bars.map(({_index, _datasetIndex}) => this.data.datasets[_datasetIndex].data[_index]);
this.hoveredItem = {bars, data, fields};
},
},
plugins: [
{
afterInit: (chart) =>
{
var menu = document.getElementById("contextMenu");
chart.canvas.addEventListener('contextmenu', handleContextMenu, false);
chart.canvas.addEventListener('mousedown', handleMouseDown, false);
function handleContextMenu(e){
e.preventDefault();
e.stopPropagation();
menu.style.left = e.clientX + "px";
menu.style.top = e.clientY + "px";
menu.style.display = "block";
console.log(chart.hoveredItem);
return(false);
}
function handleMouseDown(e){
menu.style.display = "none";
}
}
}
],
https://codepen.io/elizzk/pen/xxZjQvJ
I am trying to develop a small web app which query the multiple google spreadsheets and make the graphs on the same page. I can query the single spreadsheet and chart the matching data like this and it is working fine.
<html>
<head>
<title>
Test
</title>
<script src="http://www.google.com/jsapi"></script>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load('visualization', '1', {'packages': ['table', 'controls', 'corechart']});
google.setOnLoadCallback(initialize);
function initialize() {
var urlMonth = 'https://docs.google.com/spreadsheets/d/1y5MgFR67kn1-GHbmeIi6wuC5hmP10x4O8vAs5RWD8Sw/edit#gid=0'
var queryStringMonthly = encodeURIComponent("select A, B, C, D, E, F, G, H, I GROUP BY A LABEL A 'Gene' ");
var queryMonthCurrent = new google.visualization.Query(urlMonth+
queryStringMonthly);
queryMonthCurrent.send(megaData);
}
function megaData(monthData) {
var monthData_table = monthData.getDataTable(firstRowIsHeader = true);
var monthData_tablePivot = new google.visualization.DataTable();
monthData_tablePivot.addColumn('string');
monthData_tablePivot.addColumn('number');
monthData_tablePivot.addColumn({type: 'string', label: 'Gene', role: 'annotation'});
var newRows = []; //
//iterate through each row
for (i = 0; i < monthData_table.getNumberOfRows(); i ++) {
var issue = monthData_table.getValue(i, 0);
//iterate through each column
for (j = 1; j < monthData_table.getNumberOfColumns(); j ++ ){
var newRow = [];
rep = monthData_table.getColumnLabel(j);
newRow.push(rep);
newRow.push(monthData_table.getValue(i, j));
newRow.push(issue);
newRows.push(newRow); //push each newRow to newRows
}
}
monthData_tablePivot.addRows( newRows);
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div4'));
// Create filter
var issueFilter = new google.visualization.ControlWrapper({
'controlType': 'StringFilter',
'containerId': 'filter_div4',
'options': {
'filterColumnLabel': 'Gene',
'ui': {
'allowMultiple': false,
'allowNone': false,
}
},
//Set default filter value
'state': {'selectedValues': [monthData_table.getValue(0 , 1)]}
}
);
//create chart
var yearChart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'current_year',
'options': {
'legend': 'none',
'width': 1100,
'height': 500,
hAxis: {
textStyle: {
color: 'black', // any HTML string color ('red', '#cc00cc')
fontName: 'Times New Roman', // i.e. 'Times New Roman'
fontSize: 12, // 12, 18 whatever you want (don't specify px)
bold: true, // true or false
italic: false // true of false
},
'title': 'Gene', titleTextStyle:{color:'black',fontSize: 16,bold:
true,italic: false}
},
vAxis: {title: 'Expression', titleTextStyle:{color:'black',fontSize:
16,bold: true,italic: false},
textStyle: {
color: 'black', // any HTML string color ('red', '#cc00cc')
fontName: 'Times New Roman', // i.e. 'Times New Roman'
fontSize: 12, // 12, 18 whatever you want (don't specify px)
bold: true, // true or false
italic: false // true of false
}
},
//Set the fontsize of labels so they don't show up crazily
'annotations': {'textStyle': {'opacity': 0},
//use 'line' style so to remove the line
pointer
'style': 'point',
'stemLength': 0
},
}
});
// bind charts and controls to dashboard
dashboard.bind(issueFilter, yearChart);
// Draw the dashboard.
dashboard.draw(monthData_tablePivot);
}
</script>
<style>
.SearchBar input {
height: 30px;
width: 400px;
}
</style>
</head>
<body>
<!--Div that will hold the dashboard-->
<center>
<h2>Seach gene expression</h2>
<div id="dashboard_div4" class="SearchBar" placeholder="Search">
<div id="filter_div4" > </div></center>
<div id="current_year" style="width:1100px; height: 300px;">
</div>
</div>
</html>
This repository is very close to my need but I don't know how to query the multiple spreadsheet. My another spreadsheet look like this
https://docs.google.com/spreadsheets/d/1vmPmaL78N-Ywz7s1y_VRSvQAZxjacN4mo7uKKrWrwzE/edit#gid=0
I need to alter value when user select the value from google chart dropdown,
please check the code, I need when user select subject value, then I can alert the message or selected value,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>
Google Visualization API Sample
</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
google.load('visualization', '1.1', {
packages: ['controls']
});
</script>
<script type="text/javascript">
function drawVisualization() {
// Prepare the data
var jsonData = '{"cols":[{"label":"Subject","type":"string"},{"label":"pete","type":"number"},{"label":"john","type":"number"},{"label":"carl","type":"number"},{"label":"andrea","type":"number"}],"rows":[{"c":[{"v":"coolness"},{"v":4.4},{"v":4.3},{"v":3.1},{"v":4.3}]},{"c":[{"v":"sexyness"},{"v":4.2},{"v":3.8},{"v":3.6},{"v":4.8}]},{"c":[{"v":"toughness"},{"v":3.1},{"v":2.7},{"v":2.4},{"v":2.9}]},{"c":[{"v":"chillnes"},{"v":4.4},{"v":4.4},{"v":4.2},{"v":4.5}]},{"c":[{"v":"madness"},{"v":4.6},{"v":4.6},{"v":4},{"v":4.6}]},{"c":[{"v":"lochness"},{"v":3.9},{"v":3.7},{"v":2.9},{"v":3.9}]},{"c":[{"v":"extraness"},{"v":4.6},{"v":4.3},{"v":3.6},{"v":4.3}]}]}';
console.log(typeof(responseText));
console.log(jsonData);
var data = new google.visualization.DataTable(JSON.parse(jsonData));
var compPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Subject',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': true
}
}
});
// Define a chart
var chart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart1',
'options': {
'title': 'Competenties',
'width': '100%',
'height': 300,
'vAxis': {
viewWindow: {
max: 5,
min: 0
},
gridlines: {
color: '#CCC',
count: 6
}
},
bar: {
groupWidth: '80%'
},
colors: ["#FFC000", "#00b0f0", "#ff0000", "#92d050"]
}
});
// Define a table
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'chart2',
'options': {
'width': '400px'
}
});
// Create a dashboard
var drawChart = new google.visualization.Dashboard(document.getElementById('dashboard')).bind([compPicker], [chart, table]);;
drawChart.draw(data);
}
google.setOnLoadCallback(drawVisualization);
</script>
</head>
<body style="font-family: Arial;border: 0 none;">
<div id="dashboard">
<table>
<tr style='vertical-align: top'>
<td>
<div id="control1"></div>
<div id="control2"></div>
<div id="control3"></div>
</td>
</tr>
<tr>
<td>
<div style="float: left;" id="chart1"></div>
<div style="float: left;" id="chart2"></div>
<div style="float: left;" id="chart3"></div>
</td>
</tr>
</table>
</div>
</body>
</html>
JS fiddle link
Please help me.
Thanks
Use the 'statechange' event listener to determine when values are selected...
Then compPicker.getState().selectedValues to get the selected values in an array...
google.charts.load('current', {
callback: drawVisualization,
packages: ['controls', 'corechart', 'table']
});
function drawVisualization() {
var jsonData = '{"cols":[{"label":"Subject","type":"string"},{"label":"pete","type":"number"},{"label":"john","type":"number"},{"label":"carl","type":"number"},{"label":"andrea","type":"number"}],"rows":[{"c":[{"v":"coolness"},{"v":4.4},{"v":4.3},{"v":3.1},{"v":4.3}]},{"c":[{"v":"sexyness"},{"v":4.2},{"v":3.8},{"v":3.6},{"v":4.8}]},{"c":[{"v":"toughness"},{"v":3.1},{"v":2.7},{"v":2.4},{"v":2.9}]},{"c":[{"v":"chillnes"},{"v":4.4},{"v":4.4},{"v":4.2},{"v":4.5}]},{"c":[{"v":"madness"},{"v":4.6},{"v":4.6},{"v":4},{"v":4.6}]},{"c":[{"v":"lochness"},{"v":3.9},{"v":3.7},{"v":2.9},{"v":3.9}]},{"c":[{"v":"extraness"},{"v":4.6},{"v":4.3},{"v":3.6},{"v":4.3}]}]}';
var data = new google.visualization.DataTable(JSON.parse(jsonData));
var compPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Subject',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': true
}
}
});
// listen for 'statechange' event on ControlWrapper
google.visualization.events.addListener(compPicker, 'statechange', function () {
// log selected values array
document.getElementById('message').innerHTML += JSON.stringify(compPicker.getState().selectedValues) + '<br/>';
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart1',
'options': {'title':'Competenties',
'width':'100%',
'height':300,
'vAxis': {
viewWindow: {max:5,min:0},
gridlines: {color:'#CCC', count: 6}
},
bar: { groupWidth: '80%' },
colors: ["#FFC000","#00b0f0","#ff0000","#92d050"]
}
});
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'chart2',
'options': {
'width': '400px'
}
});
var drawChart = new google.visualization.Dashboard(document.getElementById('dashboard'));
drawChart.bind([compPicker], [chart, table]);
drawChart.draw(data);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard">
<table>
<tr style='vertical-align: top'>
<td>
<div id="control1"></div>
<div id="control2"></div>
<div id="control3"></div>
</td>
</tr>
<tr>
<td>
<div style="float: left;" id="chart1"></div>
<div style="float: left;" id="chart2"></div>
<div style="float: left;" id="chart3"></div>
</td>
</tr>
</table>
</div>
<div id="message"></div>
I wanted to enable users to filter the results being displayed on the chart. Google API provides CategoryFilter which enforces filtering by rows. Here is my code which works perfectly fine
<html>
<head>
<!--Load the Ajax API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['controls']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(<?=$jsonTable?>);
var countryPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'negeri',
dataTable: data,
options: {
filterColumnLabel: 'Negeri',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: true
}
},
// Define an initial state, i.e. a set of metrics to be initially selected.
state: {'selectedValues': ['Kedah', 'Johor']}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart_div',
options: {
title: 'Statistik Negeri vs. Kategori Sukan',
width: 1000,
height: 1000,
hAxis: {title: 'Negeri', titleTextStyle: {color: 'blue'}},
vAxis: {title: 'Jumlah Kategori', titleTextStyle: {color: 'blue'}}
}
});
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure the controls so that:
// - the 'Country' selection drives the 'Region' one,
// - the 'Region' selection drives the 'City' one,
// - and finally the 'City' output drives the chart
bind(countryPicker, chart).
// Draw the dashboard
draw(data);
}
</script>
</head>
<body>
<div id="dashboard">
<div id="negeri"></div>
<div id="chart_div"></div>
</div>
</body>
</html>
However in my datatable, I would also want to filter by columns. These two types of filtering should work together. (dependent; by bind() function). I have referred to #asgallant http://jsfiddle.net/asgallant/WaUu2/ and that is the feature that I wanted to combine with.
How can I possibly combine them? I have tried combining setChartView() by #asgallant with google's dashboard() but it's not working.
<html>
<head>
<!--Load the Ajax API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['controls']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(<?=$jsonTable?>);
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 countryPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'negeri',
dataTable: data,
options: {
filterColumnLabel: 'Negeri',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: true
}
},
// Define an initial state, i.e. a set of metrics to be initially selected.
state: {'selectedValues': ['Kedah', 'Johor']}
});
var columnFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'colFilter_div',
dataTable: columnsTable,
options: {
filterColumnLabel: 'colLabel',
ui: {
label: 'Kategori Sukan',
allowTyping: false,
allowMultiple: true,
allowNone: false,
selectedValuesLayout: 'belowStacked'
}
},
state: initState
});
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart_div',
options: {
title: 'Statistik Negeri vs. Kategori Sukan',
width: 1000,
height: 1000,
hAxis: {title: 'Negeri', titleTextStyle: {color: 'blue'}},
vAxis: {title: 'Jumlah Kategori', titleTextStyle: {color: 'blue'}}
}
});
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure the controls so that:
// - the 'Country' selection drives the 'Region' one,
// - the 'Region' selection drives the 'City' one,
// - and finally the 'City' output drives the chart
bind(countryPicker, columnFilter).
bind(columnFilter, chart).
// Draw the dashboard
draw(data);
}
</script>
</head>
<body>
<div id="dashboard">
<div id="negeri"></div>
<div id="chart_div"></div>
</div>
</body>
</html>
You want to bind your countryPicker filter to the chart as normal, but do not bind the columnFilter control to anything - the setChartView function handles everything for the columnFilter. You need to tweak a couple other lines to make it work with a dashboard, but nothing major. This is what it should look like:
function drawChart() {
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(<?=$jsonTable?>);
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 countryPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'negeri',
dataTable: data,
options: {
filterColumnLabel: 'Negeri',
ui: {
labelStacking: 'vertical',
allowTyping: false,
allowMultiple: true
}
},
// Define an initial state, i.e. a set of metrics to be initially selected.
state: {'selectedValues': ['Kedah', 'Johor']}
});
var columnFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'colFilter_div',
dataTable: columnsTable,
options: {
filterColumnLabel: 'colLabel',
ui: {
label: 'Kategori Sukan',
allowTyping: false,
allowMultiple: true,
allowNone: false,
selectedValuesLayout: 'belowStacked'
}
},
state: initState
});
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart_div',
options: {
title: 'Statistik Negeri vs. Kategori Sukan',
width: 1000,
height: 1000,
hAxis: {title: 'Negeri', titleTextStyle: {color: 'blue'}},
vAxis: {title: 'Jumlah Kategori', titleTextStyle: {color: 'blue'}}
}
});
// Create the dashboard.
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard')).
bind(countryPicker, chart);
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);
var runOnce = google.visualization.events.addListener(dashboard, 'ready', function () {
google.visualization.events.removeListener(runOnce);
setChartView();
});
columnFilter.draw();
dashboard.draw(data);
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});