How to get data point x/y values when Google Visualisation line chart data point clicked [duplicate] - google-visualization

i want to take out 'text value' on mouse click on anywhere on the row/svg image ,for i.e. in the below image if i click anywhere on 2nd blue highlighted row, then i should be able to get the text 'Adams' as alert. I tried to iterate thru svg elements but svg elements are created horizontally rather then vertically

you can use the 'select' event, to determine the value selected
when the 'select' event fires, check chart.getSelection()
google.visualization.events.addListener(chart, 'select', function () {
selection = chart.getSelection();
if (selection.length > 0) {
console.log(dataTable.getValue(selection[0].row, 0));
}
});
getSelection returns an array of the selected rows,
Timeline charts only allow one row to be selected at a time,
so the selection will always be in the first element
chart.getSelection()[0]
each element in the array will have properties for row and column
(column will always be null for a Timeline chart)
once you have the row, you can use getValue on the DataTable
dataTable.getValue(selection[0].row, 0)
getValue takes two arguments, rowIndex and columnIndex
use 0 to get the value of the first column
see following working snippet...
google.charts.load('current', {
callback: function () {
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) ]]);
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
google.visualization.events.addListener(chart, 'select', function () {
selection = chart.getSelection();
if (selection.length > 0) {
console.log(dataTable.getValue(selection[0].row, 0));
}
});
chart.draw(dataTable);
},
packages: ['timeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="timeline"></div>
EDIT
to capture the click anywhere on the row, outside the colored bar,
use the 'ready' event to find the svg elements and add a listener
the elements will have an x attribute of zero (0)
and a fill attribute other than 'none'
since the number of elements will match the number of rows,
we can use the index of the element, amongst its peers, to find the value
see following working snippet,
both the 'select' and 'click' events are used to find the value clicked
google.charts.load('current', {
callback: function () {
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) ]]);
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var saveRows = [];
google.visualization.events.addListener(chart, 'ready', function () {
chartRows = container.getElementsByTagName('rect');
Array.prototype.forEach.call(chartRows, function(row) {
if ((parseInt(row.getAttribute('x')) === 0) && (row.getAttribute('fill') !== 'none')) {
saveRows.push(row);
row.addEventListener('click', function (e) {
for (var i = 0; i < saveRows.length; i++) {
if (e.target === saveRows[i]) {
getRowLabel(i);
break;
}
}
}, false);
}
});
});
google.visualization.events.addListener(chart, 'select', function () {
selection = chart.getSelection();
if (selection.length > 0) {
getRowLabel(selection[0].row);
}
});
function getRowLabel(index) {
console.log(dataTable.getValue(index, 0));
}
chart.draw(dataTable);
},
packages: ['timeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="timeline"></div>

Related

Google Visualization API series data in rows not columns. Pivot? [duplicate]

I want to display "population" of various countries through the years in the same line chart. The data displayed is based on selections from a multi-select dropdown "Countries". Underlying Data Table has 3 columns:
Year, Country, Population
2012,countryA,33
2013,countryA,35
2014,countryA,40
2012,countryB,65
2013,countryB,70
2014,countryB,75
2012,countryC,15
2013,countryC,20
2014,countryC,25
I am trying to create a pivoted Data View from the underlying Data Table
The code I am using is:
function drawLineChart() {
var arr = $('#country').val();
var lineChartJson = $.ajax({
url: "../json/lineChart.json",
dataType: "json",
async: false
}).responseText;
var lineChartData = new google.visualization.DataTable(lineChartJson);
var view = new google.visualization.DataView(lineChartData);
var viewCols = [0];
for(var i = 0; i < arr.length; i++) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
}
view.setColumns(viewCols);
var aggCols = [{
column: 1,
type: 'number',
label: view.getColumnLabel(1),
aggregation: google.visualization.data.sum
}];
for(var i = 2; i < 4; i++) {
var aggCols1 = [{
column: i,
type: 'number',
label: view.getColumnLabel(i),
aggregation: google.visualization.data.sum
}];
aggCols = aggCols.concat(aggCols1);
}
var pivotedData = google.visualization.data.group(view, [0], aggCols);
But this does not seem to work as expected and I just get 1 Line in the chart with values for all countries added up (although I can see the legend for 3 countries)
On the other hand if I set my View columns as below, it works as expected.
view.setColumns([0, {
type: 'number',
label: arr[0],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[0]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[1],
calc: function (dt, row) {
// return values of C only for the rows where B = "bar"
return (dt.getValue(row, 1) == arr[1]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[2],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[2]) ? dt.getValue(row, 2) : null;
}
}]);
What is going wrong in the loop? Is something wrong with "concat" in the loop where I am creating View Columns? I also saw the viewCols array by using console.log and it seems to have the right elements
I was trying to follow the below post:
Creating pivoted DataView from existing google charts DataTable object
the problem has to do with scope
arr[i] is undefined within calc: function (dt, row)
here is another way to pivot the data...
google.charts.load('current', {
callback: function () {
var arr = [
'countryA',
'countryB',
'countryC'
];
var lineChartData = google.visualization.arrayToDataTable([
['Year', 'Country', 'Population'],
[2012,'countryA',33],
[2013,'countryA',35],
[2014,'countryA',40],
[2012,'countryB',65],
[2013,'countryB',70],
[2014,'countryB',75],
[2012,'countryC',15],
[2013,'countryC',20],
[2014,'countryC',25]
]);
// sort by year
lineChartData.sort([{column: 0}]);
// get unique countries
var countryGroup = google.visualization.data.group(
lineChartData,
[1]
);
// build country data table
var countryData = new google.visualization.DataTable({
cols: [
{label: 'Year', type: 'number'},
]
});
// add column for each country
for (var i = 0; i < countryGroup.getNumberOfRows(); i++) {
countryData.addColumn(
{label: countryGroup.getValue(i, 0), type: 'number'}
);
}
// add row for each year / country
var rowYear;
var rowIndex;
for (var i = 0; i < lineChartData.getNumberOfRows(); i++) {
if (rowYear !== lineChartData.getValue(i, 0)) {
rowYear = lineChartData.getValue(i, 0);
rowIndex = countryData.addRow();
countryData.setValue(rowIndex, 0, rowYear);
}
for (var x = 1; x < countryData.getNumberOfColumns(); x++) {
if (countryData.getColumnLabel(x) === lineChartData.getValue(i, 1)) {
countryData.setValue(rowIndex, x, lineChartData.getValue(i, 2));
}
}
}
// draw agg table
new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'table-div',
dataTable: countryData
}).draw();
// draw line chart
new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart-div',
dataTable: countryData
}).draw();
},
packages: ['corechart', 'table']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="table-div"></div>
<div id="chart-div"></div>
I could figure out the problem with my code above.
"calc" is the callback function in loop. So only last value of loop variable "i" is visible within the loop.
Putting a wrapper function fixes it:
for(var i = 0; i <= arr.length; i++)(function(i) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
})(i);

Legend and axis tooltip comes with black box with google chart (Firefox

I am currently working on Google Charts with below Version.
google.charts.load('upcoming', {packages: ['corechart']);
When i enter a mouse on axis and legend tooltip comes with black box as per attached image.
I also tried "Current" and "42" version but still getting a same issue as in attached image. I am facing this issue with Firefox.
Google Line Chart- Tooltip with balck box in Firefox
Is it a bug in Google Chart API or anything else?
tooltip seems to work fine here
any code / css / chart options you can share?
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var dataTable = new google.visualization.DataTable({
cols: [
{id: 'x', label: 'Date', type: 'date'},
{id: 'y', label: 'Fn', type: 'number'},
{id: 'z', label: 'Shade', type: 'number'}
]
});
var formatDate = new google.visualization.DateFormat({
pattern: 'MMM-dd-yyyy'
});
var oneDay = (1000 * 60 * 60 * 24);
var startDate = new Date(2016, 10, 27);
var endDate = new Date();
var ticksAxisH = [];
var dateRanges = [
{start: new Date(2017, 0, 1), end: new Date(2017, 0, 20)},
{start: new Date(2017, 1, 5), end: new Date(2017, 1, 10)}
];
var maxShade = 200;
for (var i = startDate.getTime(); i < endDate.getTime(); i = i + oneDay) {
// x = date
var rowDate = new Date(i);
var xValue = {
v: rowDate,
f: formatDate.formatValue(rowDate)
};
// y = 2x + 8
var yValue = (2 * ((i - startDate.getTime()) / oneDay) + 8);
// z = null or max shade
var zValue = null;
dateRanges.forEach(function (range) {
if ((rowDate.getTime() >= range.start.getTime()) &&
(rowDate.getTime() <= range.end.getTime())) {
zValue = maxShade;
}
});
// add data row
dataTable.addRow([
xValue,
yValue,
zValue
]);
// add tick every 7 days
if (((i - startDate.getTime()) % 7) === 0) {
ticksAxisH.push(xValue);
}
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
dataTable: dataTable,
options: {
chartArea: {
bottom: 64,
top: 48
},
hAxis: {
slantedText: true,
ticks: ticksAxisH
},
legend: {
position: 'top'
},
lineWidth: 4,
series: {
// line
0: {
color: '#00acc1'
},
// area
1: {
areaOpacity: 0.6,
color: '#ffe0b2',
type: 'area',
visibleInLegend: false
},
},
seriesType: 'line'
}
});
chart.draw(container);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

How to Suppress Horizontal Scrollbar on Table

I would like a Google Visualization Table with a fixed width and td cells that wrap. When I specify a width in the draw method a horizontal scroll bar appears. Rather than this, I want wrapping of cells.
This jsfiddle is a working example. In this example I would like for the first column to wrap. I have tried adding a class with word-wrap: break-word;. But this does not work.
Here is relevant js:
function drawChart() {
var cssClassNames = {
'tableCell': 'googlecell'
};
var datatable = new google.visualization.DataTable();
datatable.addColumn('string', 'Keyword', 'col1');
datatable.addColumn('number', 'Pageviews');
datatable.addColumn('number', 'Secs.');
datatable.addRows(3);
datatable.setCell(0, 0, '(not set)');
datatable.setCell(0, 1, 20308);
datatable.setCell(0, 2, 68.74);
datatable.setCell(1, 0, '(not provided)');
datatable.setCell(1, 1, 14410);
datatable.setCell(1, 2, 49.99);
datatable.setCell(2, 0, 'product_type_l1==sdsssijven&+product_type_l2==*');
datatable.setCell(2, 1, 3838);
datatable.setCell(2, 2, 48.35);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(datatable, {
showRowNumber: false,
'allowHtml': true,
'cssClassNames': cssClassNames,
width: 400
});
}
google.load("visualization", "1", {
packages: ["corechart", "table"]
});
google.setOnLoadCallback(drawChart);
And relevant css:
.googlecell {
word-wrap: break-word;
}
What about:
.googlecell {
word-break: break-all;
}
Is that what you are after? (demo)

Google Line Chart Legend Click Events

I want to hide the line in Line chart when ever the user clicks on the Line Chart legend. Is there any way that I can do it in Google Chart API ? I seen this feature on Highcharts.
Yes it is possible. Here is an example by asgallant:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'City');
data.addColumn('number', 'Foo');
data.addColumn('number', 'Foo');
data.addColumn('number', 'Bar');
data.addColumn('number', 'Bar');
data.addColumn('number', 'Baz');
data.addColumn('number', 'Baz');
data.addRow(['Boston', 5, null, 7, null, 2, null]);
data.addRow(['New York', 4, null, 8, null, 5, null]);
data.addRow(['Baltimore', 6, null, 2, null, 4, null]);
/* define the series object
* follows the standard 'series' option parameters, except it has two additonal parameters:
* hidden: true if the column is currently hidden
* altColor: changes the color of the legend entry (used to grey out hidden entries)
*/
var series = {
0: {
hidden: false,
visibleInLegend: false,
color: '#FF0000'
},
1: {
hidden: false,
color: '#FF0000',
altColor: '#808080'
},
2: {
hidden: false,
visibleInLegend: false,
color: '#00FF00'
},
3: {
hidden: false,
color: '#00FF00',
altColor: '#808080'
},
4: {
hidden: false,
visibleInLegend: false,
color: '#0000FF'
},
5: {
hidden: false,
color: '#0000FF',
altColor: '#808080'
}
};
var options = {
series: series,
height: 400,
width: 600
};
var view = new google.visualization.DataView(data);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
google.visualization.events.addListener(chart, 'select', function () {
// if row is undefined, we clicked on the legend
if (typeof chart.getSelection()[0]['row'] === 'undefined') {
// column is the DataView column, not DataTable column
// so translate and subtract 1 to get the series index
var col = view.getTableColumnIndex(chart.getSelection()[0]['column']) - 1;
// toggle the selected column's data counterpart visibility
series[col - 1].hidden = !series[col - 1].hidden;
// swap colors
var tmpColor = series[col].color;
series[col].color = series[col].altColor;
series[col].altColor = tmpColor;
// reset the view's columns
view.setColumns([0,1,2,3,4,5,6]);
// build list of hidden columns and series options
var hiddenCols = [];
options.series = [];
for (var i = 0; i < 6; i++) {
if (series[i].hidden) {
// add 1 to the series index to get DataTable column
hiddenCols.push(i + 1);
}
else {
options.series.push(series[i]);
}
}
// hide the columns and draw the chart
view.hideColumns(hiddenCols);
chart.draw(view, options);
}
});
chart.draw(view, options);
}
Here is the solution. You can hide line in your line chart by clicking the legend.
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
As mentioned above, you can create a DataView for your DataTable and then
to show only the clicked line/column, call
view.setColumns(chart.getSelection()[0].column)
to hide the clicked line/column call
view.hideColumns(chart.getSelection()[0].column)
getSelection() will have the line/legend on the chart you have selected.

Sencha touch - trying to delete row from list

I try to get an editable list with this code:
var isEditing = false;
new Ext.Application({
launch: function(){
new Ext.Panel({
//layout: 'card',
fullscreen: true,
items: new Ext.List({
id: 'myList',
store: new Ext.data.Store({
fields: ['myName'],
data: [{ myName: 1 }, { myName: 2 }, { myName: 3}]
}),
itemSelector: '.x-list-item',
multiSelect: true,
itemTpl: '<span class="name">{myName}</span>',
tpl: new Ext.XTemplate(
'<tpl for=".">' +
'<div class="x-list-item">' +
'<tpl if="this.isEditing()">' +
'<img src="images/delete.gif" ' +
'onclick="Ext.getCmp(\'myList\').myDeleteItem({[xindex-1]})" ' +
'style="vertical-align: middle; margin-right: 15px;"/>' +
'</tpl>' +
'{myName}</div>' +
'</tpl>',
{
compiled: true,
isEditing: function () {
console.log('isEditing (tpl):' + isEditing)
return isEditing;
}
}),
myDeleteItem: function (index) {
var store = this.getStore();
var record = store.getAt(index);
console.log('removing ' + record.data.myName);
store.remove(record);
},
listeners: {
itemtap: function () {
if (isEditing){
console.log('isEditing: ' + isEditing);
return;
}
},
beforeselect: function () {
console.log('isEditing: before ' + !isEditing);
return !isEditing;
}
}
}),
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
layout: { pack: 'right' },
items: [
{
xtype: 'button',
text: 'Edit',
handler: function () {
var list = Ext.getCmp('myList');
if (!isEditing)
list.mySelectedRecords = list.getSelectedRecords();
isEditing = !isEditing;
this.setText(isEditing ? 'Save' : 'Edit');
list.refresh();
if (!isEditing)
list.getSelectionModel().select(list.mySelectedRecords);
}
}]
}]
});
}
});
but its not working like it should. If I press the EDIT button there is no delete-image and so there is no deleted item....
There are 3 things that I can see:
The Template is rendered once, you will need to call .refresh() or .refreshNode() on the list to update any item templates. The better way to accomplish this would be to hide the delete button via CSS and display it when the 'edit' button is clicked.
There is probably a naming conflict between the isEditing variable declared at the top and the isEditing function reference. It is very confusing to have these two things named the same, and can lead to problems with variable scoping.
The click event that you are looking for may be intercepted by the parent list item and Sencha Touch is turning it into a 'itemtap' event on the list item.
I was not able to delete until I added an id field without a datatype to my model. I don't know why as it should know which record to delete via the index.
Ext.regModel('Setting', {
fields: [
{name: 'id'}, // delete works after adding
{name: 'name', type: 'string'}
],
proxy: {
type: 'localstorage',
id: 'settings'
}
Kevin