Add tooltips to a Google Line Chart with multiple data series - with simplified test case and screenshot - charts

I have a Google Line Chart with 2 data series - Row A and Row B:
Here is the very simple test code - just open it in the browser and it will work:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart']}]}"></script>
<script type="text/javascript">
var data = {"rows":[
{"c":[{"v":"C"},{"v":-43},{"v":-42}]},
{"c":[{"v":"D"},{"v":-49},{"v":-39}]},
{"c":[{"v":"E"},{"v":-49},{"v":-48}]},
{"c":[{"v":"F"},{"v":-50},{"v":-49}]},
{"c":[{"v":"G"},{"v":-57},{"v":-56}]}],
"cols":[
{"p":{"role":"domain"},"label":"MEASUREMENT","type":"string"},
{"p":{"role":"data"},"label":"Row A","type":"number"},
{"p":{"role":"data"},"label":"Row B","type":"number"}]};
function drawCharts() {
var x = new google.visualization.DataTable(data);
var options = {
title: 'How to add tooltips?',
width: 800,
height: 600
};
var chart = new google.visualization.LineChart(document.getElementById('test'));
chart.draw(x, options);
}
$(function() {
google.setOnLoadCallback(drawCharts);
});
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>
I would like to add tooltips to each data point, which would for example display:
Row A: x=D y=-49
on mouse hover. And I can not use dataTable.addColumn, because my chart is generated at once by a perl script and I just use a data Object with cols and rows as above.
Does anybody please know, how to do it here?

You can use a DataView to create the tooltip columns for you. This code snippet will dynamically create a tooltip column in the DataView for every data series:
var columns = [0];
for (var i = 1; i < x.getNumberOfColumns(); i++) {
columns.push(i);
columns.push({
type: 'string',
properties: {
role: 'tooltip'
},
calc: (function (j) {
return function (dt, row) {
return dt.getColumnLabel(j) + ': x=' + dt.getValue(row, 0) + ' y=' + dt.getValue(row, j)
}
})(i)
});
}
var view = new google.visualization.DataView(x);
view.setColumns(columns);
See the working example here: http://jsfiddle.net/asgallant/xWwxP/

Related

google charts - data from csv - date format

In a webpage I load data from a csv file that contains like (it can contains months of data) :
timestamp,open,high,low,close
2022-08-03,1.01554,1.02105,1.01210,1.01618
2022-08-02,1.02578,1.02939,1.01619,1.01625
2022-08-01,1.02182,1.02753,1.02040,1.02587
2022-07-29,1.01952,1.02544,1.01440,1.02248
2022-07-28,1.02005,1.02344,1.01120,1.01947
2022-07-27,1.01174,1.02209,1.00950,1.01998
2022-07-26,1.02210,1.02502,1.01060,1.01179
2022-07-25,1.02174,1.02579,1.01770,1.02200
The first column is a date, but I think the google chart treat it like a string while creating the chart.
This is the code in html page I use to load data from csv and to create the chart:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="jquery.csv-0.71.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
// load the visualization library from Google and set a listener
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
</script>
<script>
function drawVisualization() {
$.get("EURUSD.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
var view = new google.visualization.DataView(data);
//view.setColumns([0,1]);
var options = {
legend: 'none',
title: 'EURUSD',
bar: { groupWidth: '100%' }, // Remove space between bars.
candlestick: {
fallingColor: { strokeWidth: 0, fill: '#a52714' }, // red
risingColor: { strokeWidth: 0, fill: '#0f9d58' } // green
}
};
var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));
data.sort({column: 0, asc: true});
chart.draw(data, options);
});
}
google.setOnLoadCallback(drawVisualization)
</script>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
enter code here
The chart I get is:
I would like to group by month or by year in the X asses, insted of everyday date printed there.
How can I do?
Thank You
Carlo
after you load the csv data...
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
convert the first column to a date...
arrayData = arrayData.map(function (row) {
row[0] = new Date(row[0]);
return row;
});

How to prevent Google Charts from changing x-axis order?

I'm trying to draw a Google Chart whose x-axis represents the week numbers. As we're crossing a new year, the axis goes 50, 51, 52, 1, 2, 3, ....
I'm properly ordering my data, but Google Charts insists on reordering my x-axis, and I end up with a weird graph:
var chartData = [
["Week","Revenue"],
[40,227],
[41,317],
[42,320],
[43,482],
[44,418],
[45,345],
[46,313],
[47,316],
[48,380],
[49,467],
[50,349],
[51,256],
[52,393],
[1,276],
[2,349],
[3,312]
];
google.load("visualization", "1", {
packages:["corechart"],
callback: function() {
var div = document.getElementById('chart');
var chartDataTable = google.visualization.arrayToDataTable(chartData);
var chart = new google.visualization['LineChart'](div);
chart.draw(chartDataTable);
}});
<div id="chart" style="height: 400px;">test</div>
<script src="//www.google.com/jsapi"></script>
How can I prevent it from reordering my data?
google's object notation allows you to provide a value (v:) and a formatted value (f:)
thus, you can use a value of 1 with a format of '40'
e.g. --> {v: 1, f: '40'}
in a row --> [{v: 1, f: '40'},227]
the following working snippet uses object notation to re-format the values for the x-axis,
and re-use those values for the x-axis labels (hAxis.ticks)
var chartData = [
["Week","Revenue"],
[40,227],
[41,317],
[42,320],
[43,482],
[44,418],
[45,345],
[46,313],
[47,316],
[48,380],
[49,467],
[50,349],
[51,256],
[52,393],
[1,276],
[2,349],
[3,312]
];
var hAxisTicks = [];
chartData.forEach(function (row, index) {
if (index === 0) {
return;
}
row[0] = {
v: index,
f: row[0].toString()
};
hAxisTicks.push(row[0]);
});
google.charts.load('current', {
callback: function () {
var div = document.getElementById('chart');
var chartDataTable = google.visualization.arrayToDataTable(chartData);
var chart = new google.visualization['LineChart'](div);
chart.draw(chartDataTable, {
hAxis: {
ticks: hAxisTicks
}
});
},
packages:['corechart']
});
<div id="chart"></div>
<script src="https://www.gstatic.com/charts/loader.js"></script>
note:
recommend using loader.js to load the the library, 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 only changes the load statement, see snippet above...
EDIT:
there are more options available for continuous axis
which must be sorted, or in reverse sort order ('number', 'date' values)
but the chart will respect the original sort order for a discrete axis ('string' values)
see following snippet for 'string' values
and discrete vs. continuous for more...
var chartData = [
["Week","Revenue"],
[40,227],
[41,317],
[42,320],
[43,482],
[44,418],
[45,345],
[46,313],
[47,316],
[48,380],
[49,467],
[50,349],
[51,256],
[52,393],
[1,276],
[2,349],
[3,312]
];
chartData.forEach(function (row, index) {
if (index === 0) {
return;
}
row[0] = row[0].toString();
});
google.charts.load('current', {
callback: function () {
var div = document.getElementById('chart');
var chartDataTable = google.visualization.arrayToDataTable(chartData);
var chart = new google.visualization['LineChart'](div);
chart.draw(chartDataTable);
},
packages:['corechart']
});
<div id="chart"></div>
<script src="https://www.gstatic.com/charts/loader.js"></script>

How to draw date in x-axis in Area Chart?

I have the following data in a Google Spreadsheet:
ColumnA ColumnB
Departament Quantity
01/01/2016 23
02/01/2016 43
04/01/2016 5
06/01/2016 65
10/01/2016 12
11/01/2016 32
13/01/2016 22
15/02/2016 2
And want to draw a linechart using HTML Templates: This is my code so far now
<!DOCTYPE html>
<html>
<head>
<script src="https://www.google.com/jsapi"></script>
</head>
<body>
<div id="main"></div>
<script>
google.load('visualization', '1', {packages: ['corechart', 'bar']});
google.setOnLoadCallback(getSpreadsheetData);
function getSpreadsheetData() {
google.script.run.withSuccessHandler(drawChart).getSpreadsheetData();
}
function drawChart(rows) {
var options = {'title':'Example','width':400,'height':300};
var data = google.visualization.arrayToDataTable(rows, false);
var chart = newgoogle.visualization.LineChart(document.getElementById("main"));
chart.draw(data, options)
}
</script>
</body>
</html>
My script to read the sheet:
function getSpreadsheetData() {
var ssID = "12GvIStMKqmRFNBM-C67NCDeb89-c55K7KQtcuEYmJWQ",
sheet = SpreadsheetApp.openById(ssID).getSheets()[0],
data = sheet.getDataRange().getValues();
return data;
}
However i cant draw the plot, this issue dissapear when i change the data to a numeric (i.e. 42370), but thats not what i want!
Question is: what do i have to add in order to change to the right format in x axis?
You can use the hAxis.format configuration option
var options = {'title':'Example','width':400,'height':300,//-->'format':'MM/dd/yyyy'};
The valid format options can be found here...
And if you need to load with a specific locale, see this...

Google Visualization Chart Data Range

I have this code,
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", '1', {packages:['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1ntnhvfMhYtFNwFjkoKu8cUZOQPCaT5_U1Z6piB_w0-E/edit#gid=0');
query.setQuery('order by A');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var options = {
title: 'TEMP & HUMID',
hAxis: {
direction: -1
},
legend: 'none'
};
var data = response.getDataTable();
var chart = new google.visualization.LineChart(document.getElementById('columnchart'));
chart.draw(data, options);
}
</script>
<title>Data from a Spreadsheet</title>
</head>
<body>
<div id="columnchart" style="width: 900px; height: 500px"></div>
</body>
</html>
And here is my spreadsheet data: https://docs.google.com/spreadsheets/d/1ntnhvfMhYtFNwFjkoKu8cUZOQPCaT5_U1Z6piB_w0-E
What I want to do is to plot last 5 data. i.e) row 8 - 12 in my spreadsheet.
I tried the limit and range queries, but what I want to do is, if a new data comes in, I want the chart to refer the updated last 5 data i.e) row 9 -13
How could I achieve this?
I don't know if this is a best approach, but I work it out.
So, before drawing the table, I actually called the spreadsheet in JSON format and retrieve its column length.
Then I subtracted the column length by number of data I want to display (limit query) which will give me offset to start.
Then I made a string with the value of limit and offset to pass the query option to query.setQuery.
Here is the code for the part.
function drawChart() {
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1NSEbUWojJsMzhH0hi8kx8ic7Xxuq29z0c7BXs-inzb8/edit#gid=0');
$.getJSON("https://spreadsheets.google.com/feeds/list/1NSEbUWojJsMzhH0hi8kx8ic7Xxuq29z0c7BXs-inzb8/od6/public/basic?hl=en_US&alt=json", function(data) {
colLen = data.feed.entry.length;
console.log(colLen);
limit = 4;
var offset = colLen - limit;
console.log(offset);
queryOption = "limit "+limit+" offset "+offset;
console.log(queryOption);
query.setQuery(queryOption);
query.send(handleQueryResponse);
});
}

Implementing Search on a JqxTree using JqxdataAdapter Plugin..?

I am trying to implement a Search Over a JqxTree in which i am populating data with the help of JSON.
I want to implement the Search in a way that when i enter a string in a textbox the tree should expand till that component.
Can anyone help me out with this.
Following is my jsp code:-
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/jqwidgets/styles/jqx.base.css" type="text/css" />
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/demos.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxcore.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxdata.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxbuttons.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxscrollbar.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxpanel.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxtree.js"></script>
</head>
<body>
<div id='content' style='float: right;'>
<script type="text/javascript">
$(document).ready(function () {
$('#ExpandAll').jqxButton({ height: '25px', width: '100px'});
$('#CollapseAll').jqxButton({ height: '25px', width: '100px'});
// Expand All
$('#ExpandAll').click(function () {
$('#jqxWidget').jqxTree('expandAll');
});
//Collapse All
$('#CollapseAll').click(function () {
$('#jqxWidget').jqxTree('collapseAll');
});
var data = <%=request.getAttribute("data")%>
// prepare the data
var source =
{
datatype: "json",
datafields: [
{ name: 'categoryId' },
{ name: 'parentId' },
{ name: 'categoryName' },
],
id: 'categoryId',
localdata: data
};
// create data adapter.
var dataAdapter = new $.jqx.dataAdapter(source);
// perform Data Binding.
dataAdapter.dataBind();
// Get the tree items.
//The 1st parameter is the item's id.
//The 2nd parameter is the parent item's id.
//The 'items' parameter represents the sub items collection name.
//Each jqxTree item has a 'label' property, but in the JSON data, we have a 'text' field.
//The last parameter specifies the mapping between the 'text' and 'label' fields.
var records = dataAdapter.getRecordsHierarchy('categoryId', 'parentId', 'items', [{ name: 'categoryName', map: 'label'}]);
$('#jqxWidget').jqxTree({ source: records, width: '500px'});
});
</script>
</div>
<!-- DIV COMPONENTS -->
<div style='margin-top: 10px;'>
<input type="button" id='ExpandAll' value="Expand All" />
</div>
<div style='margin-top: 10px;' >
<input type="button" id='CollapseAll' value="Collapse All" />
</div><br/>
<div id='jqxWidget'>
</div>
</body>
</html>
Please Help me out..!! :)
Here's how I achieved It
$("#btnSearchTree").on('click', function () {
//Setting current selected item as null
$('#jqxWidget').jqxTree('selectItem', null);
//collapsing tree(in case if user has already searched it )
$('#jqxWidget').jqxTree('collapseAll');
//Using span for highlighting text so finding earlier searched items(if any)
var previousHighlightedItems = $('#jqxWidget').find('span.highlightedText');
// If there are some highlighted items, replace the span with its html part, e.g. if earlier it was <span style="background-color:"Yellow">Te></span>st then it will replace it with "Te""st"
if (previousHighlightedItems && previousHighlightedItems.length > 0) {
var highlightedText = previousHighlightedItems.eq(0).html();
$.each(previousHighlightedItems, function (idx, ele) {
$(ele).replaceWith(highlightedText);
});
}
//Getting all items for jqxTree
var items = $('#jqxWidget').jqxTree("getItems");
//Getting value for input search box and converting it to lower for case insensitive(may change)
var searchedValue = $("#ipSearchTreeText").val().toLowerCase();
//Searching the text in items label
for (var i = 0; i < items.length; i++) {
if (items[i].label.toLowerCase().indexOf(searchedValue) > -1) {
//If found expanding the tree to that item
$('#jqxWidget').jqxTree('expandItem', items[i].parentElement);
//selecting the item : not necessary as it selects the last item if multiple occurrences are found
$('#jqxWidget').jqxTree('selectItem', items[i]);
//changing the innerhtml of found item and adding span with highlighted color
var itemLabelHTML = $(items[i].element).find('div').eq(0).html();
//splitting the item text so that only searched text
can be highlighted by appending span to it.
var splittedArray = itemLabelHTML.split(searchedValue);
var highlightedText = '';
//if there are multiple occurrences of same searched text then adding span accordingly
for (var j = 0; j < splittedArray.length; j++) {
if (j != splittedArray.length - 1)
highlightedText = highlightedText + splittedArray[j] + '<span class="highlightedText" style="background-color:yellow">' + searchedValue + '</span>';
else
highlightedText = highlightedText + splittedArray[j];
}
//var highlightedText = splittedArray[0] + '<span style="background-color:yellow">' + searchedValue + '</span>' + splittedArray[1];
//replacing the item html with appended styled span
$(items[i].element).find('div').eq(0).html(highlightedText);
}
};
});