Add dynamic series - javascript

I'm using Highcharts plugin and I have two array, here is an example of my arrays:
array1: Serie1, Serie2, Serie3
array2: 20, 30, 40
What I want to do is use this array in series options, array 1 as serie name and array 2 as serie value, I could do this manually but in the future maybe array1 is going to have more values and also array2.
$('#Chart').highcharts({
title: {
text: 'Example'
},
xAxis: {
labels:
{
enabled: false
}
},
yAxis: {
allowDecimals: true,
min: 0,
title: {
text: 'Results'
}
},
credits: {
enabled: false
},
legend: {
reversed: true
},
series: [{
name: array1[x],
data: array2[x].map(function (value) {
return Number(value);
})
}]
});
I tried using a for loop but I think that is not possible use this inside series option. Also I'm trying using a for loop outside the highcharts code and using a string var concatenating the above code but I'm not pretty sure about this, here is my code:
var constructor = "";
for (var i = 0; i < array1.length; i++) {
constructor += "name: '"+ array1[i] + "',";
constructor += "data: " + array2[i] + ".map(function (value) {"
constructor += "return Number(value);";
})

You could create the graph without series and then in a separate function you can do iterations on the array to get the data correctly and dynamically add the series in this way:
for (var i = 0; i < array1.length; i++) {
chart.addSeries({
name: array1[i],
data: [array2[i]]
}, false);
}
chart.redraw();
Not tested but the idea is that

Related

dynamically adding series to highcharts

I'm relative new to highcharts so I'm not that knowledgeable.
But what I am trying to do is that I am trying to dynamically create series with a name and some x, y values. To get the x and y values I use two dictionaries looking like this:
The X values. They are dates
The Y values. They are seconds
What I want to do is create a series that have the names of the keys and then they can have multiple points for x, y values.
So for example at "Fiber_Mätning" I have two values in the key in both dictionaries. What I want to do is that I create a series with the name "Fiber_Mätning", and then it should have two points where I give both x and y value.
So the 1st point in "Fiber_Mätning" would be x:"2020-10-28" y:"28800"
and the 2nd point in "Fiber_Mätning" would be x:"2020-10-29" y:"18000"
After that I would move on onto the next key in both dictionaries and do the same. So the way I create the series need to be a function that is dynamically creating series and the points depending on the amount of keys and values in the dictionaries.
Currently my highchart code looks like this:
$('#container').highcharts({
chart:{
type: 'column',
events:{
load: function(){
RedrawColumns(this)
},
redraw: function(){
RedrawColumns(this)
}
}
},
title:{
text: 'Time worked by {{user_to_show}}'
},
subtitle:{
text:'{{user_to_show}}´s flex time: '
},
tooltip:{
formatter: function (){
var text = 'Date: ' + this.x + '<br>' + 'Time: ' + secondsTimeSpanToHMS(this.y/1000) +
'<br>' +'Extra info:' + {{extra_info|safe}}[this.x];
return text;
}
},
xAxis:
{
categories: {{all_dates|safe}}
},
yAxis:
[{
title:
{
text: '' //If it isnt given '' it will display "value" so using '' to hide it
},
gridLineWidth: 1,
type: 'datetime', //y-axis will be in milliseconds
dateTimeLabelFormats:
{ //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
opposite: true
}],
plotOptions:
{
series:
{
dataLabels:
{
enabled: true,
formatter: function()
{
if( this.series.index == 0 )
{
return secondsTimeSpanToHMS(this.y/1000) ;
}
else
{
return this.y;
}
}
}
}
},
series:
[{
}]
});
});
(I am doing this with django, html and js)
If anything is unclear please say so and I will try to explain it in further detail.
Thanks in advance for any replies.
Here is my proposal for the solution. I think that everything is explained in the comments. If something is unclear, feel free to ask.
let data1 = {
Jarnvag_asdasd: ['2020-10-22'],
Fiber_Matning: ['2020-10-28', '2020-10-29'],
Fiber_Forarbete: ['2020-10-28', '2020-10-29'],
};
let data2 = {
Jarnvag_asdasd: [28800],
Fiber_Matning: [28800, 18000],
Fiber_Forarbete: [28800, 14400],
};
// The constructor to create the series structure
function CreateSeries(name, data) {
this.name = name;
this.data = data;
}
// series array
let series = [];
// Iterate through the data to concat them
for (let i in data1) {
let data = [];
data1[i].forEach((d, j) => {
data.push([d, data2[i][j]])
})
series.push(new CreateSeries(i, data))
}
Highcharts.chart('container', {
series: series
});
Demo: https://jsfiddle.net/BlackLabel/r7ame5gw/

JSON api timestamp + data parsing

I'm making a chart using Highcharts.js
The API I'm using has a different output than what Highchart uses.
Highchart reads JSON data as [timestamp, data]
which looks something like this: [1512000000000,171.85],
furthermore, the rest of the data is parsed within the same call.
Now MY Api outputs data by a single call for each timestamp (via url &ts=1511929853 for example
outputs {"ENJ":{"USD":0.02154}} (the price for that point in time)
Now here's where things get complicated. I would need to parse the price from a certain date, till now.
I've already made a ++ variable for the timestamp, but how would I include the timestamp and the price for that timestamp within the array for the data output.
It's a bit confusing, as the calls would have to be repeated so many times to draw a historical graph of the price. Some help would be appreciated. If you need more clarification, I'm right here.
Data is parsed via data function
full code here
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime()/1000);
function count() {
if (startDate != endDate) {
startDate++
}
else {
return false;
}
};
count();
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function (data) {
// Create the chart
var enjPrice = `${data.ENJ.USD}`;
console.log(enjPrice);
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data: JSON.parse("[" + enjPrice + "]"),
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
});
You can use spread operator, like this,
let var = [new Date().getTime(), { ...data }.ENJ.USD]
This will result [1512000000000, 171.85] as you expected.
You need to make different functions for getting the data and generating the chart. Below is an example of how would you do it.
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime() / 1000);
var data = [];
function count() {
if (startDate != endDate) {
data.push(getPrice(startDate));
startDate++;
} else {
generateChart();
}
};
count();
function getPrice(timestamp) {
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function(data) {
return [timestamp, data.ENJ.USD];
});
}
function generateChart() {
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data,
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
}
Though this is not the best way how you would do it but you get an idea.
I managed to solve the problem, by using a different API, which indexes data for past 30 days. I iterated into each index, 31, of them and grabbed the time and high(price) values and parsed them into a number since I was getting a "string" and then looped them into an array and put them into the final data [array]. just what I needed for the chart to work. If anyone needs any help just ask away. :) PS: Excuse the console.logs as I was using them to debug and test which helped me tremendously, you can remove them, as shall I
$.getJSON('https://min-api.cryptocompare.com/data/histoday?fsym=ENJ&tsym=USD', function(data) {
var x = `${data.Data[0].time}`;
var y = `${data.Data[0].high}`;
console.log(x);
console.log(y);
var tempData = [];
console.log(tempData);
for (var i = 0; i < 31; i++ ) {
var a = `${data.Data[i].time}`;
var b = `${data.Data[i].high}`;
function numberfy(val){
parseFloat(val);
}
a = parseFloat(a);
a = a * 1000;
b = parseFloat(b);
x = [a , b];
tempData.push(x);
};
data = tempData;
console.log(data.length);
Highcharts.stockChart('container', {

Highcharts - issue with tooltip formatting in synchronized charts

I am using synchronized charts using Highcharts, but I am having an issue with using the formatter function within the tooltip options. Each chart has different formatting requirements (% vs integer vs. float etc), but it seems to just take the last charts's formatting for each of the charts tooltips.
This was unexpected as I didn't have such issues for chart titles as well as y-axis formatting, which it picks up correctly. This is the code I currently have (abbreviated as it is quite lengthy otherwise):
for (var j = 0; j < json.data.length; j++) {
$('#highchart_metric' + i + '_').highcharts({
chart: {
type: 'area',
},
title: {
text: json.fmt[i].displayName,
},
xAxis: { // left out for brevity},
yAxis: {
labels: {
formatter: function () {
var label = this.axis.defaultLabelFormatter.call(this);
return numeral(label).format(json.fmt[i].format);
}
}
},
tooltip: {
formatter: function () {
return moment(this.x).format("MMM Do[,] YYYY") + ': <b>' + numeral(this.y).format(json.fmt[i].format) + '</b>';
}
}
series: [{ // left out for brevity }]
});
}
The json would be structured something along the lines of:
var json = {
data: [[/* data */][/* data */]];
fmt: [
{
col: "tfr",
displayName: "TFR",
fmt: "0,0.00"
},
{
col: "volume",
displayName: "Ticket Volume",
fmt: "0,0"
}
]
};
It looks like it is the issue with incorrect use of a callback and a for loop. Each formatter callback creates a closure which has access to the same variable i - which, when the loop ends, is equaled to json.data.length.
Use a forEach kind of loop which will create a seperate i variable for each chart.
Compare forEach http://jsfiddle.net/9eezsx7v/ with for loop http://jsfiddle.net/9eezsx7v/1/

Show only the MIN/MAX value on Y-AXIS with C3JS

I would like to have the y-axis only with the min/max values of my data.
I tried to use the d3 directive but without results.
I had a look at google but I didn't find an answer to achieve this behaviour.
Below the code:
$.getJSON('assets/json/chartc3.json', function(data)
{
scene=data;
var chart = c3.generate({
bindto: '#chartc3',
data:
{
json: scene,
keys:
{
x: 'round',
value: ['Marketable', 'Total Requested Capacity', 'Your Bid'],
},
types: {
Marketable: 'area'
},
colors: {
Marketable: '#A09FA2',
'Total Requested Capacity': '#272E80',
'Your Bid': '#8EBF60'
}
},
axis:
{
x: {
tick:
{
culling:
{
max: 10
}
},
type: 'category'
},
y:
{
min: 0,
padding : {
bottom : 0
},
tick:
{
values: [[0], [***d3.max(scene)]***],
format: function (d) { return d3.format(',f')(d) +' kWh/h' }
//or format: function (d) { return '$' + d; }
}
}
}.........
How could I achieve the result described above ? d3.max(scene) returns NaN.
Well the problem is scene is not an array its a json object.
var k = d3.max([1,5,2])
k will be 5
so you will need to pass an array of elements which constitute your y ordinals.
you need to use
d3.max(arr, function(d){return numberic value});
or
var arr = scene.map(function(d){return ...the number value..})
y:{
min:d3.min(arr),
max:d3.max(arr)
},
the function depends on the array element of your data.
I used a little function to calculate the max by myself.
var maxs=0;
for (var j=0; j<scene.length; j++) {
var maxtemp=Math.max(scene[j].Marketable, scene[j]['Your Bid'], scene[j]['Total Requested Capacity']);
maxs=Math.max(maxs, maxtemp);
}

HighCharts: How to read the JSON data

This is my JSON:
[{"name":"AniSig01",
"data":[["2013,06,11,16,06,55",14],
["2013,06,11,16,07,00",14],
["2013,06,11,16,07,06",15],
["2013,06,11,16,07,11",14]]},
{"name":"AniSig02",
"data":[["2013,06,11,16,06,55",0],
["2013,06,11,16,07,00",0],
["2013,06,11,16,07,06",0],
["2013,06,11,16,07,11",0]]},
{"name":"AniSig03",
"data":[["2013,06,11,16,06,55",6],
["2013,06,11,16,07,00",6],
["2013,06,11,16,07,06",7],
["2013,06,11,16,07,11",6]]},
{"name":"AniSig04",
"data":[["2013,06,11,16,06,55",13],
["2013,06,11,16,07,00",13],
["2013,06,11,16,07,06",14],
["2013,06,11,16,07,11",13]]}]
And my HighCharts code:
$(document).ready(function()
{
var options =
{
chart:
{
renderTo: 'container',
type: 'spline',
},
title:
{
text: 'Statistik',
},
xAxis:
{
type:'datetime',
},
yAxis:
{
title: { text: ''},
},
tooltip:
{
shared: true,
crosshairs: true,
},
plotOptions:
{
series:
{
marker: {enabled: false},
animation: false,
threshold: null
}
},
series:[]
};
$.getJSON('datgen/DatReq.txt',function(data)
{
$.each(data, function(key,value)
{
var series = { data:[]};
$.each(value, function(key,val)
{
if (key == 'name')
{
series.name = val;
}
else
{
$.each(val, function(key,val)
{
val[0] = 'Date.UTC(' + val[0] + ')';
series.data.push(val[0], val[1]);
});
}
});
options.series.push(value);
});
var linechart = new Highcharts.Chart(options);
});
});
But I see these 4 signals only as a point (vertical line) on the chart.
and the Tooltip didn't show the correct time (the x-value)!
Does anyone know what the problem is?
As you've discovered, your X values are at fault. Not only are they wrong (per the tooltip), but they seem to be the same wrong for each point (giving you a vertical line).
So, let's concentrate on the X values. What are they? Okay, times. At some point, you had to parse the times from the data source into Javascript. Where did you do that?
Here:
val[0] = 'Date.UTC(' + val[0] + ')';
There we go — Javascript functions simply don't work that way. You can't just shove code into a string and expect it to be executed.
Split val[0] on the comma character, and feed each part of the result into a real call to Date.UTC.

Categories

Resources