Select event not fired on Google chart API for Sankey - javascript

I'm trying to hook an event to a click on a Google Sankey diagram. The Events claim to include select but it doesn't fire on Chrome or Safari. onmouseover/onmouseout/ready seem to be hooked up if the event is switched in the code below -- I get something in the console log. That is switching the line:
google.visualization.events.addListener(chart, 'select', selectHandler);
to
google.visualization.events.addListener(chart, 'onmouseover', selectHandler);
shows the event listener is connected.
I've tried this on other newer chart types like word-trees and select is connected. What have I missed?
E.g.
<html>
<head>
<script type='text/javascript' src='https://www.google.com/jsapi'</script>
<script type='text/javascript'>
google.load('visualization', '1.1', {packages:['sankey']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'A');
data.addColumn('string', 'B');
data.addColumn('number', 'Mails');
data.addRows([
['from elvis','frank', 285],
['frank', 'to wendy', 61],
]);
var options = {width: 600};
var chart = new google.visualization.Sankey(document.getElementById('thechart'));
google.visualization.events.addListener(chart, 'select', selectHandler);
function selectHandler() {
console.log('You selected ' + JSON.stringify(chart.getSelection()));
};
chart.draw(data, options);
}
</script>
</head>
<body>
<div id='thechart' style='width: 600px; height: 300px;'></div>
</body>
</html>

You have to set correct options:
// Sets chart options.
var options = {
width: 600,
sankey: {
node: {
interactivity: true
}
}
};
I used this example https://jsfiddle.net/5mvx6bdr/
Works perfect :)
sankey: node: interactivity is set to false by default.

I think the issue here is that you are using the getSelection method for the Sankey chart event which returns an object. That object contains the node in the chart that you clicked on but you need to query the object in the right way to extract this information. I don't think it is possible to do things in a single line as attempted in the question above.
This is what worked for me when I had the same problem:
google.visualization.events.addListener(chart, 'select', function(){
var selection = chart.getSelection();
for(var key in selection) {
var value = selection[key];
console.log(value.name);
}
alert('you selected '+value.name);
});

The top answer did not work for me.
However, setting link interactivity to true did the trick.
var options = {
sankey: {
node: {
interactivity: true,
colors: this.colors
},
link: {
interactivity: true
}
}
}

Related

I want to select and highlight country on google Geochart when someone click on a html button or div

I need a country to be selected and highlighted on google Gecochart when a button or Div is clicked.
I was able to achieve that completely if someone clicks on the country on Geochart, but partially if someone clicks the button/div as the Geochart is not highlighting the country until the user moves the mouse pointer above the geochart.
I am trying to implement that using the code below
var chart='';
google.charts.load('current', {
'packages':['geochart'],
});
google.charts.setOnLoadCallback(drawRegionsMap);
function drawRegionsMap() {
var data = google.visualization.arrayToDataTable([
['Country', 'Popularity'],
['Germany', 200],
['United States', 300],
['Brazil', 400],
['Canada', 500],
['France', 600],
['RU', 700]
]);
var options = {};
var container =document.getElementById('regions_div');
chart = new google.visualization.GeoChart(container);
observer = new MutationObserver(function (nodes) {
Array.prototype.forEach.call(nodes, function (node) {
// check for new nodes
if (node.addedNodes.length > 0) {
Array.prototype.forEach.call(node.addedNodes, function (addedNode) {
// the tooltip element will also be here, we only want the group elements
if (addedNode.tagName === 'g') {
// find children of the group element
Array.prototype.forEach.call(addedNode.childNodes, function (childNode) {
// check for path element, change stroke
if (childNode.tagName === 'path') {
childNode.setAttribute('stroke', '#FF0000');
//childNode.setAttribute('fill', '#BE965C');
}
});
}
});
}
});
});
// activate mutation observer
observer.observe(container, {
childList: true,
subtree: true
});
chart.draw(data, options);
}
function myclick() {
//google.visualization.events.trigger(chart, 'select',[{ row: 3, column: null }]);
chart.setSelection([{ row: 3, column: null }]);
console.log( chart.getSelection());
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="regions_div" style="width: 900px; height: 500px;"></div>
<div onclick="myclick()">
text
</div>
<button type="button" onclick="myclick()">Click Me!</button>
I also tried to call google.visualization.events.trigger(chart, 'select', chart.getSelection()); to trigger the selection and highlight directly but it didn't work.
Any idea how to to highlight the country when clicking on the button/div directly (without the need to move the mouse over the Gecochart)?
Thank you!
The code can also be found in this snippet https://jsfiddle.net/nmaybar/8p2zruso/
I have solved the issue by changing the version from 'current' to '49' by adjusting the following code:
google.charts.load('current', { 'packages':['geochart'],});
To:
google.charts.load('49', {'packages':['geochart'],});
I am not sure why it doesn't work with version 'current' or 'upcoming'. I think it is a bug.

Make google chart responsive

Im using google charts in a project but im having a hard time to make them responsive.
Iǘe seen other examples on responsive charts but I cant seem to get it to work in my case.
All my charts gets rendered and after that their sizes do not change.
If someone can make this chart responsive id appreciate it. Thank you:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Year');
data.addColumn('number', 'Revenue');
data.addColumn('number', 'Average Revenue');
data.addRows([
['2004', 1000, 630],
['2005', 1170, 630],
['2006', 660, 630],
['2007', 1030, 630]
]);
var options = {
title: 'Revenue by Year',
seriesType: "bars",
series: {1: {type: "line"}},
vAxis: {title: 'Year',
titleTextStyle:{color: 'red'}},
colors:['red','black']
};
var chart = new google.visualization.ComboChart(document.getElementById('chart'));
chart.draw(data, options);
}
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
Fiddle for the chart:
Fiddle
If it could take up a percentage width of a parent it would be great
The solution was already given online elsewhere.
You need to call your drawChart() function whenever the window is resized to get the desired behaviour. The website flopreynat.com exactly describes this problem and solution (codepen). It describes how this can be done using JQuery:
$(window).resize(function(){
drawChart();
});
Using just Javascript, this answer on Stack Exchange by Sohnee describes how to trigger functions upon a resize event:
window.onresize = doALoadOfStuff;
function doALoadOfStuff() {
//do a load of stuff
}
All credit to both authors of the links above.
Add width_units to your option block:
var options = {
width: 80,
width_units: '%'
}
Or simply use:
var options = {
responsive: true,
}
I created a class chart, and used the window resize event like the accepted answer.
css:
.chart {
width: 100%;
min-height: 500px;
}
js:
$(window).resize(function(){
drawChart();
});
html:
<div id="barchart" class="chart"></div>

Google chart is not taking full width while jquery show and hide

I am making a google chart whith show and hide functionality.Means chart will be hidden on the page load and when user clicks a button chart will be made visible.
My code
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var items = $(".label1").text();
var data = google.visualization.arrayToDataTable([
<%= chartItems %>
]);
var options = {
title: 'Poll Results'
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
<div id="chart_div" style="display:none; width:800px;height:500px;"></div>
My problem is that when user clicks on the button and chart is visible its not taking the full width and height(800x500).rather its taking an unknown dimension(400x200).
Note: when the chart is made visible in the page load itself, It works correctly.
Code is same change in HTML like this
<div id="chart_div" style=" width:800px;height:500px;"></div>
You can do as marios suggested and set dimensions inside that chart's options, but that won't fix all of the problems that come along with drawing a chart inside a hidden div. The Visualization APIs dimensional measurements don't work well inside hidden divs, so elements get positioned in the wrong place and have the wrong size in some browsers. You need to unhide the div immediately prior to drawing the chart, and you can hide it again when the chart is done drawing. Here's example code that does this:
var container = document.getElementById('chart_div');
container.style.display = 'block';
var chart = new google.visualization.PieChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
container.style.display = 'none';
});
chart.draw(data, options);
Use chartArea:{} to set width & height
function drawChart() {
var items = $(".label1").text();
var data = google.visualization.arrayToDataTable([
<%= chartItems %>
]);
var options = {
title: 'Poll Results',
chartArea: {
width: 800,
height: 500
}
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I confirm that this is a bug. It work if the div is hidden "visibility:hidden;"
It does not work if the CSS shows "display:none"
There is an option to ask for specific width and height the google chart api https://developers.google.com/chart/interactive/docs/customizing_charts?hl=es.
Directly give width in chart option.
For eg:
options='{
"width": "800"
}'

Enabling/disabling legend and its corresponding row onclick in Google charts

My requirement is,
After a google chart gets loaded, if I click the legend, the legend should be grayed out and its corresponding value in the graph should be removed.
When I click the grayed out legend, the legend should be highlighted as it was before and the removed value should once again be added to the graph.
I am able to do the 50 % of the first part with the below code:
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
var duplicateChartData = new Array();
var unSelectedArray = new Array();
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
duplicateChartData = new Array();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addRows([
['Mushrooms', 3],
['Onions', 1],
['Olives', 1],
['Zucchini', 1],
['Pepperoni', 2]
]);
// Set chart options
var options = {'title':'How Much Pizza I Ate Last Night',
'width':400,
'height':300};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
duplicateChartData = data;
function selectHandler() {
var selectedItem = chart.getSelection()[0];
var selectedRow = selectedItem.row;
var isUnSelected = unSelectedArray[selectedRow]
if (selectedItem && !isUnSelected) {
data.setValue(selectedRow, 1, 0);
chart.draw(data, options);
unSelectedArray[selectedRow] = true;
}
if(isUnSelected){
data.setValue(selectedRow, 1, duplicateChartData.getValue(selectedRow,1));
unSelectedArray[selectedRow] = false;
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(data, options);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div id="chart_div"></div>
</body>
</html>
I basically setValue as 0 for the selected value and try to reset when clicked again. But whenever a zero is set the legend and data gets deleted. But what I want is thw legend to just gray out. ow to achieve this. Please help me.
I did this for line chart. It satisfies your both requirements. Hope this will help you.
google.visualization.events.addListener(chart, 'select', function () {
var sel = chart.getSelection();
// if selection length is 0, we deselected an element
if (sel.length > 0) {
// if row is undefined, we clicked on the legend
if (typeof sel[0].row === 'undefined') {
var col = sel[0].column;
if (columns[col] == col) {
// hide the data series
columns[col] = {
label: data.getColumnLabel(col),
type: data.getColumnType(col),
calc: function () {
return null;
}
};
// grey out the legend entry
series[col - 1].color = '#CCCCCC';
}
else {
// show the data series
columns[col] = col;
series[col - 1].color = null;
}
var view = new google.visualization.DataView(data);
view.setColumns(columns);
chart.draw(view, options);
}
}
});
Here is the working sample jqfaq.com
Awesome piece of code Abinaya (sorry i cld not +1 im still a newbie here at SO), just what i was looking for, thanks, just a minor correction, based on the comment at jqfaq.com. tried it out and it works 100%.
// if row is undefined, we clicked on the legend
//if (typeof sel[0].row === 'undefined') { *** doesn't seem to work
if (sel[0].row === null) { // this works
checkout the amended jsfiddle
I also had been searching for code on how to get the selected legend label and your code also does that using this line of code
//get selected legend label
data.getColumnLabel(col)
thanks again

Google chart redraw/scale on window resize

How do I redraw/rescale a google linechart on window resize?
To redraw only when the window resize is completed and avoid multiple triggers, I think is better create an event:
//create trigger to resizeEnd event
$(window).resize(function() {
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
$(this).trigger('resizeEnd');
}, 500);
});
//redraw graph when window resize is completed
$(window).on('resizeEnd', function() {
drawChart(data);
});
The original code by Google simply does this at the end:
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
Changing it with a little javascript you can scale it when the window resizes:
function resize () {
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
window.onload = resize;
window.onresize = resize;
Since the window.resize event fires multiple times on each resize event, I believe that the best solution is to use smartresize.js and use smartdraw(). This limits the number of chart redraw’s per window.resize.
By using the provided js you can do it as simply as this:
// Instantiate and draw our user charts, passing in some options (as you probably were doing it)
var chart = new google.visualization.LineChart(document.getElementById('div_chart'));
chart.draw(data, options);
// And then:
$(window).smartresize(function () {
chart.draw(data, options);
});
This is the simplest way I can work out of doing this without causing too much stress to the browser:
var chart1 = "done";
$(window).resize(function() {
if(chart1=="done"){
chart1 = "waiting";
setTimeout(function(){drawChart();chart1 = "done"},1000);
}
});
All it does is wait 1 second before the chart reloads and doesn't let the function call again in this waiting period. as window resize functions are called multiple times any time you change the window size this helps make the function only actually work once each time you change the window size, the rest of the calls get stopped by the if statement.
I hope this helps
There is no option in Google Visualization API to make Google Charts responsive.
But we can make Google Charts responsive as Window Resizes. To make Google Chart responsive there is jQuery library available at GitHub - jquery-smartresize licensed under MIT License, which has the ability to resize graphs on window resize event.
This project on GitHub has two script files :-
jquery.debouncedresize.js: adds a special event that fires once after the window
has been resized.
&
jquery.throttledresize.js: adds a special event that fires at a reduced rate (no
more double events from Chrome and Safari).
Here are two examples of responsive charts...
Responsive Google Pie Chart
Responsive Google Bar Chart
We can change the bottom padding of visualization_wrap to match the desired aspect ratio of chart.
Calculate as Height / Width x 100
For a 16x9 display it would be 9/16 = 0.5625 x 100 = 56.25%
For a square it'd be 100%
We can customize chartarea option of Google Chart to ensure that labels don't get cut off on resizing.
Redraw/rescale a Google linechart on window resize:
$(document).ready(function () {
$(window).resize(function(){
drawChart();
});
});
I personally prefer the following approach, if You can live with using addEventListener, and don't mind lack of support for IE < 9.
var windowResizeTimer;
window.addEventListener('resize', function(e){
clearTimeout(windowResizeTimer);
windowResizeTimer = setTimeout(function(){
chart.draw(data, options);
}, 750);
});
Note the use of the setTimeout() and clearTimeout() functions and the added delay of 750 milliseconds, which makes this slightly less intensive when multiple resize events fire in quick succession (which is often the case for browsers on desktop when resizing using a mouse).
I've been stuck on the same thing for days and I found out that adding an event works best.
window.addEventListener("resize", drawChart);
Just add this line after declaring your function and it will work fine.
Replace drawChart with the name of your function.
Try with these approaches
window.dispatchEvent(new Event('resize'))
Chartkick.charts["<id of chart element like chart-1>"].redraw()
Using Tiago Castro's answer, I have implemented a line chart to show the demonstration.
google.load('visualization', '1', {
packages: ['corechart', 'line']
});
google.setOnLoadCallback(drawBackgroundColor);
function drawBackgroundColor() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'Compute Time');
data.addColumn('number', 'Compute Times');
console.log("--");
data.addRows([
[0, 0, 0],
[10, 10, 15],
[20, 20, 65]
]);
console.log(data);
var options = {
height: 350,
legend: {
position: 'bottom'
},
hAxis: {
title: 'Nb Curves'
},
vAxis: {
title: 'Time (ms)'
},
backgroundColor: '#f1f8e9'
};
function resize() {
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
window.onload = resize();
window.onresize = resize;
}
<script src='https://www.google.com/jsapi'></script>
<div id="chart_div">

Categories

Resources