How to fill data dynamically in Highchart - javascript

I'm using below code to display bar chart, I don't know how to populate value dynamically in name and y field. I've name and y data in javascript array.
var productsName = [Laptop,Photoframe,PuzzleBox];
var productPrintCount = [56,24,10]
I don't want to hardcode name and y value in chart, I want to populate dynamically, can someone help how can I put these value in below chart?
JSFiddle
data: [{
name: 'Laptop',
y: 56
}, {
name: 'Photoframe',
y: 24
}, {
name: 'PuzzleBox',
y: 10
}]

var productsName = ['Laptop', 'Photoframe', 'PuzzleBox'],
productPrintCount = [56,24,10],
mappingDataFn = function () {
var resultData = [];
$.each(productsName, function (key, value) {
resultData.push({
'name': value,
'y': productPrintCount[key]
});
});
return resultData;
};
...
series: [{
name: 'Brands',
colorByPoint: true,
data: mappingDataFn()
}]
The idea:
mapping the data from a function.
here the jsfiddle

Related

Storing Highcharts in array issue

I am plotting a number of highcharts dynamically in a loop and pushing each highchart to an array. So that while clicking on an external button, I can export the charts. But while pushing charts to array, only the last entry is properly set with options.
i had a reference to a fiddle that suggests to clone the options. [https://jsfiddle.net/ndb21y1w/][2]
https://www.highcharts.com/forum/viewtopic.php?t=38574
The fiddle have same series data plotted on all the charts. How to solve this if the data is different for each chart populated. Thanks for any help in advance.
Adding more clarity to question :
The data is populated dynamically in loop. My code logic is like:
counter i;
setInterval(function() {
//logic to populated data...
//It is a multiline chart, so three sets of arrays are populated.
//filling data1[], data2[] and data3[] .
drawChart(data1, data2, data3);
if(condition true) clearInterval();
i++;
});
drawChart(data1, data2, data3) {
var chart = new Highcharts.Chart({
title: {
text: "title",
},
xAxis: {
categories: [1,2,3,4...],
},
series: [{
type: 'line',
data: data1,
}, {
type: 'line',
data: data2,
}, {
type: 'line',
data: data3,
},
});
chartArray.push(chart);
}
This chartArray is where I mentioned to get the last entry only properly.
To create a chart you have to pass an HTML element that will be a chart container. In your code that what's missing. Check the demo I have prepared to reproduce this issue: https://jsfiddle.net/BlackLabel/c60y1t2v/
Code:
var chartArray = [],
counter = 1,
dataArr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
containers = document.getElementById('containers');
function drawChart(data) {
var cnt = document.createElement('div'),
cntId = 'container' + counter++,
chart;
cnt.setAttribute('id', cntId);
containers.appendChild(cnt);
chart = new Highcharts.Chart(cntId, {
title: {
text: "title",
},
xAxis: {
categories: [1, 2, 3, 4],
},
series: [{
type: 'line',
data: data,
}]
});
return chart;
}
dataArr.forEach(function(data) {
var chart = drawChart(data);
chartArray.push(chart);
});
You need to define options each time you use a new chart. Reinitialize the OriginalOptions every time you create a new chart.
const options = [...Array(5)].map(() => {
const originalOptions = {
series: [{
data: [], // some random data
type: 'column'
}]
}
return Object.assign(originalOptions)
})
Fiddle
Updated:
For dynamically repopulating the chart, you have to initialize an empty chart and then add new series + redraw whenever your data is populated.
Your redraw function will look something like this:
var i = 0;
var data = [];
var chart = new Highcharts.Chart('container',{
series: []
});
var interval = setInterval(function() {
i++;
data[i] = [i*10 + 1, i*10+2, i*10+3];
drawChart(data[i]);
if(i > 2) clearInterval(interval);
},1000);
function drawChart(data) {
var series = {
type: 'line',
data: data
}
chart.addSeries(series, false);
chart.redraw();
}
See Updated Fiddle
To Print HTML as PDF you can use this software "wkhtmltopdf"
in Linux you need to use this command :
sudo apt-get install wkhtmltopdf
There are many library based on "wkhtmltopdf" in many languages so you can use it.
Library for PHP : https://github.com/mikehaertl/phpwkhtmltopdf
Store chart options in Array then map over to Initialize Highchart for each options.
var chartArray = [];
function drawChart(data1, data2, data3, i) {
// Create container for charts
const el = document.createElement('div');
document.body.appendChild(el).setAttribute("id", "container"+i);
// Create charts
var chart = new Highcharts.chart(el, {
series: [{
type: 'line',
data: data1,
}, {
type: 'line',
data: data2,
}, {
type: 'line',
data: data3,
}]
});
chartArray.push(chart);
console.log(chartArray);
}
var counter = 0;
var delayTime = 2000;
var timer = setInterval(function(){
var data1 = [30, 70, 50];
var data2 = [40, 70, 60];
var data3 = [10, 90, 20];
drawChart(data1, data2, data3, counter);
if(counter == 2){
clearInterval(timer);
}
counter++;
},delayTime);
<script src="https://code.highcharts.com/highcharts.js"></script>

Plotly.js - Get 4 y values for each x in a stacked bar chart

I have plotted a stacked bar chart for 4 data values that I have for every U.S. state. The CSV file I have been working off of looks like this:
Here's the JS code I wrote for the stacked bar chart:
// Read the data from CSV
d3.csv('https://raw.githubusercontent.com/krithikaragha/ResPy/master/Flask%20App/static/data/tobacco_use_by_state.csv', function(data) {
var chartData = []; // Array containing all the traces
function makeTrace(d) { // Function to make all 50 traces
return {
x: ["Smokes Everyday", "Smokes Somedays", "Former Smoker", "Never Smoked"],
y: [d.smokesEveryday, d.smokesSomedays, d.formerSmoker, d.neverSmoked],
name: d.state,
type: 'bar'
}
}
// Loop through all rows of the data
for(var i = 0; i < data.length; i++) {
// Call makeTrace to create a trace with index i
chartData.push(makeTrace(data[i]));
// Define a chart layout
var layout = {
barmode: 'stack',
width: 1200,
height: 800
};
// Plot the stacked bar chart
Plotly.newPlot('bar', chartData, layout);
}
});
The resulting stacked bar chart ended up looking like this:
The result I want to achieve is: I want each U.S. state to have its own bar which is stacked with respective 4 values (smokesEveryday, smokesSomedays, formerSmoker and neverSmoked)
Is there any way I can achieve this? Thanks in advance.
I figured it out myself.
Turns out, I had to make four separate traces for each of the 4 values I needed. So I looped through the data and created arrays for each column - smokedEveryday, smokesSomedays, formerSmoker and neverSmoked and a last array states to hold the state's abbreviations.
Then I created 4 individual traces with x-axis holding the states array and y-axis holding the respective smoking array.
Here's the modified code snippet:
// Read the data from CSV
d3.csv('https://raw.githubusercontent.com/krithikaragha/ResPy/master/Flask%20App/static/data/tobacco_use_by_state.csv', function(data) {
var states = [];
var smokesEveryday = [];
var smokesSomedays = [];
var formerSmoker = [];
var neverSmoked = [];
// Loop through all rows of the data
for(var i = 0; i < data.length; i++) {
states.push(data[i].abbr);
smokesEveryday.push(data[i].smokesEveryday);
smokesSomedays.push(data[i].smokesSomedays);
formerSmoker.push(data[i].formerSmoker);
neverSmoked.push(data[i].neverSmoked);
}
var smokesEverydayTrace = {
x: states,
y: smokesEveryday,
name: 'Smokes Everyday',
type: 'bar'
};
var smokesSomedaysTrace = {
x: states,
y: smokesSomedays,
name: 'Smokes Somedays',
type: 'bar'
};
var formerSmokerTrace = {
x: states,
y: formerSmoker,
name: 'Former Smoker',
type: 'bar'
};
var neverSmokedTrace = {
x: states,
y: neverSmoked,
name: 'Never Smoked',
type: 'bar'
};
var data = [neverSmokedTrace, formerSmokerTrace, smokesSomedaysTrace, smokesEverydayTrace];
var layout = {
barmode: 'stack',
title: "Percentage of Tobacoo Use by State",
xaxis: {
title: {
text: "Tobacco Use"
},
tickangle: 45
},
yaxis: {
title: {
text: "Percentage"
}
},
bargap: 0.4,
width: 1250,
height: 800
};
Plotly.newPlot('bar', data, layout);
});

Using different list for names of each point in highcharts in javascripts

I have three arrays coming from a json dictionary in js in this way:
var a=[]
var b=[]
var c=[]
var d = JSON.parse('{{ dictionary | safe}}');
for (var key in d) {
b.push(d[key]['score']);
a.push(key);
c.push(d[key]['text']);
}
I managed to have a chart using highchat is this way:
$('#container0').highcharts({
title: {
text: 'Daily News {{ name }}',
x: -20
},
subtitle: {
text: 'Source: News.',
x: -20
},
xAxis: {
categories: a
},
yAxis: {
title: {
text: 'Scores'
},
plotLines: [{
value: 0,
width: 1,
color: colors[3]
}]
},
series: [{
allowPointSelect: true,
name: 'news score',
data: b,
color: colors[2]
}]
});
When I mouse over/click on each pint, I get the value. I want to modify it in order to show the value from the array c. I tried many ways but nothing worked. I do appreciate your helps.
Name for a point can be set through setting property name for a data point. It can be done as presented in API reference, so each point is an object with name property, like:
series: [{
data: [{
name: 'Point 1',
y: 1
},
...
In your case array [nameString, value] will work as well.
series: [{
data: [
['Point 1', 1],
...
JSFiddle: http://jsfiddle.net/fnmncx6h/
So, for your code you could use something like this:
var a=[]
var b=[]
var d = JSON.parse('{{ dictionary | safe}}');
for (var key in d) {
b.push([d[key]['text'], d[key]['score']]);
a.push(key);
}
and later use b as data for series.
To set tooltip's text you can use one of many formatting functions provided in API - e.g. headerFormat, pointFormatter.

javascript associative array, looping, and / or scope issue with Highcharts JSON call

I have a javascript associative array issue, looping issue, and / or scope issue. I'm trying to call data from a postgresql database, parse it, and implement it in a Highchart.
The data consists of five series with five items (columns / fields) each:
[Object, Object, Object, Object, Object]
Opened, the fifth object looks like:
4: Object
acronym: "1"
current: "3.4"
id: 1
name: "a"
pc1: "2.5"
previous: "2.4"
url: "http://myhost:3000/series/1.json"
__proto__: Object
length: 5
__proto__: Array[0]
After parsing, I get a sequence of objects:
[Object]
[Object]
[Object]
[Object]
[Object]
Which consist of the parsed data expect, i.e., a k:v pair [name: "a", y: 2.5]:
[Object]
0: Object
name: "a"
y: 2.5
__proto__: Object
length: 1
__proto__: Array[0]
However, what I need is an array of objects:
[{name: "a", y: 2.5}, {name: "b", y: 3.0}, {name: "c", y: 1.0}, {name: "d", y: 2.0}, {name: "e", y: 3.2}]
If I insert "dummy" data - below - the chart renders correctly, so the issue's with my code, specifically, the creation of the array and its availability outside the JSON function.
[{name: 'name1', y: 2.5}, {name: 'name2', y: 4.0}];
Any and all help would be appreciated. Here's the entire javascript code for the Highchart - with notes where the issues are.
$(document).ready(function () {
var options = {
chart: {
renderTo: 'container',
type: 'column',
},
title: {
text: 'The Conference Board'
},
legend: {
enabled: false
},
subtitle: {
text: 'Leading Indicators '
},
xAxis: {
type: 'category',
labels: {
rotation: -45,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
credits: {
enabled: false
},
yAxis: {
title: {
text: 'Percent Change Year / Year'
},
},
series: [{
data: [] // dummy code inserted here makes the chart render
}]
};
url = "http://myhost:3000/series";
$.getJSON(url, function (series) {
console.log(series); // five series of five k:v pairs each
$.each(series, function(key_i, val_i) { // parsing to a single k:v (name: value) pair
data = []; // I'm trying to create an array of objects // [{},{},{},{},{}]
data.push({ // for insertion into the var options.series.data above
name: val_i.name,
y: parseFloat(val_i.pc1)
});
options.series[0].data = data;
console.log(options.series[0].data); // getting all k:val_i pairs sequentially; however, not as an array of objects
});
options.series[0].data = data;
console.log(options.series[0].data); // only getting the last k:v pair and the chart doesn't render
});
console.log(options.series[0].data); // an empty array []
var chart = new Highcharts.Chart(options);
});
Again, thank you in advance for your help with this. I've been working on it for days.
try
$.getJSON(url, function (series) {
options.series[0].data = $.map(series, function(val) {
return { name: val.name, y: parseFloat(val.pc1) };
});
new Highcharts.Chart(options);
});
Update fix your existing each loop
$.getJSON(url, function (series) {
var data = [];
$.each(series, function(val) {
data.push({ name: val.name, y: parseFloat(val.pc1) });
});
options.series[0].data = data;
new Highcharts.Chart(options);
});
I believe something like:
var jsonArray = yourArray.map(function(item) { return JSON.stringify(item); });
will handle the conversion to JSON for you.

Highcharts: Plot yAxis values starting from a specific range

I am using highstocks and I am wondering if there is anyway I can plot the y values in a column series starting from an arbitrary number. For example. I have a column series called NU (New Users) with its first entry yAxis value of 1,000. Currently, that first entry is plotted on the yAxis from range [0, 1,000]. But instead I would like it to be plotted from [5,000, 6,000].
The reason I want this is because NU is essentially apart of another column called DAU (Daily Active Users), and I want it to be shown up as so. The first entry of the DAU column series has a Y value of 6,000, and 6,000 - 1,000 is 5,000; therefore I would like this entry of NU to start at 5,000.
Here is what I have so far
http://jsfiddle.net/6JACr/2/
I was going to plot DAU as (Original DAU - NU), and stack NU on top of DAU, but that would mean the series holds an incorrect value for DAU.
Here is my code
$(document).ready(function() {
var all_series = [];
var accu_series;
var accu_data = [];
var pccu_series = [];
var pccu_data = [];
var dau_series;
var dau_data = [];
var nu_series;
var nu_data = [];
function draw_charts() {
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1,
buttons: [{
type: 'week',
count: 1,
text: '1w'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'month',
count: 3,
text: '3m'
}, {
type: 'month',
count: 6,
text: '6m'
}, {
type: 'ytd',
text: 'YTD'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}]
},
plotOptions: {
column: {
grouping: false
}
},
yAxis: [{
// Primary Y-Axis
labels:{
align:'right',
x:-10
},
lineWidth : 1,
offset : 0
}, {
// Secondary Y-Axis
opposite: true
}],
series : all_series
});
}
//Function that takes a record and fills the series data with that record
function fill_data(index, record) {
var date = new Date(record['dailyDate']);
var utc_date = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
accu_data[index] = [utc_date, parseFloat(record['accu'])];
dau_data[index] = [utc_date, parseFloat(record['dau'])];
nu_data[index] = [utc_date, parseFloat(record['users'])];
}
// //Function that sets up the series data for plotting
function fill_series() {
dau_series = {
name: "DAU",
type: "column",
data: dau_data,
stack: 0
};
all_series[0] = dau_series;
nu_series = {
name: "NU",
type: "column",
data: nu_data,
stack: 0
};
all_series[1] = nu_series;
}
//Pull data from API, format it, and store into the series arrays
(function() {
var result = '[{"accounts":"1668","accu":"568","activePayingRate":"1.97757","activePayingUsers":"854","activeUsers":"4905","area":"1","arpu":"34.6908","company":"45","dailyDate":"2013-08-06","dau":"6000","lost":"87","newUser":"0","paying":"96","payingRate":"1.53724","pccu":"747.0","registration":"572","sales":"3305.01","server":"1","users":"1000"},{"accounts":"1554","accu":"497","activePayingRate":"2.18398","activePayingUsers":"833","activeUsers":"4533","area":"1","arpu":"34.7479","company":"45","dailyDate":"2013-08-07","dau":"5873","lost":"89","newUser":"0","paying":"96","payingRate":"1.68568","pccu":"759.0","registration":"483","sales":"3300.04","server":"1","users":"1209"}]';
var json_result = JSON.parse(result);
$.each(json_result, function(index, record) {
fill_data(index,record);
});
fill_series();
draw_charts();
})();
});
You can use low property for column, for example: http://jsfiddle.net/6JACr/4/
To display proper tooltip, add extra property like val and use pointFormat to display it.
Note: when dataGrouping will be used custom properties are removed, in that case I advice to create your own tooltip formatter, to display what you need.

Categories

Resources