Showing tooltip with two or more stack columns - highcharts

When I select a column, I want to show a tool-tip with only the values for the specific stack selected, but I'm showing all values for the two stacks (2012 and 2013).
Can I configure the tool-tip to show only one stack value?
If I cannot do it, how can I show the stack label into the tool-tip(2012 or 2013)?
I tried to use point.series.stack, but I'm getting a undefined value. Is it possible?
Code to show a tooltip over a stacked chart:
tooltip: {
formatter: function() {
var s = '<b>'+ this.x +'</b>';
$.each(this.points, function(i, point) {
s += '<br/>'+ point.series.name +': '+point.series.stack+':'+ point.y +'m';
});
return s;
},
shared : true
}
The complete code
Thanks for your help.
Hi again
I followed your advice in order to show only the values for the same stack.
I have this formatter code:
tooltip: {
formatter: function() {
var tip = '<b>'+ this.x ;
var stackSelected = this.point.series.options.stack;
tip += '/'+stackSelected+'</b>';
$.each(this.series.chart.series, function(i, s) {
if(s.options.stack == stackSelected){
tip += '<br/><br/>';
tip += '<b>'+s.name+' : </b>'+s.yAxis;
}
});
return tip;
},
shared : false
}
But I have problems in order to get the value for each serie.
Could you help me on this please?
Thanks in advance
I forgot the complete code: http://jsfiddle.net/Kqumw/4/

I can get that i want
Thanks for your tips.
This is my tooltip code:
tooltip: {
formatter: function() {
var tip = '<b>'+ this.x ;
var stackSelected = this.point.series.options.stack;
var categorySelected = this.point.category;
tip += '/'+stackSelected+'</b>';
tip += '<br/><br/>';
var index = 0;
$.each(this.series.chart.series, function(i, s) {
if(s.options.stack == stackSelected){
$.each(s.data, function(j, point){
if(point.category == categorySelected)
tip += '<b>'+s.name+' : </b>'+point.y+'<br>';
});
}
});
return tip;
},
shared : false
}
This is the complete code http://jsfiddle.net/Kqumw/5/

It's not possible to show different tooltip for the same category when shared is set for tooltip. If you want to show stack in tooltip, use point.series.options.stack, see: http://jsfiddle.net/Kqumw/1/
If you want to show only one stack (full stack for hovered point), then disable shared (shared: false) and find on your own corresponding points for the same category and the same stack (by comparing category index/name from points and stack id from series).

Related

Highcharts skipping shared tooltip points for large data sets

Seems like Highcharts is skipping a few data points in the shared tooltip for high number of data points (2500+).
I am trying to render a dual axis chart with 2500+ data points for 4 series - using Highcharts. I am also using a shared tooltip option to render my custom tooltip html. But at times Highcharts skips 1 or 2 data points in the tooltip. For example, when I slowly hover over each of the points from left to right, then I am supposed to see '1st April' after '31st March'. But instead, I see '2nd April'. Is it a bug? Or am I missing something? (I have verified that all the dates are present in the categories passed to the Highcharts.)
tooltip: {
borderColor: '#ccc',
backgroundColor: 'transparent',
borderWidth: 0,
shadow: false,
shared: true, //show all series values together
useHTML: true,
// hideDelay: 50000,
formatter: function() {
if (props.config.type == 'pie') {
return 'Value : ' + this.y;
} else {
let html = '<div class="fixed-tooltip">';
html += formatTooltipDate(this.x);
if (this.points &&
this.points.length > 1 &&
props.config.type != "combination") { //multiple series*(see note below)
//*combination series are having 1 point, so handled in the else section as single series.
let dateIndex = props.config.data.categories.indexOf(this.x);
console.log(" date ", this.x);
console.log(" dateIndex ", dateIndex);
if (props.config.type == "dual") {
let dualAxisTitles = props.config.dualAxisTitles;
html += formatDualSeriesTooltipData(this.x, dateIndex, this.points, dualAxisTitles);
} else {
html += formatMultiSeriesTooltipData(this.x, dateIndex, this.points);
}
} else { //single series
//for combination charts have a custom tooltip logic
if (props.config.type == "combination") {
let dateIndex = props.config.data.categories.indexOf(this.x);
html += formatMultiSeriesTooltipData(this.x, dateIndex, props.config.data.series);
} else {
let seriesColor = this.points[0].point.series.color;
let seriesName = this.points[0].point.series.name;
let value = this.points[0].y;
html += formatSingleSeriesTooltipData(value);
}
}
html += '</div>';
return html;
}
}
}
Expected to see a tooltip for "1st April" data point, after "31st March". Instead seeing tooltip for "2nd April" data point.
The points are skipped if there is no enough space for them in the plot area (1px for 1 point). The solution is to set a adequate chart width:
chart: {
width: 1000
},
Live demo: http://jsfiddle.net/BlackLabel/yjk0ta43/
API: https://api.highcharts.com/highstock/chart.width

Highcharts - Stack Graph Display Average of all values

I am using highcharts for statistical data displaying. I want to display , on the stack label , the average of all the values .
Below is what i am doing but i cant seem to get it right :
yAxis: {
min: 0,
title: {
text: 'Task'
},
stackLabels: {
style: {
color: 'black'
},
enabled: true,
formatter: function() {
return (this.axis.series[1].yData[this.x]).toPrecision(2) + '%';
}
}
},
The above only takes the last value on the stack and shows the percentage. For instance , if the last value is 50 , the above displays 50% as the stack value . I want to take an average of all the values. Any help would be appreciated.
If you want to show any stack's percentage mean if your stacked column has two stack A-5 and B-10 , then the % of B in column is 66% and % of A is 33%. If you want to show that use following in formatter function ( refer This Fiddle Link)
formatter: function() {
return (this.axis.series[1].yData[this.x] / this.total * 100).toPrecision(2) + '%';
}
Updating as per OP 's comment Refer Working fiddle here
Use following code : Make your data in a variable and calculate the sum
var seriesData = [{
name: 'Incomplete',
data: [1, 3, 4, 7, 20]
}, {
name: 'Complete',
data: [3, 4, 4, 2, 5]
}];
var total = 0;
$.each(seriesData,function(item){
$.each(seriesData[item].data,function() {
total += this;
});
});
And then use following in stacklabel formatter :
formatter: function() {
return ( this.total/ total * 100).toPrecision(2) + '%';
}
series:seriesData
hope it helps :)
This doesn't seem to be as easy as it should be.
I would accomplish this by pre-processing the data to generate an array of averages, and then referencing that array from the stackLabels formatter function.
Example, build the averages (assumes array 'data' with sub array for each series data values):
var sum = 0;
var averages = [];
var dataLen = data.length;
$.each(data[0], function(x, point) {
sum = 0;
for(var i = 0; i < dataLen; i++) {
sum += data[i][x];
}
averages.push(sum/dataLen);
})
And then in the formatter:
yAxis : {
stackLabels: {
enabled: true,
formatter: function() {
return Highcharts.numberFormat(averages[this.x],2);
}
}
}
Example:
http://jsfiddle.net/jlbriggs/vatdrecb/
If I could find a way to get a reliable count of the points in each stack, you could just use
return this.total/countOfPoints;
in the formatter without needing to build an array, but I can't seem to reliably get that count.

Set navigator min zoom

I'm trying to set the min zoom (max range) of my chart. Basically I'm trying to do the opposite of the minRange property. I'm struggling for a while with this problem. I have a "solution", but I don't like it, this solution allow the user to choose a range greater then the "max range", and immediately correct it.
POSSIBLE SOLUTION
$(function() {
var lastMin;
var lastMax;
var maxRange = 12 * 30 * 24 * 3600 * 1000; //12 month
$('#container').highcharts('StockChart', {
scrollbar: {
liveRedraw: false
},
xAxis: {
events: {
afterSetExtremes: function(e) {
var max = this.max,
min = this.min;
if (lastMin && lastMax) {
if(max-min > maxRange) {
if (min < lastMin) {
min = max - maxRange;
} else {
max = min + maxRange;
}
}
}
var x = this;
setTimeout(function(){
x.setExtremes(min,max); //chart xAxis
}, 1);
lastMin = min;
lastMax = max;
}
}
},
rangeSelector: {
selected: 1
},
series: [{
name: 'USD to EUR',
data: usdeur
}]
});
});
I want to block the user from choosing a range greater than the allowed, in other words, block the navigator when it's too big
I'm also following this issue, I tried all the proposed solution, but I'm having errors ("Uncaught ReferenceError: Highcharts is not defined")
Thanks Sebastian!
I managed to find a solution (fiddle) wrapping the "render" function. Doing that I managed to really set a "min zoom" on the navigator bar.
$(function() {
var lastX0;
var lastX1;
var maxRange = 100; //100 pixels
(function (H) {
H.wrap(H.Scroller.prototype, 'render', function (proceed) {
console.log(arguments)
if(arguments[4] - arguments[3] > maxRange + 2) {
if (arguments[3] < lastX0) {
arguments[3] = lastX0;
} else {
arguments[4] = lastX1;
}
}
proceed.apply(this, [].slice.call(arguments, 1));
lastX0 = arguments[3];
lastX1 = arguments[4];
});
}(Highcharts));
$('#container').highcharts('StockChart', {
scrollbar: {
liveRedraw: true
},
series: [{
name: 'USD to EUR',
data: usdeur
}]
});
var highchart = $('#container').highcharts();
var extremes = highchart.xAxis[0].getExtremes();
var rangeTotal = extremes.max - extremes.min;
var f = maxRange / $('#container').width();
highchart.xAxis[0].setExtremes(extremes.max - (f * rangeTotal), extremes.max);
});
In the sample code I'm used a fixed amount of pixels, but in my real application i'm making it dynamic. I making this, because I can't use the data grouping property in the software that I'm working, and since the minimum size of a bar in a chart is 1 pixel (obviously) highcharts hide some bars (or points).
I'm setting the minimum zoom so all bar in the displayed range are visible , since the user can't display a higher range in the x Axis the "hidden" bar "problem" (is an awesome feature, but I can't make use of it) won't happen

Pie chart legend shows empty values

Using dot net highcharts and the label formatter to only display certain items in the legend, it displays values that have been returned as ''.
.SetLegend(new Legend { Enabled = true, LabelFormatter = "function() { if (this.y >= 5) { return this.name; } else { return ''; } }" })
You can disable default legend and create your own as HTML. Then you can control which point should be or not displayed.
Example: http://jsfiddle.net/N3KAC/1/
$legend = $('#customLegend');
$.each(chart.series[0].data, function (j, data) {
$legend.append('<div class="item"><div class="symbol" style="background-color:'+data.color+'"></div><div class="serieName" id="">' + data.name + '</div></div>');
});
$('#customLegend .item').click(function(){
var inx = $(this).index(),
point = chart.series[0].data[inx];
if(point.visible)
point.setVisible(false);
else
point.setVisible(true);
});
The formatter only formats the text that gets displayed - it does not determine whether or not there is a legend entry for a series.
What you need is the showInLegend property, and you will need to run your check on the series object, not on the legend.
Reference:
http://api.highcharts.com/highcharts#plotOptions.series.showInLegend

How to auto-format dates in custom tooltip formatter?

Highcharts does a great job auto-formatting dates both on the x-axis and in tooltips. Unfortunately I need a custom function to format my y-values, and /plotOptions/line/tooltip/pointFormat accepts only a format string and not a function, so I have to set /tooltip/formatter instead. How do I get hold of the formatted date (e.g. Oct'13 or 20. Oct) as shown on the x axis? I don't seem to have access to point.key from there, only the raw millis value.
http://jsfiddle.net/9Fke4/
You can use dateFormat()
tooltip: {
formatter: function() {
return '<b>' + Highcharts.dateFormat('%b\' %d',this.x) + ':</b> ' + this.y;
}
},
http://jsfiddle.net/9Fke4/1/
FWIW, this was answered in a Highcharts issue on Github
formatter: function() {
var tooltip = this.series.chart.tooltip,
item = this.point.getLabelConfig(),
header = this.series.chart.tooltip.tooltipFooterHeaderFormatter(item);
return header + this.y;
}
Corresponding fiddle:
http://jsfiddle.net/9Fke4/12/
If you are using a shared series:
tooltip: {
formatter: function (tooltip) {
var header,
s = [];
$.each(this.points, function(i, point) {
if(header == null) {
var config = point.point.getLabelConfig();
header = tooltip.tooltipFooterHeaderFormatter(config);
}
s.push(point.y);
});
return header + s.reverse().join('<br>');
},
shared: true
}
conver the raw milliseconds to a date object using
var currentDate = new Date (tome in milliseconds)
in the tootip/formatter function you have defined.
this will give you good control over the date. you can use currentDate.getMonth(), getDate(), getDay(), etc methods to get the information you want from that date.
build a string with the above info and return.
I hope this will help you.
The solution I ended up with is to pre-format the y-values and store them as part of the series data; the pre-formatted values can then be referenced from the tooltip headerFormat and pointFormat, where they can be used along with {point.key}, which contains the auto-formatted date (and which is not available when providing a custom tooltip formatter):
http://jsfiddle.net/uG3sv/

Resources