Set null dates on Google Chart Timeline - javascript

Im trying to create a Timeline chart using Google Chart API. However the problem is I can't handle null dates on specific rows.
How do you hide rows that have null Start or End dates?
google.charts.load("current", {packages:["timeline"]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
google.visualization.events.addListener(chart, 'error', errorHandler);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Role' });
dataTable.addColumn({ type: 'string', id: 'Name' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[
'NTC',
'NTC',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Briefing Meeting',
'Baseline',
new Date('07/07/2016'),
new Date('07/06/2016'),
],
[
'Concept Design',
'Baseline',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Concept Design',
'Forecast',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Concept Design',
'Actual',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Detail Design',
'Baseline',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Detail Design',
'Forecast',
new Date('07/05/2016'),
new Date('07/06/2016'),
],
[
'Detail Design',
'Actual',
new Date('07/05/2016'),
new Date(),
],
]);
var colors = [];
var colorMap = {
Baseline: '#425cfb',
Forecast: '#f8ac08',
Actual: '#06af90',
NTC: '#1b9e2e'
}
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
colors.push(colorMap[dataTable.getValue(i, 1)]);
}
var options = {
colors: colors,
timeline: {
showBarLabels: false,
groupByRowLabel: true,
// rowLabelStyle: {fontName: 'Helvetica', fontSize: 24, color: '#603913'},
barLabelStyle: { fontName: 'Garamond', fontSize: 6 },
},
interpolateNulls: true,
};
}
It displays invalid datetime if I set new Date(0), Is there a workaround here?

Filtering the already incorrect rows when you have the possibility to filter these posts at your server code is a waste of time and resources. Try to filter these in your PHP instead!
Google provides you with a filter method which you can use to filter your rows. I've also used the DataView class in this solution.
First I created a filterDate at the same time as the rest of our empty new Date()s, then I 'zeroed' the milliseconds, as there might pass a millisecond or two before this is executed.
//use this one to determine what date to filter away.
var filterDate = new Date();
filterDate.setMilliseconds(0);
//Convert to JSON
filterDate = filterDate.toJSON();
Then I filter the rows I wish to use, using the filter option test which executes a function, passing the value, row, column and datatable as parameters. Should return false if you wish to exclude the row:
//filter the rows we actually want
var someRows = dataTable.getFilteredRows([{
column: 2,
test: testFunc
}, {
column: 3,
test: testFunc
}]);
In our function that we call, testFunc we 'zero' the milliseconds, and convert it to JSON and then compare to our filterDate. If it's the same, we judge that the row should be excluded:
//This is our test function
function testFunc(value) {
value.setMilliseconds(0);
return value.toJSON() !== filterDate;
}
Lastly we initiate a DataView from our dataTable and we set our rows to be the ones we just filtered:
//Create a dataView object from our dataTable, and set the rows to the ones we just filtered
var dataView = new google.visualization.DataView(dataTable);
dataView.setRows(someRows);
And we're good to go, but as already stated, you should try to filter these at your serverside instead.
JSFiddle for reference

Related

Moving annotations on Bar Chart with Negative Values Google Chart

I am using google charts within an MVC project.
I am looking to implement a bar chart that has negative values.
I would like the annotations on the negative portion of the chart to be on the same side as the end of the bar (just like the positive, see image below, green box is where I would like annotations to be).
I cant seem to find any documentation on how this can be achieved.
Is it possible to move the annotation to the other side?
there are no standard config options that will move the annotations
but you can move them manually
however, the chart will actually move them back whenever activity occurs,
such as on bar hover
have to use a MutationObserver, or something, to keep them there
use chart methods --> getChartLayoutInterface().getXLocation(value)
to find the location
also, need to adjust the axis window to leave room for the labels
see following working snippet...
google.charts.load('current', {
callback: function () {
var data = new google.visualization.DataTable({
cols: [
{label: 'x', type: 'string'},
{label: 'y0', type: 'number'},
],
rows: [
{c:[{v: 'Omega'}, {v: -0.95}]},
{c:[{v: 'Large'}, {v: -0.92}]},
{c:[{v: 'Medium'}, {v: 2.76}]},
{c:[{v: 'Tiny'}, {v: 2.03}]}
]
});
var options = {
annotations: {
alwaysOutside: true,
stem: {
color: 'transparent'
},
textStyle: {
color: '#000000'
}
},
hAxis: {
// leave room for annotation
viewWindow: {
min: data.getColumnRange(1).min - 1
}
},
legend: {
position: 'none'
}
};
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: 'stringify',
sourceColumn: 1,
type: 'string',
role: 'annotation'
}]);
var container = document.getElementById('chart');
var chart = new google.visualization.BarChart(container);
// move annotations
var observer = new MutationObserver(function () {
$.each($('text[text-anchor="start"]'), function (index, label) {
var labelValue = parseFloat($(label).text());
// only negative -- and -- not on tooltip
if ((labelValue < 0) && ($(label).attr('font-weight') !== 'bold')) {
var bounds = label.getBBox();
var chartLayout = chart.getChartLayoutInterface();
$(label).attr('x', chartLayout.getXLocation(labelValue) - bounds.width - 8);
}
});
});
observer.observe(container, {
childList: true,
subtree: true
});
chart.draw(view, options);
},
packages: ['corechart']
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>

google charts timelines element border-radius

I have a problem figuring out how to set the border-radius on elements in a google charts Timeline. I have looked through all the options but there doesn't seem to be one for that.
I have tried manually setting it but without any luck.
Does anyone have a solution to this problem?
thx in advance
the chart elements can be modified when the chart's 'ready' event fires
however, the chart will revert back to the original style on any interactivity
a MutationObserver can be used to know when the chart has been modified
in order to re-apply the custom style / border radius
the chart is drawn using svg, to change the border radius on a rect element,
set attributes 'rx' and 'ry'
see the following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['timeline']
});
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) ]
]);
var observer = new MutationObserver(setBorderRadius);
google.visualization.events.addListener(chart, 'ready', function () {
setBorderRadius();
observer.observe(container, {
childList: true,
subtree: true
});
});
function setBorderRadius() {
Array.prototype.forEach.call(container.getElementsByTagName('rect'), function (rect) {
if (parseFloat(rect.getAttribute('x')) > 0) {
rect.setAttribute('rx', 20);
rect.setAttribute('ry', 20);
}
});
}
chart.draw(dataTable);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="timeline"></div>

how to use boolean type column in Google calendar charts?

I want to depict build status (Pass or fail) using a boolean type(true/false) on google's Calendar type charts. I am using the below HTML code for the same. But I am getting a red flag prompting me to add 2 columns . Any suggestions what could be wrong in this snippet ?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {packages:["calendar"]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'date', id: 'Date' });
dataTable.addColumn({ type: 'boolean',id :'pass/fail', role:'certainty' });
dataTable.addRows([
[ new Date(2012, 3, 13), true ],
[ new Date(2012, 3, 14), true ],
[ new Date(2012, 3, 15), true ],
[ new Date(2012, 3, 16), true ],
[ new Date(2012, 3, 17), false ]
// Many rows omitted for brevity.
]);
var chart = new google.visualization.Calendar(document.getElementById('calendar_basic'));
var options = {
title: "Build Execution Analytics",
height: 350,
};
chart.draw(dataTable, options);
}
</script>
</head>
<body>
<div id="calendar_basic" style="width: 1000px; height: 350px;"></div>
</body>
</html>
each chart type has a specific Data Format
Calendar charts do not accept a boolean column
from the reference, allowed columns are...
column 0 -- date, datetime, or timeofday
column 1 -- number
column n -- string -- role: tooltip (optional)
I would suggest using a certain number for pass and another for fail
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'date', id: 'Date' });
dataTable.addColumn({ type: 'number', id :'pass/fail' });
dataTable.addRows([
[ new Date(2012, 3, 13), 100 ], // pass
[ new Date(2012, 3, 14), 100 ], // pass
[ new Date(2012, 3, 15), 100 ], // pass
[ new Date(2012, 3, 16), 100 ], // pass
[ new Date(2012, 3, 17), 0 ] // fail
]);
var chart = new google.visualization.Calendar(document.getElementById('calendar_basic'));
chart.draw(dataTable, {
title: 'Build Execution Analytics',
height: 350,
});
},
packages:["calendar"]
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="calendar_basic"></div>

Google Charts Timeline - PHP array as input

I am working on a Google Charts Timeline plot, showing the duration periods of a number of tasks, located in a table in a MySQL database. Using PHP there is a number of ways to retrieve and store this, for instance as a 2-dimensional array. However, is there a way to pass such an array (or other easily created data containing objects), in the way that the Google Charts Timeline can handle, through the dataTable.addrows() method?
Or if I should describe it as an example:
function drawChart() {
// Nothing to see here, move along now...
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
// The column heading can be fixed or variable, this doesnt matter.
dataTable.addColumn({ type: 'string', id: 'Opgave ID' });
dataTable.addColumn({ type: 'string', id: 'Opgavetitel' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
/* I would like to replace the fixed input of dataTable.addRows, with a
*variable input, for instance a 2-dimensional PHP-array.
*/
dataTable.addRows([
[ '1', 'Some task', new Date(2015, 3, 9), new Date(2015, 3, 23) ],
[ '2', 'Another task', new Date(2015, 3, 13), new Date(2015, 3, 20) ],
[ '3', 'A different task', new Date(2015, 3, 16), new Date(2015, 3, 30) ]]);
// No questions for any of this
var options = {
timeline: {showRowLabels: false, singleColor: '#8d8'}
};
chart.draw(dataTable, options);
}
Doing a quick google search, I found this article:
http://www.dyn-web.com/tutorials/php-js/json/multidim-arrays.php
I'm not a PHP programmer, so this isn't tested but should work:
<?
$timeData = array(
array('1', 'Some task', new DateTime('2015-04-09'), new DateTime('2015-04-23')),
array('2', 'Another task', new DateTime('2015-04-13'), new DateTime('2015-04-20')),
array('3', 'A different task', new DateTime('2015-04-16'), new Date('2015-04-30))
);
?>
function drawChart() {
// Nothing to see here, move along now...
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
// The column heading can be fixed or variable, this doesnt matter.
dataTable.addColumn({ type: 'string', id: 'Opgave ID' });
dataTable.addColumn({ type: 'string', id: 'Opgavetitel' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows(<? echo json_encode( $timeData ); ?>);
// No questions for any of this
var options = {
timeline: {showRowLabels: false, singleColor: '#8d8'}
};
chart.draw(dataTable, options);
}
You may find it easier to locate existing material if you broaden your search to a more basic concept (passing a PHP 2d array to javascript). Here's an example of an existing Stack Overflow question on that topic:
Best way to pass a 2d array into JavaScript from PHP?
And there are many more like it.
I got the same problem while using Google Charts Timeline while using Laravel 6.0 framework. I passed the query results to the view file as an associative array and the used json_encode() to convert the associative array into a JavaScript array that turned into an array of objects:
<script>
// create a custom data object to pass into the array
// the charter array data is of the format:
//
// Array(5)
// 0: {mn: "2020-02-12 10:03:17", mx: "2022-07-12 10:03:17", cha_booking_id: 1}
// 1: {mn: "2020-02-12 13:33:07", mx: "2020-10-12 13:33:07", cha_booking_id: 2}
// 2: {mn: "2020-02-12 13:39:47", mx: "2020-08-12 13:39:47", cha_booking_id: 3}
// 3: {mn: "2020-04-12 06:21:08", mx: "2020-04-12 06:21:08", cha_booking_id: 4}
// 4: {mn: "2020-05-12 08:44:24", mx: "2020-07-12 08:44:24", cha_booking_id: 5}
var data = [];
charter.forEach(el => {
var arr = [
el.cha_booking_id.toString(),
new Date(
el.mn.substring(0, 4), // get the year from the date format that is passed
el.mn.substring(5, 7), // get the month from the date format that is passed
el.mn.substring(8, 10) // get the day from the date format that is passed
),
new Date(
el.mx.substring(0, 4),
el.mx.substring(5, 7),
el.mx.substring(8, 10)
)
];
data.push(arr);
// The column heading can be fixed or variable, this doesnt matter.
dataTable.addColumn({ type: 'string', id: 'Opgave ID' });
dataTable.addColumn({ type: 'string', id: 'Opgavetitel' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows(data);
// No questions for any of this
var options = {
timeline: {showRowLabels: false, singleColor: '#8d8'}
};
chart.draw(dataTable, options);
</script>

Google Charts API: Always show the Data Point Values using arrayToDataTable. How?

First I'd like to let it be known that although there is a similar question labeled:
Google Charts API: Always show the Data Point Values in Graph
...on the site, I can't seem to use it's solution since my chart is fed using arrayToDataTable.
Here's my code:
function drawChart1998() {
var data = google.visualization.arrayToDataTable([
['Year', 'Index Trend'],
['1/3', 1236777],
['1/7', 834427],
['1/10', 2164890],
['1/14', 1893574],
['1/17', 2851881],
['1/21', 359504],
['1/24', 2264047],
['1/28', 3857933],
['1/31', 2197402],
['2/4', 2469935],
['2/7', 1651752],
['2/11', 4710582],
['2/14', 1565803],
['2/18', 345499],
['2/21', 2817319],
['2/25', 733242],
['2/28', 1485788],
['3/4', 1091181],
['3/7', 4477498],
['3/11', 490931],
['3/14', 3905556],
['3/18', 475417],
['3/21', 1512729],
['3/25', 1782796],
['3/28', 4778434]
]);
var options = {
curveType: "function",
title: '1998 Results',
vAxis: {viewWindow: {min: 0, max: 5006386}},
hAxis: {textStyle: {color: 'black', fontName: 'verdana', fontSize: 10} },
series: {0: { pointSize: 6 }}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_1998'));
chart.draw(data, options);
}
As you can see, I managed to set the series to display the DataPoint dots but I can't seem to figure out how to incorporate the following line of code as the previous post on the site suggests in order to display the values for each DataPoint.
data.addColumn({type: 'string', role: 'annotation'});
For reference, you can input an annotation column to your DataTable using the arrayToDataTable method. Pass an object instead of a string for the column header:
var data = google.visualization.arrayToDataTable([
[/* column headers */, {type: 'string', role: 'annotation'}, /* column headers */],
// ...
]);
This works for any column role.
If you just want to display the value of a data point, you don't have to add an extra column to your DataTable. You can use a DataView to add an "annotation" column, calculated as the string-value of a source column:
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
type: 'string',
role: 'annotation',
sourceColumn: 1,
calc: 'stringify'
}]);
Then draw the chart using the view instead of the DataTable:
chart.draw(view, options);

Categories

Resources