Reputation: 175
I didn't see any solutions matching the exact scenario I was hitting in Highcharts so I'm posting my find here.
I have a stacked bar chart in Highcharts and needed the bars to be sorted by value greatest to smallest and maintain their category relationship. Normally the preferred solution would be to sort the data before sending it in to Highcharts but that wasn't an option in my scenario.
Credit to the original poster where I found the solution here
Upvotes: 2
Views: 2106
Reputation: 5826
You should perform the Chart.redraw()
only once after all setData operations are finished: http://jsfiddle.net/BlackLabel/2mLg7235/
$.each(series, function(seriesIndex, ser) {
(...)
ser.setData(data, false);
});
chartSource.redraw();
In your code the redraw happens after every setData
operation.
In my example the sorting function executes two times faster or so (thanks to this modification).
Upvotes: 6
Reputation: 175
This solution is slow to execute as it post-processes the chart data. If I find a way to speed it up, I will update the code posted here.
$(function () {
var chart;
var sortData = function(chartSource) {
var series = chartSource.series;
var axis = chartSource.xAxis[0];
var categories = [];
if($.isArray(series)) {
var ser = $.grep(series, function(ser, seriesIndex) {
return ser.visible;
})[0];
$.each(ser.data, function(dataIndex, datum) {
console.log(datum.category + ": " + datum.stackTotal);
var obj = {
name: datum.category,
index: dataIndex,
stackTotal: datum.stackTotal
}
categories.push(obj);
});
}
categories.sort(function(a, b) {
var aName = a.name.toLowerCase();
var bName = b.name.toLowerCase();
var aTotal = a.stackTotal;
var bTotal = b.stackTotal;
if(aTotal === bTotal) {
return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
} else {
return ((aTotal > bTotal) ? -1 : ((aTotal < bTotal) ? 1 : 0));
}
});
var mappedIndex = $.map(categories, function(category, index) {
return category.index;
});
categories = $.map(categories, function(category, index) {
return category.name;
});
console.log(categories);
console.log(mappedIndex);
axis.setCategories(categories);
$.each(series, function(seriesIndex, ser) {
var data = $.map(mappedIndex, function(mappedIndex, origIndex) {
return ser.data[mappedIndex].y;
});
ser.setData(data,false);
});
chartSource.redraw();
};
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
}
},
plotOptions: {
series: {
stacking: 'normal',
events: {
hide: function() { sortData(chart); },
show: function() { sortData(chart); }
}
}
},
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]
}]
}, function(chart) { sortData(chart); });
});
});
Upvotes: 0