JQuery Flot not displaying correct time in x-axis - javascript

My graph is not correctly parsing the time. The x-axis consists of unix timestamps and my goal is to display it in M-D format in the users local time. For some reason, all dates are showing as 01/18.
Full code at JSFiddle: http://jsfiddle.net/v49wqvfv/3/
Graph code:
var data = [[1492854610, -1240],[1492939020, -1273],[1493025073, -1279],[1493117066, -1186],[1493198484, -1269],[1493289175, 1198],[1493370646, -1280],[1493458518, -1255],[1493543731, -1275],[1493630250, -1273],[1493716306, -1279],[1493803609, -1264],[1493889258, -1276],[1493975557, -1278],[1494064529, -1235],[1494155440, -1160],[1494237980, -1224],[1494321047, -1280],[1494407990, -1271],[1494494125, -1275],[1494581609, -1257],[1494668321, -1252],[1494753220, -1277],[1494847855, -1140],[1494925963, -1278],[1495012537, -1275],[1495099289, -1269],[1495188205, -1227],[1495273568, -1244],[1495358329, -1272]];
var ticks = [];
var abovePoints = [];
var belowPoints = [];
for (var i = 0; i < data.length; i++) {
ticks.push(data[i][0]);
}
data = [
{ label: null, data: data, points: {show:false} },
{ label: null, data: data, points: {show:true}, lines: {show:false}}
];
$.plot('#placeholder', data, {
grid: {
hoverable: true,
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: 0, to: 0 } },
]
},
series: {
color: '#f36b6b',
lines: {
show: true,
fill: true
},
points: {
show: true
},
threshold: {
below: 0,
color: '#56af45'
}
},
xaxis: {
mode: "time",
timeformat: "%m-%e"
}
});

JavaScript timestamp are in milliseconds while UNIX timestamps are in seconds. You need to multiply your timestamps with one thousand:
var data = [[1492854610000, -1240],[1492939020000, -1273],[1493025073000, -1279],[1493117066000, -1186],[1493198484000, -1269],[1493289175000, 1198],[1493370646000, -1280],[1493458518000, -1255],[1493543731000, -1275],[1493630250000, -1273],[1493716306000, -1279],[1493803609000, -1264],[1493889258000, -1276],[1493975557000, -1278],[1494064529000, -1235],[1494155440000, -1160],[1494237980000, -1224],[1494321047000, -1280],[1494407990000, -1271],[1494494125000, -1275],[1494581609000, -1257],[1494668321000, -1252],[1494753220000, -1277],[1494847855000, -1140],[1494925963000, -1278],[1495012537000, -1275],[1495099289000, -1269],[1495188205000, -1227],[1495273568000, -1244],[1495358329000, -1272]];
See the documentation for more information. Updated fiddle: http://jsfiddle.net/v49wqvfv/4/

Related

Chart JS custom message on tooltip, not x and y axis

I am displaying a bar chart that has 3 different pieces of information, (project name, number of days remaining, and the end date.) I am displaying the project name on one axis, and the number of days remaining determines the height of the bar. Currently, when I hover over a bar the tooltip displays the information already on the x and y axis. I want it to instead have the end date.
ie: project "b" will end in 2 days (August 4th), when I hover over the bar I want the tooltip to say "End date of 2022-08-04" instead of "b Work Days Remaining: 2"
My json of the data looks like this:
[{"po_num": "a", "days_rem": 10, "date_end": "2022-08-16"},
{"po_num": "b", "days_rem": 2, "date_end": "2022-08-04"},
{"po_num": "c", "days_rem": 6, "date_end": "2022-08-10"}]
Here is the link of the current graph.
https://i.stack.imgur.com/HefRz.png
Here is an MS paint rendering of what I am trying to do:
https://i.stack.imgur.com/GAT2I.png
The implementation code:
link = "{{{BASE_BACK_URL}}}";
$.getJSON(link, function (data) {
let po_names = [];
let days_rem = [];
for (let i = 0; i < data.length; i++) {
po_names.push(data[i]["po_num"]);
days_rem.push(data[i]["days_rem"]);
}
const ctx = document.getElementById('po-timeline-chart');
const myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: po_names,
datasets: [{
label: 'Work Days Remaining',
data: days_rem,
backgroundColor: 'rgb(0, 89, 178)'
}],
},
options: {
legend: {
align: "end"
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
});
Solution listed below:
$.getJSON(link, function (data) {
let po_names = [];
let days_rem = [];
for (let i = 0; i < data.length; i++) {
po_names.push(data[i]["po_num"]);
days_rem.push(data[i]["days_rem"]);
}
const ctx = document.getElementById("po-timeline-chart");
const myChart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: po_names,
datasets: [
{
label: "Work Days Remaining",
data: days_rem,
backgroundColor: "rgb(0, 89, 178)",
},
],
},
options: {
tooltips: {
enabled: true,
callbacks: {
// To change title in tooltip
title: (data) => {
return "This PO will run out on";
},
// To change label in tooltip
label: (data) => {
return date_end[data['index']];
},
},
},
legend: {
align: "end",
},
scales: {
xAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
});

jqplot number of events per hour

I have an array fetched from
<div style='hidden' id=dataHours data-hours='{"08":3,"10":3,"11":1,"12":1,"14":2,"16":2,"18":1}'>
It is converted to json array .
I would like to use jqplot to create an matrix with x-axis as hours an y-axis as number of events.
I currently tries this code:
var json_data = $('#dataHours').data('hours');
var dateHoursArray = $.map(json_data, function(value, index) {
return [[index,value]];
});
console.log(dateHoursArray);
$.jqplot('maindiv', dateHoursArray, {
legend: {
show:true,
location : 'ne'
},
title: 'Tickets created per hour',
animate: true,
animateReplot: true,
axes: {
xaxis: {
label:'Hours',
autoscale: true,
min:0,
max:23,
rendererOptions: {
tickRenderer:$.jqplot.CanvasAxisTickRenderer
},
tickOptions: {
formatString:'%.0f'
}
},
yaxis: {
label:'Tickets',
autoscale: true
}
},
highlighter: {
sizeAdjust: 7.5
},
cursor: {
show: false
},
grid: {
gridLineColor: '#cccccc',
background: '#fff',
borderColor: '#000',
borderWidth: 2.0,
shadow: false,
}
});
But it does not work as I would like to expect.
Anyone?
Logic.
Created an array of 24 hours and walked through array to increase counter on matching hour:
/*
Calculate max tickets per hour on 24 hours using tickets within specific period
*/
$date_sums = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; // 24 hours of 0
if(!empty($ticket_array)) {
foreach ($ticket_array AS $ticket) {
$hour = date("G", strtotime($ticket["ticket_created_date"]));
if (!empty($ticket["ticket_created_date"])) {
$date_sums[$hour] += 1;
} // end if
} // end foreach
foreach ($date_sums AS $sum => $value) {
$dates_sum[] = $value;
}
} // end if
Then Javascripted the base64_encoded json_encoded $dates_sum array:
var json_data = $('#dataHours').data('hours');
var json_data = JSON.parse(atob(json_data)); //base64 decode and make into javascript object
var dateHoursArray = [Array.from(json_data)];
Took me a few trial and errors on the last line of Array.from ;)

Highcharts Using CSV instead of JSON

I tried the code like this with many small restructuration and modification but without success.
Here is the code:
$(function () {
$.get('data.csv', function(data) {
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length,
// set the allowed units for data grouping
groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]],
i = 0;
for (i; i < dataLength; i += 1) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
]);
}
$('#chart').highcharts({
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
labels: {
align: 'right',
x: -3
},
title: {
text: 'OHLC'
},
height: '60%',
lineWidth: 2
}, {
labels: {
align: 'right',
x: -3
},
title: {
text: 'Volume'
},
top: '65%',
height: '35%',
offset: 0,
lineWidth: 2
}],
data: {
csv: data
},
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
Here is data.csv:
Date,Open,High,Low,Close,Volume
2013-12-20,9371.08,9413.09,9352.98,9400.18,161686900
2013-12-19,9279.68,9351.9,9257.24,9335.74,98276500
2013-12-18,9145.35,9190.73,9122.05,9181.75,82342700
2013-12-17,9142.75,9161.8,9085.12,9085.12,72207500
2013-12-16,9004.62,9187.78,8997.75,9163.56,99105600
2013-12-13,9016.78,9046.63,8990.58,9006.46,67761700
2013-12-12,9032.67,9060.54,8984.28,9017,75120200
2013-12-11,9093.26,9153.14,9065.51,9077.11,64845800
2013-12-10,9180.29,9223.73,9091.97,9114.44,74363400
Can you help me to figure out the problem or purpose new approch please ?
What is my goal ?
Is to be able to load a CSV file inside the chart instead of using JSON file.
Why ?
Because modifing CSV file is more easier for me using PHP than JSON, and it's for performance too.
Thank's
When you do data.length, you are getting length of the csv file string. What you need to do is split the data with the newline delimiter.
// sample from data
var data = `Date,Open,High,Low,Close,Volume
2013-12-20,9371.08,9413.09,9352.98,9400.18,161686900
2013-12-19,9279.68,9351.9,9257.24,9335.74,98276500`;
// split by \n (new line)
data = data.split('\n'); // now data is an array of rows
var finalObj = [];
// iterate over the rows
data.map(function(row){
var obj = {};
// row is a string separated by ','
row = row.split(','); // now row is an array
obj['date'] = row[0];
obj['open'] = row[1];
obj['high'] = row[2];
obj['low'] = row[3];
obj['close'] = row[4];
obj['volume'] = row[5];
finalObj.push(obj);
})
console.log(finalObj);
Output:
[
{
date:'Date',
open:'Open',
high:'High',
low:'Low',
close:'Close',
volume:'Volume'
},
{
date:'2013-12-20',
open:'9371.08',
high:'9413.09',
low:'9352.98',
close:'9400.18',
volume:'161686900'
},
{
date:'2013-12-19',
open:'9279.68',
high:'9351.9',
low:'9257.24',
close:'9335.74',
volume:'98276500'
}
]

Jquery - Counting JSON objects

Im building a chart system that will show me all data entries. I retrieve my data using ajax and I loop trough the data and group the results by colors (red, blue and yellow) and then divide them by months.
I setup base objects (dateCounts_Red, dateCounts_Blue and dateCounts_Yellow) so that by default it starts all months at 0. A counter would then add when it finds a match tot he apropriate color and month.
When I output my dateCounts I get:
{"2015":{"2015-12":1,"2015-10":null,"2015-08":null,"2015-11":null}}
{"2015":{"2015-12":0,"2015-10":null}}
{"2015":{"2015-12":0,"2015-10":null}}
Here is the code I have so far:
var dateCounts_Red = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Blue = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Yellow = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
data.d.results.forEach(function(element) {
var date = element.created_date.slice(0, 7);
var yr = date.slice(0, 4);
var Color = element.colorvalue;
if(Color == "red") {
dateCounts_Red[yr][date]++;
}
if(Color == "blue"){
dateCounts_Blue[yr][date]++;
}
if(Color == "yellow"){
dateCounts_Yellow[yr][date]++;
}
});
Red_yr_2015_data = [dateCounts_Red['2015']['2015-01'], dateCounts_Red['2015']['2015-02'], dateCounts_Red['2015']['2015-03'], dateCounts_Red['2015']['2015-04'], dateCounts_Red['2015']['2015-05'], dateCounts_Red['2015']['2015-06'], dateCounts_Red['2015']['2015-07'], dateCounts_Red['2015']['2015-08'], dateCounts_Red['2015']['2015-09'], dateCounts_Red['2015']['2015-10'], dateCounts_Red['2015']['2015-11'], dateCounts_Red['2015']['2015-12']];
Blue_yr_2015_data = [dateCounts_Blue['2015']['2015-01'], dateCounts_Blue['2015']['2015-02'], dateCounts_Blue['2015']['2015-03'], dateCounts_Blue['2015']['2015-04'], dateCounts_Blue['2015']['2015-05'], dateCounts_Blue['2015']['2015-06'], dateCounts_Blue['2015']['2015-07'], dateCounts_Blue['2015']['2015-08'], dateCounts_Blue['2015']['2015-09'], dateCounts_Blue['2015']['2015-10'], dateCounts_Blue['2015']['2015-11'], dateCounts_Blue['2015']['2015-12']];
Yellow_yr_2015_data = [dateCounts_Yellow['2015']['2015-01'], dateCounts_Yellow['2015']['2015-02'], dateCounts_Yellow['2015']['2015-03'], dateCounts_Yellow['2015']['2015-04'], dateCounts_Yellow['2015']['2015-05'], dateCounts_Yellow['2015']['2015-06'], dateCounts_Yellow['2015']['2015-07'], dateCounts_Yellow['2015']['2015-08'], dateCounts_Yellow['2015']['2015-09'], dateCounts_Yellow['2015']['2015-10'], dateCounts_Yellow['2015']['2015-11'], dateCounts_Yellow['2015']['2015-12']];
Im currently getting the following error from my Highcharts js:
Uncaught TypeError: Cannot set property 'index' of undefined
THis is preventing the chart system to work correctly the data returned is not being returned with it's expected data.
Here a full example to the issue https://jsfiddle.net/awo5aaqb/21/
Would anyone know what im missing?
Your date count objects have major structural flaw.
When you prettify them they look like:
var dateCounts_Blue = {
"2015": {
"2015-01": 0,
"2015-02": 0,
"2015-03": 0,
"2015-04": 0
},
"2015": {
"2015-05": 0
},
"2015": {
"2015-06": 0
},
"2015": {
"2015-07": 0
},
......
Object keys must be unique so these are clearly being repeated and the compiler will over write duplicates.
Fix the pattern that breaks away from the intended pattern grouping at the beginning
var dateCounts_Red = {
"2015":
{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
},
};
var dateCounts_Blue = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
}
};
var dateCounts_Yellow = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0}
};
Your data structure is flawed and such comparing values when doing the foreach loop becomes inconsistent because it compares it to multiple values, the above JSON is the fix for your problem.
Not quite codereview.stackexchange.com, but I heavily modified your javascript to make it work a bit better
$.ajax({
url: basePath,
dataType: 'json',
cache: false,
success: function(data) {
var counts = {};
data.d.results.forEach(function(element) {
// If you know it's all the same year, you could totally ignore this
var yr = element.created_date.slice(0, 4);
var month = parseInt(element.created_date.slice(5,7));
var color = element.colorvalue;
if (counts[color] === undefined) {
counts[color] = {};
}
if (counts[color][yr] === undefined) {
counts[color][yr] = {};
}
current_value = counts[color][yr][month];
if (current_value === undefined) {
// Doesnt exist yet, so add it
counts[color][yr][month] = 1;
} else {
// Exists, so increment by 1
counts[color][yr][month] = current_value + 1;
}
});
console.log(JSON.stringify(counts));
console.log(transform_series(counts['red']['2015']));
console.log(transform_series(counts['blue']['2015']));
console.log(transform_series(counts['yellow']['2015']));
var Options = {
chart: {
renderTo: 'myfirstchart',
type: 'column',
margin: 75,
options3d: {
enabled: true,
alpha: 25,
beta: 0,
depth: 70
}
},
title: {
text: "Test Highcharts"
},
subtitle: {
text: 'Test charts'
},
plotOptions: {
column: {
depth: 25
}
},
xAxis: {
categories: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]
},
yAxis: {
title: {
text: "Number of entries"
}
},
tooltip: {
headerFormat: '<b>{point.key}</b><br>',
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: {point.y} / {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
depth: 40
}
},
series: [{
name: 'Red',
color: 'red',
data: transform_series(counts['red']['2015']),
stack: '2015'
}, {
name: 'Blue',
color: 'blue',
data: transform_series(counts['blue']['2015']),
stack: '2015'
}, {
name: 'Yellow',
color: 'yellow',
data: transform_series(counts['yellow']['2015']),
stack: '2015'
}]
};
return new Highcharts.Chart(Options);
}
});
// this transforms the hash {10: 5, 11:1, 12:1} to get you all 12 months
// and returns an array of values [ 0, 0, 0, 0, 0 ... 5, 1, 1] that
// can be used in high charts
function transform_series(series) {
return Array.apply(null, Array(13)).map(function (_, i) {return (series[i] === undefined) ? 0 : series[i];}).slice(1,13);
}

Remove starting "0" values from Highcharts series array

I have following generated JavaScript-Code to display a chart with HighCharts:
<script type="text/javascript">
var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
var TaskChart; // Chart-Objekt
var TaskDuration = new Array();
// Save starting points to javascript variables for HighCharts
var startingUTC = 1288102643364;
TaskDuration = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,216,216,206,206];
for(var i = 0; i < TaskDuration.length; i++) {
if(TaskDuration[i] == 0) {
TaskDuration[i] = null;
}
}
</script>
<script type="text/javascript">
$j(document).ready(function() {
TaskChart = new Highcharts.Chart({
credits: {
enabled: false
},
chart: {
renderTo: "chart01",
defaultSeriesType: 'area',
zoomType: 'x',
spacingBottom: 250
},
title: {
text: "Task Duration"
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
week: '%e. %b %Y'
},
offset: 10,
startOnTick: true,
maxZoom: 7 * 24 * 3600000 // seven days
},
yAxis: {
title: {
text: "Duration"
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>';
}
},
plotOptions: {
area: {
stacking: 'normal',
lineColor: '#666666',
lineWidth: 1,
marker: {
lineWidth: 1,
lineColor: '#666666'
}
}
},
series: [
{
name: 'Duration',
pointStart: startingUTC,
pointInterval: 24*60*60*1000,
data: TaskDuration
}]
});
});
</script>
The problem is now that I want to remove all the "0" values from the beginning of the TaskDuration series array.
I try to set the values in the array to 'null':
for(var i = 0; i < TaskDuration.length; i++) {
if(TaskDuration[i] == 0) {
TaskDuration[i] = null;
}
}
But Highcharts still display the values in the chart.
How to prevent this behavior?
I also try to remove all values from the array until a value which is not "0". But with this approach the "startingUTC" is wrong. Maybe I have also to recalculate this value...
Regards,
Sandro
You need to remove elements not to set null, use this to remove zero element from array:
var myArray=[];
for(var i = 0; i < TaskDuration.length; i++) {
if(TaskDuration[i] != 0) {
myArray.push(TaskDuration[i]);
}
}
working JSfiddle
The problem is that you're using pointStart and pointInterval.
PointInterval will ignore your null points and will add points to the yAxis.
So, remove it.
series: [{
name: 'Duration',
data: TaskDuration
}]

Categories

Resources