Highcharts stacked column charts ( Parse json string for series) - javascript

I am getting following json string on Ajax call from javascript:-
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
I want to fill series of my highchart with the above given data. My requirement is to make "date" as X-Axis, "MsgType" as name and "Count" as data. I have for two objects when i needed to put count for MsgTypes. But here first i need to group data based on date and then need to place each MsgType with count in stack. Please help me with this as i am not able to figure out anything. Any help will be appreciated. I have implemented following for other scenario : -
Highcharts.chart('MP_Chart', {
chart: {
type: 'column'
},
title: {
text: 'Market Processes',
style: { "fontSize": "16px", "font-weight": "bold" }
},
credits: {
enabled: false
},
xAxis: {
categories: Date,
labels: {
style: {
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Total Queued messages',
style: {
fontWeight: 'bold'
}
},
stackLabels: {
enabled: false,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
itemStyle: {
fontSize: '12px',
font: '12pt',
}
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'Queued',
data: JSON.parse("[" + QueuedMPCount + "]")
}, {
name: 'Polled',
data: JSON.parse("[" + PolledMPCount + "]")
}]
});

Assuming I understood your question correctly, you need to pre-process the data a bit before passing it to Highcharts, for example, like this:
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
json = json.reverse() //reverse incomming json because highcharts expectes sorted dates
var series = [];
var names = [];
for (let i = 0; i < json.length; i++) { //loop through all incoming records
if (names.indexOf(json[i].MsgType) !== -1) { //check if we have a record with this messageType yet, if yes, add to that messagetypes array
series[names.indexOf(json[i].MsgType)].data.push({
x: new Date(json[i].date),
y: json[i].count
})
} else { //add new messageTypes
names.push(json[i].MsgType)
series.push({
name: json[i].MsgType,
data: [{
x: new Date(json[i].date),
y: json[i].count
}]
})
}
}
Coupled with this, I changed the xAxis type to datetime and series definition to take the variable we created earlier:
xAxis: {
type: 'datetime',
...
},
series: series
We then get this:
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
json = json.reverse()
var series = [];
var names = [];
for (let i = 0; i < json.length; i++) {
if (names.indexOf(json[i].MsgType) !== -1) {
series[names.indexOf(json[i].MsgType)].data.push({
x: new Date(json[i].date),
y: json[i].count
})
} else {
names.push(json[i].MsgType)
series.push({
name: json[i].MsgType,
data: [{
x: new Date(json[i].date),
y: json[i].count
}]
})
}
}
Highcharts.chart('MP_Chart', {
chart: {
type: 'column'
},
title: {
text: 'Market Processes',
style: {
"fontSize": "16px",
"font-weight": "bold"
}
},
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
labels: {
style: {
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Total Queued messages',
style: {
fontWeight: 'bold'
}
},
stackLabels: {
enabled: false,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
itemStyle: {
fontSize: '12px',
font: '12pt',
}
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: series
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="MP_Chart"></div>
JSfiddle working example: https://jsfiddle.net/ewolden/Lbyq4k0n/19/

Related

Highcharts not working in ie 11

Please don't say question already asked. I searched alot but faild.
The charts displaying perfectly in chrome, Firefox, and edge but not displaying in IE 11 and less.
here is my code
Highcharts.chart('teledensity', {
chart: {
type: 'line'
},
colors: [graph_data.series_color_one,graph_data.series_color_two,graph_data.series_color_three],
title: {
text: 'title'
},
credits:{
enabled:false
},
xAxis: {
type: 'category',
labels: {
autoRotation: [0],
style: {
fontSize: '11px',
fontFamily: 'Verdana, sans-serif'
}
},
categories: graph_categories,
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'title of y-axis'
},
stackLabels: {
enabled: true,
formatter: function(){
// var val = this.total;
// return (val/1000000).toFixed(2);
},
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
},
legend: {
align: 'center',
x: 20,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: 'white',
// borderColor: '#CCC',
// borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}',
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function(){
var val = this.y;
return (val/1000000).toFixed(2);
},
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
},
treshold: 1
}
},
series: [{
name: 'series one',
data: ['1','2','3'],
marker: {
lineWidth: 2,
lineColor: '#000',
fillColor: 'white'
}
}, {
name: 'series two',
data: ['1','2','3'],
marker: {
symbol: 'square'
},
}, {
name: 'series three',
data: ['1','2','3'],
marker: {
symbol: 'square'
},
}]
});
The problem was with the series you had given. I just changed your series as following.
series: [{
name: 'series one',
data: [1,2,3],
marker: {
lineWidth: 2,
lineColor: '#000',
fillColor: 'white'
}
}, {
name: 'series two',
data: [4,5,6],
marker: {
symbol: 'square'
},
}, {
name: 'series three',
data: [7,8,9],
marker: {
symbol: 'square'
},
}]
You can see that, you were given the data as a string data: ['1','2','3']. You can see the updated jsFiddle here.
Note: If jsFiddle is not loading in your IE browser, please try using draft version of jsFiddle.
I would also recommend you to style your container div, in your case teledensity with some height.
#teledensity {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto
}
Highcharts.chart('teledensity', {
chart: {
type: 'line'
},
title: {
text: 'title'
},
credits:{
enabled:false
},
xAxis: {
type: 'category',
labels: {
autoRotation: [0],
style: {
fontSize: '11px',
fontFamily: 'Verdana, sans-serif'
}
},
categories: ['2015','2016','2017'],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'title of y-axis'
},
stackLabels: {
enabled: true,
formatter: function(){
// var val = this.total;
// return (val/1000000).toFixed(2);
},
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
},
legend: {
align: 'center',
x: 20,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: 'white',
// borderColor: '#CCC',
// borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}',
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function(){
var val = this.y;
return (val/1000000).toFixed(2);
},
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
},
treshold: 1
}
},
series: [{
name: 'series one',
data: [1,2,3],
marker: {
lineWidth: 2,
lineColor: '#000',
fillColor: 'white'
}
}, {
name: 'series two',
data: [4,5,6],
marker: {
symbol: 'square'
},
}, {
name: 'series three',
data: [7,8,9],
marker: {
symbol: 'square'
},
}]
});
#teledensity {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto
}
<div id="teledensity"></div>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://highcharts.github.io/export-csv/export-csv.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
Solved...!
As I was creating graph dynamically and I used .map() which is ES6 not supported by IE11 so I modify code
From
graph_series_data_one = series_data_one ?>.reverse().map(x => parseFloat(x));
graph_series_data_two = series_data_two ?>.reverse().map(x => parseFloat(x));
To
graph_series_data_one = series_data_one ?>.reverse().map(function (x) { return parseFloat(x); });
graph_series_data_two = series_data_two ?>.reverse().map(function (x) { return parseFloat(x); });
and it worked.
Thanks.

highchart stacked column total data per categories

I want to get the total data per categories. The point.stackTotal only gives the total of the active data.
From the code example I pasted, I would like to know the total consumption per fruit. So even if I clicked Joe's name on the legend on upper right part (that makes all Joe's information on stacked chart inactive), I'd still know the total consumption of Apple (and any other fruits) of John, Jane, and Joe on mouseover each bar categories so apparently, what I am looking for is not the point.stackTotal.
$(function () {
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
});
I think that you should be able to show the total value for all visible and hidden columns for your category using stackLabels.formatter function. You can get more information about stackLabels in Highcharts API:
http://api.highcharts.com/highcharts/yAxis.stackLabels.formatter
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
},
formatter: function() {
var x = this.x,
value = 0;
series = this.axis.series;
Highcharts.each(series, function(s) {
value += s.userOptions.data[x];
});
return value;
}
}
Here you can see very simple example how you can achieve something similar to required chart:
http://jsfiddle.net/h8f30uwo/
Best,

Highcharts - center placement of columns

I have a Highcharts column chart and I am trying to reduce the distance between each column on the X axis whilst pulling them towards the center so that the columns appear more grouped.
So for example in my example above, the red and the blue column would be much closer together and positioned towards the center.
Below is my chart configuration. The seriesData parameter is just a custom object I pass in at render.
chartConfig.js
function chartConfig(seriesData) {
return {
barColor: seriesData.color,
data: seriesData,
credits: { enabled: false },
chart: {
width: seriesData.width,
defaultSeriesType: 'column',
backgroundColor: '#EAEFF6'
},
tooltip: { enabled: false },
colorAxis: {
dataClassColor: 'category'
},
colors: [],
legend: {},
title: {
useHTML: true,
text: (seriesData.name === 'n/a' || seriesData.name === 'N/A') ? '_' : seriesData.name,
style: {
color: (seriesData.name === 'n/a' || seriesData.name === 'N/A') ? '#E9EFF4' : '#666666',
fontSize: '14px',
fontFamily: 'Roboto',
fontWeight: 'bold',
paddingTop: '10px',
lineHeight: '1em'
},
align: 'center',
x: 0,
y: 2
},
plotOptions: {
column: {
stacking: 'normal',
animation: true,
borderColor: 'grey',
borderWidth: 0
},
series: {
borderRadius: 15,
dataLabels: {
enabled: false
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: [{
max: Math.max.apply(null, seriesData.scaleValues),
min: Math.min.apply(null, seriesData.scaleValues),
title: false,
minorGridLineColor: '#FFF',
gridLineColor: '#8E8E8E',
minPadding: 0,
tickPositions: (seriesData.scalePercentageValues || null),
labels: {
formatter: function () {
if (seriesData.usePercentage) {
return `${this.value} %`;
}
return this.value;
}
}
}],
xAxis: {
lineWidth: 0,
minorGridLineWidth: 0,
lineColor: 'transparent',
minorTickLength: 0,
tickLength: 0,
categories: seriesData.elements.map((x) => { return x.name; }),
labels: {
style: {
color: '#666666',
fontSize: '12px',
fontFamily: 'Roboto'
}
}
},
series: [{
dataLabels: {
style: {
fontSize: '12px',
fontWeight: 'normal',
textShadow: 'none',
color: 'black',
fontFamily: 'Roboto',
backgroundColor: 'blue'
},
enabled: true,
formatter: function () {
if (seriesData.usePercentage) {
return `${this.y}%`;
}
return this.y;
}
},
showInLegend: false,
name: 'Fill Series',
color: '#F2F6F9',
pointWidth: 28,
animation: true,
data: seriesData.elements.map((x) => {
return { name: x.name, y: x.value, color: x.color };
}),
borderRadiusTopLeft: 10,
borderRadiusTopRight: 10,
borderColor: '#C0C0C0',
borderWidth: '1'
}]
};
}
module.exports = chartConfig;
The only solution I have tried so far is to use pointPadding and groupPadding. However this does not seem to have the desired effect.

how to add stacklabel total on Highcharts columnrange?

I'm currently working with Highcharts columnrange and I need to add stack label on top of each column/each month in order to show Total Number of Hours our Store is being Opened.. But sadly, I've tried different ways and still no joy.
Here's the current jsfiddle that I have;
http://jsfiddle.net/rds_a/0mLa0yd5/2/
Here's the code;
$(function () {
$('#container').highcharts({
data: {
table: 'summary'
},
chart: {
type: 'columnrange'
},
colors: ['black', 'orange'],
title: {
text: 'Jackstone Store'
},
yAxis: {
allowDecimals: false,
title: {
text: 'Units'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
plotOptions: {
columnrange: {
grouping: false,
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black'
}
}
}
}
});
});

HighChart Stacked Column label issue

I have a chart with values that are uneven, ie: First value is 1315 and second value is 1, and so on, and when displaying the chart the labels are being overlapped. I have already searched in multiple forums but no one had the exact same problem. Here's a fiddle to see the problem: http://jsfiddle.net/6LutjLc3/
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Issue']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
formatter: function () {
return '<b>' + this.x + '</b><br/>' +
this.series.name + ': ' + this.y + '<br/>' +
'Total: ' + this.point.stackTotal;
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black'
}
}
}
},
series: [{
name: 'John',
data: [1235]
}, {
name: 'Toto',
data: [2]
}, {
name: 'Matt',
data: [1]
}, {
name: 'Jane',
data: [72]
}, {
name: 'Joe',
data: [3]
}]
});
});
What I need to code is to give the value 1 one box where the label fits in as like any other example in highchart.
Thanks in advance for your help!
If your client demands use of this style of graph you can get better looking results by modifying your dataLabel settings. Setting overflow to false and adding a formatter function that only returns a value if it's let's say at least 7% (or whatever percentage works best for you) of the current total will help. See the following:
dataLabels: {
enabled: true,
overflow: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black'
},
formatter: function () {
if (this.percentage >= 7) return this.y;
}
}
Fiddle here: http://jsfiddle.net/6LutjLc3/4/

Categories

Resources