Highchart show/hide y axis with multiple associated series - highcharts

I'm working with Highchart. I've got a multiple series graph in which several series can be associated to the same y-axis. The association is based on the measurement unit, which is also the y-axis id. Series are added dynamically.
Each y-axis has setExtremes() different than null and for this reason I have encountered one problems that it seems I can't resolve.
When hiding a series. I want the associative y-axis to be visible until all the series associated to that specific axis are hidden also. At the moment I was able just to hide the y-axis once one of the series is set to series.hide()
The used code is presented below. And can be accessed in jsfiddle through this like: http://jsfiddle.net/39xBU/134/ .
$(function () {
//creates chart options
var options = {
chart: {
renderTo: 'container',
zoomType: 'xy'
},
title: {
text: 'Axis manipulation'
},
xAxis: [{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
}],
yAxis: [{ // Primary yAxis
id:'°C',
labels: {
formatter: function() {
return this.value +'°C';
},
style: {
color: '#89A54E'
}
},
title:{
text:''
},
opposite: true,
showEmpty: false
}, { // Secondary yAxis
id:'mm',
gridLineWidth: 0,
labels: {
formatter: function() {
return this.value +' mm';
},
style: {
color: '#4572A7'
}
},
title:{
text:''
},
showEmpty: false
}],
tooltip: {
formatter: function() {
var unit = {
'Rainfall': 'mm',
'Temperature': '°C',
'Sea-Level Pressure': 'mb'
}[this.series.name];
return ''+
this.x +': '+ this.y +' '+ unit;
}
},
legend: {
layout: 'vertical',
align: 'left',
x: 120,
verticalAlign: 'top',
y: 80,
floating: true,
backgroundColor: '#FFFFFF'
},
series: []
};
// Adds series to the chart. i do this because in the real application I add data dinamically
options.series.push({
name: 'Rainfall',
color: '#4572A7',
type: 'spline',
yAxis: getAssociativeYAxisIndex('mm', options.yAxis),
data: [149.9, 171.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 195.6, 154.4]
});
options.series.push({
name: 'Sea-Level Pressure',
type: 'spline',
color: '#4572A7',
yAxis: getAssociativeYAxisIndex('mm', options.yAxis),
data: [116, 116, 115.9, 115.5, 112.3, 109.5, 109.6, 110.2, 113.1, 116.9, 118.2, 116.7],
marker: {
enabled: false
},
dashStyle: 'shortdot'
});
options.series.push({
name: 'Temperature',
color: '#89A54E',
type: 'column', // date is not shown only if it is 'spline'
yAxis:getAssociativeYAxisIndex('°C', options.yAxis),
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
});
var chart = new Highcharts.Chart(options);
//after rendering I set axis limits, based on their measurement unit.
var yAxis1 = chart.get('mm');
yAxis1.setExtremes(0, 200);
var yAxis2 = chart.get('°C');
yAxis2.setExtremes(0, 40);
// hide Rainfall button
$("#b1").click(function(){
chart.series[0].hide()
chart.yAxis[1].update({
labels: {
enabled: false
},
title: {
text: null
}
});
});
// hide sealevel button
$("#b").click(function(){
chart.series[1].hide()
chart.yAxis[1].update({
labels: {
enabled: false
},
title: {
text: null
}
});
});
// delete rainfall button
$("#b2").click(function(){
chart.series[0].remove();
chart.yAxis[1].setExtremes(null, null);
});
// delete sea-level button
$("#b3").click(function(){
chart.series[1].remove();
chart.yAxis[1].setExtremes(null, null);
});
//get's series associatie axis
function getAssociativeYAxisIndex(seriesMeasureUnit, yAxis) {
var axisIndex = -1;
$.each(yAxis, function (index, axes) {
if (seriesMeasureUnit == axes.id) {
axisIndex = index;
return false;
}
});
return axisIndex;
};
});
Any suggestions to this matter would be very useful.

You can simply check if all of series are hidden, this way: http://jsfiddle.net/39xBU/135/
And code:
new function to make it easy to read:
function hideShowAxis(series) {
var axis = series.yAxis,
show = false;
$.each(axis.series, function (i, e) {
if (e.visible) {
show = true;
}
});
axis.update({
labels: {
enabled: show
}
});
}
and execute:
// hide Rainfall button
$("#b1").click(function () {
chart.series[0].hide()
hideShowAxis(chart.series[0]);
});
// hide sealevel button
$("#b").click(function () {
chart.series[1].hide()
hideShowAxis(chart.series[1]);
});

Related

highchart- how do I hide y-axis, when y-axis is set with max and min limits

I am working with highcharts and I have to set min and max limits on y-axis but when I try to hide the series by clicking on legends y-axis does not disappear as shown in the snippet. Temperature y-axis does not hide when its corresponding series get disappeared on clicking legend. Issue is that in the code
showEmpty for y-axis is set to false which make the other axis without the max and min values dissaper on click. I tried to find out the solution in Highchart documentation but have not found anything usefull in regard to my issue,
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
zoomType: 'xy'
},
title: {
text: 'Average Monthly Weather Data for Tokyo'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: [{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
}],
yAxis: [{ // Primary yAxis
labels: {
formatter: function() {
return this.value +'°C';
},
style: {
color: '#89A54E'
}
},
title: {
text: 'Temperature',
style: {
color: '#89A54E'
}
},
opposite: true,
showEmpty: false,
max: 100,
min:0,
}, { // Secondary yAxis
gridLineWidth: 0,
title: {
text: 'Rainfall',
style: {
color: '#4572A7'
}
},
labels: {
formatter: function() {
return this.value +' mm';
},
style: {
color: '#4572A7'
}
},
showEmpty: false
}, { // Tertiary yAxis
gridLineWidth: 0,
title: {
text: 'Sea-Level Pressure',
style: {
color: '#AA4643'
}
},
labels: {
formatter: function() {
return this.value +' mb';
},
style: {
color: '#AA4643'
}
},
opposite: true,
showEmpty: false
}],
tooltip: {
formatter: function() {
var unit = {
'Rainfall': 'mm',
'Temperature': '°C',
'Sea-Level Pressure': 'mb'
}[this.series.name];
return ''+
this.x +': '+ this.y +' '+ unit;
}
},
legend: {
layout: 'vertical',
align: 'left',
x: 120,
verticalAlign: 'top',
y: 80,
floating: true,
backgroundColor: '#FFFFFF'
},
series: [{
name: 'Rainfall',
color: '#4572A7',
type: 'column',
yAxis: 1,
data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}, {
name: 'Sea-Level Pressure',
type: 'spline',
color: '#AA4643',
yAxis: 2,
data: [1016, 1016, 1015.9, 1015.5, 1012.3, 1009.5, 1009.6, 1010.2, 1013.1, 1016.9, 1018.2, 1016.7],
marker: {
enabled: false
},
dashStyle: 'shortdot'
}, {
name: 'Temperature',
color: '#89A54E',
type: 'spline',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}]
});
});
});
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
You can avoid this issue if you use softMin and softMax instead of min and max.
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
zoomType: 'xy'
},
title: {
text: 'Average Monthly Weather Data for Tokyo'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: [{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
}],
yAxis: [{ // Primary yAxis
labels: {
formatter: function() {
return this.value +'°C';
},
style: {
color: '#89A54E'
}
},
title: {
text: 'Temperature',
style: {
color: '#89A54E'
}
},
opposite: true,
showEmpty: false,
softMax: 100,
softMin:0,
}, { // Secondary yAxis
gridLineWidth: 0,
title: {
text: 'Rainfall',
style: {
color: '#4572A7'
}
},
labels: {
formatter: function() {
return this.value +' mm';
},
style: {
color: '#4572A7'
}
},
showEmpty: false
}, { // Tertiary yAxis
gridLineWidth: 0,
title: {
text: 'Sea-Level Pressure',
style: {
color: '#AA4643'
}
},
labels: {
formatter: function() {
return this.value +' mb';
},
style: {
color: '#AA4643'
}
},
opposite: true,
showEmpty: false
}],
tooltip: {
formatter: function() {
var unit = {
'Rainfall': 'mm',
'Temperature': '°C',
'Sea-Level Pressure': 'mb'
}[this.series.name];
return ''+
this.x +': '+ this.y +' '+ unit;
}
},
legend: {
layout: 'vertical',
align: 'left',
x: 120,
verticalAlign: 'top',
y: 80,
floating: true,
backgroundColor: '#FFFFFF'
},
series: [{
name: 'Rainfall',
color: '#4572A7',
type: 'column',
yAxis: 1,
data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}, {
name: 'Sea-Level Pressure',
type: 'spline',
color: '#AA4643',
yAxis: 2,
data: [1016, 1016, 1015.9, 1015.5, 1012.3, 1009.5, 1009.6, 1010.2, 1013.1, 1016.9, 1018.2, 1016.7],
marker: {
enabled: false
},
dashStyle: 'shortdot'
}, {
name: 'Temperature',
color: '#89A54E',
type: 'spline',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}]
});
});
});
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>

Is there a complete/ready event even if I turn off the animation effect for a HighChart instance?

I am wondering, is there any 'ready' event for me to check whether a HighChart instance is 100% rendered in my browser.
I found that with some complicated data, the HighChart would take a few seconds to render even if I turned off the animation. So is there any way to know that if the chart is 100% ready so that I can take further steps (like to trigger a function to convert the HighChart into a raw image data and to save it locally later)?
Example:
Animation ON:
http://jsfiddle.net/7rLnwdxu/11
Animation OFF:
http://jsfiddle.net/7rLnwdxu/12
The load event fires before the chart is completely drawn (the lines inside the chart). It also fails to fire when the animation is turned off. And the redraw event never fires in both cases.
Thanks,
CODE BELOW:
$(function () {
$('#container').highcharts({
chart: {
polar: true,
type: 'line',
events: {
load: function(event) {
alert('Chart loaded');
},
redraw: function(event) {
alert('Chart redrawn');
}
}
},
title: {
text: 'Budget vs spending',
x: -80
},
pane: {
size: '80%'
},
xAxis: {
categories: ['Word1_Word2', 'Word1 Word2',
'Word1 - Word2', 'Word1-Word2',
'Word1 Word2', 'Word1 Word2'],
tickmarkPlacement: 'on',
lineWidth: 0,
animation: false
},
yAxis: {
gridLineInterpolation: 'polygon',
lineWidth: 0,
min: 0
},
tooltip: {
shared: true,
pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>'
},
legend: {
align: 'right',
verticalAlign: 'top',
y: 70,
layout: 'vertical'
},
series: [{
name: 'Allocated Budget',
data: [43000, 19000, 60000, 35000, 17000, 10000],
pointPlacement: 'on'
}, {
name: 'Actual Spending',
data: [50000, 39000, 42000, 31000, 26000, 14000],
pointPlacement: 'on'
}]
});
});
And this is happening not just with Polar Chart but also simple charts, for example:
http://jsfiddle.net/AVygG/97/
CODE BELOW:
$(function () {
// create the chart
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
events: {
load: function(event) {
alert ('This is triggered BEFORE the whole series line is drawn');
console.log(this);
}
}
},
xAxis: {
},
series: [{
name : 'TestSeries',
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
chart.title = "hello";
});
Yes there are 2 events for this :
load : Fires when the chart is finished loading.
redraw : Fires when the chart is redrawn.
HIGHCHARTS API : http://api.highcharts.com/highcharts#chart.events
There some example of code :
Highcharts's onReady event?
when is a highchart completely loaded?
If you need the graph is finished to be rendered
Can you try with this :
http://jsfiddle.net/7rLnwdxu/14/
or with following code :
$(function () {
function myFunction() {
setTimeout(function(){
alert("Chart should be rendered now");
//codes
}, 1500);
}
$('#container').highcharts({
chart: {
polar: true,
type: 'line',
events: {
load: function(event) {
myFunction();
}
}
},
title: {
text: 'Budget vs spending',
x: -80
},
pane: {
size: '80%'
},
xAxis: {
categories: ['Word1_Word2', 'Word1 Word2',
'Word1 - Word2', 'Word1-Word2',
'Word1 Word2', 'Word1 Word2'],
tickmarkPlacement: 'on',
lineWidth: 0,
animation: false
},
yAxis: {
gridLineInterpolation: 'polygon',
lineWidth: 0,
min: 0
},
tooltip: {
shared: true,
pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>'
},
legend: {
align: 'right',
verticalAlign: 'top',
y: 70,
layout: 'vertical'
},
series: [{
name: 'Allocated Budget',
data: [43000, 19000, 60000, 35000, 17000, 10000],
pointPlacement: 'on'
}, {
name: 'Actual Spending',
data: [50000, 39000, 42000, 31000, 26000, 14000],
pointPlacement: 'on'
}]
});
});

Set at the same level the unit of two yaxis highcharts

I would like to set at the same level 2 yAxis with highcharts. Because it's difficult to explain what I want, this picture should help you to understand :
I want to align the two "0" value of my 2 charts.
This is my current code :
$(function () {
$('#tresorerieChart').highcharts({
chart: {
zoomType: 'xy'
},
title: {
text: 'Average Monthly Temperature and Rainfall in Tokyo'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: [{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
}],
yAxis: [{ // First yAxis
labels: {
format: '{value}°C',
style: {
color: Highcharts.getOptions().colors[1]
}
},
title: {
text: 'Temperature',
style: {
color: Highcharts.getOptions().colors[1]
}
}
},
{ // Third yAxis
title: {
text: 'Rainfall',
style: {
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value} mm',
style: {
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
tooltip: {
shared: true
},
legend: {
layout: 'vertical',
align: 'left',
x: 120,
verticalAlign: 'top',
y: 100,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
},
series: [{
name: 'Rainfall',
type: 'column',
yAxis: 1,
data: [49.9, -71.5, 106.4, -129.2, 144.0, -176.0, -135.6, 148.5, 216.4, 194.1, -95.6, 54.4],
tooltip: {
valueSuffix: ' mm'
}
}, {
name: 'Temperature',
type: 'spline',
data: [-7.0, -6.9, -9.5, -14.5, -18.2, -21.5, -25.2, -26.5, -23.3, -18.3, -13.9, -9.6],
tooltip: {
valueSuffix: '°C'
}
},
{
name: 'Temperature',
type: 'spline',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6],
tooltip: {
valueSuffix: '°C'
}
}]
});
});
Thanks in advance.
Long time ago I have created example how to align two yAxis to the same value, you can find this here: http://jsfiddle.net/5m9JW/414/
Code responsible for linking axes:
var i = 15;
while (chart.yAxis[1].translate(0) != chart.yAxis[0].translate(0) && i > 0) {
chart.yAxis[0].setExtremes(chart.yAxis[0].getExtremes().min - chart.yAxis[0].translate(chart.yAxis[1].translate(0), true));
i--;
};

Highcharts tooltip formatter

For this.x, I am getting the index location when I push the data in via code. If I populate the data separately, like the following code, then this.x returns the right item. How can I fix this issue?
Works
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
Index location is getting pushed out for this.x here
var points = [{
Name: 'good',
Y: '15000'
}, {
Name: 'baad',
Y: '3000'
}, {
Name: 'wow',
Y: '2000'
}];
var chartData = {
GetChartSeries: function (points, name) {
var seriesData = [];
if (points != null && points != 'undefined') {
for (i=0; i<points.length; i++) {
seriesData.push({
name: ""+points[i].Name,
y: parseFloat(points[i].Y)
//,color: ''
});
}
}
return seriesData;
}
};
$(function () {
$('#container').highcharts({
chart: {
type: 'column',
margin: [ 50, 50, 100, 80],
borderColor: '#A4A4A4',
borderRadius: 5,
borderWidth: 2
},
legend: {
enabled: false
},
title: {
text: 'Graduation Year Breakdown'
},
colors: ['#790000'],
legend: {
enabled: false
},
plotOptions: {
series: {
/*
dataLabels: {
enabled: true,
color: 'red'
},
*/
borderRadius: 3,
colorByPoint: true
}
},
tooltip: {
formatter: function() {
return '<b>'+ Highcharts.numberFormat(this.y, 0) +'</b><br/>'+
'in year: '+ this.x;
}
},
xAxis: {
categories: [],
labels: {
rotation: -45,
align: 'right',
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Number of Students'
}
},
series: [{
//name: 'Population',
data: chartData.GetChartSeries(points, ""),//[4000, 3400, 2000, 34000, 120000],
dataLabels: {
enabled: true,
//rotation: -90,
color: '#4F4F4F',
align: 'center',//'right',
//x: 4,
//y: 10,
style: {
fontSize: '12px',
//fontWeight: 'bold',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
While I am uncertain as to why your solution doesn't work, I can propose an alternative solution.
The tooltip formatter function has access to a number of different parameters. Instead of this.x, you could use this.point.name.
For example:
formatter: function() {
// If you want to see what is available in the formatter, you can
// examine the `this` variable.
// console.log(this);
return '<b>'+ Highcharts.numberFormat(this.y, 0) +'</b><br/>'+
'in year: '+ this.point.name;
}

Sort series per category

I have a chart that looks like this:
http://jsfiddle.net/rtGFm/37/
I would like to have a "sort" button that sorts high to low each category, putting the columns in a different order for each category. Is this possible with HighCharts?
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: ''
},
subtitle: {
text: ''
},
xAxis: {
categories: [
'foreclosures',
'nuisances',
'distance from city center'
]
},
yAxis: {
min: 0,
title: {
text: ''
}
},
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' mm';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Alger Heights',
data: [49.9, 71.5, 50]
}, {
name: 'Shawmut Hills',
data: [83.6, 78.8, 67]
}, {
name: 'Baxter',
data: [48.9, 38.8, 100]
}, {
name: 'Midtown',
data: [42.4, 33.2, 80]
}, {
type: 'scatter',
data: [55,60,70],
marker: {
symbol: 'square',
lineColor: '#FFFFFF',
lineWidth: 1,
radius: 8
},
name: 'Average'
}]
});
});
I had the same problem :) highcharts still does not provide any solution for this problem, but it is flexibel enough so that you can sort anyway - just by javascript.
Put your data in a separate value:
var dataMain = [{name:"test1",data:5}, {name:"test1",data:1},{name:"test1",data:2}]
In series you can just add a function which sorts your data:
series: (function(){
for(var i = 0;i<dataMain.length;i++){
dataMain[i].data = dataMain[i].data.sort(function(a,b){
return a[0] - b[0] ;
})
return dataMain;
}
Hope I got everything wright.
Got it to work, I believe. Trick is to add each column in correct order as a new serie with same type (column), reuse colors and hide legend...
Very hackish, the JS code to sort like 8 categories independently will be ugly but the result looks fine.
Edit: Updated fiddle, I see the spacing between the categories grows with series, doesn't look supernice.
My jsfiddle is here
$(function () {
$('#container').highcharts({
chart: {
inverted: true
},
title: {
text: 'Series sorted in within categories'
},
xAxis: {
categories: ['January']
},
series: [{
type: 'column',
name: 'Stockholm',
data: [{x:0, y:95, color: Highcharts.getOptions().colors[0]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x:0, y:80, color: Highcharts.getOptions().colors[1]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x: 1, name: 'February', y: 98, color: Highcharts.getOptions().colors[1] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}, {
type: 'column',
name: 'Stockholm',
data: [{x: 1, name: 'February', y: 80, color: Highcharts.getOptions().colors[0] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}]
});
});
br,
Jens
I think this can be done,
this may look like a little work around.
since we have a limited number of columns i mean 4 in the given example.
if we have arrays with sorting done with respect to each series then we can handle them.
on button click we can update the chart with new set of data as well as category array.
May be there is no solution from the APi.
According to me this is a possible approach.
Thanks,

Resources