agri
agri

Reputation: 507

Highcharts Stacked Column chart change legendItemClick function

On legendItemClick, how do I prevent subtraction of legend item value from total and instead add the value to another legend item.

E.g. I would like the 'Other Fruit' series to contain all switched off fruit series (the same with 'Other Veg' series).

Here is the Fiddle

$(function () {
 $('#container').highcharts({
    chart: {
        type: 'column'
    },
    title: {
        text: 'Stacked column chart'
    },
    xAxis: {
        categories: ['Then', 'Now']
    },
    yAxis: {
        min: 0,
        title: {
            text: 'Total 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: {
     series: {
            events: {
                legendItemClick: function () {
                 //if fruit/veg is clicked then add value to other fruit/veg and keep the total unchanged
                  // return false;

                }
            }
        },
        column: {
            stacking: 'normal',
            dataLabels: {
                enabled: true,
                formatter:function() {
                  return this.series.name+' '+this.point.y;
                },
                color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
                style: {
                    textShadow: '0 0 3px black'
                }
            }
        }
    },
    series: [{
        name: 'Other Fruit',
        data: [8, 13]
    },{
        name: 'Other Veg',
        data: [16, 10]
    },{
        name: 'Tomatoes',
        data: [3, 7]
    },{
        name: 'Cucumbers',
        data: [5, 4]
    },{
        name: 'Apples',
        data: [5, 3]
    }, {
        name: 'Bananas',
        data: [3, 6]
    }, {
        name: 'Oranges',
        data: [3, 4]
    }]
});

});

Upvotes: 1

Views: 314

Answers (1)

Rahul Sharma
Rahul Sharma

Reputation: 912

Things we need to do

  • Series should be categorized as fruit and vegetables, so that we know which others series("Other Fruit" or "Other Veg") to add/subtract value from.
  • When the legend item is clicked, check if it's a fruit or a veggie and add the value to others.
  • When clicked again, subtract the values from others.
  • We should not be able to hide the others series.

    series: [{
      name: 'Other Fruit',
      data: [{y:8}, {y:13}],
    },{
      name: 'Other Veg',
      data: [{y:16}, {y:10}]
    },{
      name: 'Tomatoes',
      data: [{y:3}, {y:7}],
      fruit: false
    },{
      name: 'Cucumbers',
      data: [{y:5}, {y:4}],
      fruit: false
    },{
      name: 'Apples',
      data: [{y:5}, {y:3}],
      fruit: true
    },{
      name: 'Bananas',
      data: [{y:3}, {y:6}],
      fruit: true
    },{
      name: 'Oranges',
      data: [{y:3}, {y:4}],
      fruit: true
    }]
    

    Added a property "fruit" to all series except "Other Fruit" and "Other Veg".

    legendItemClick: function () {
        var isFruit = this.options.fruit;
        if(isFruit == undefined){ //property undefined for "Other fruit" and "Other Veg"
          return false; //returning false prevents hiding the series
        }
        var chart = this.chart;
        var othersSeries;
        if(isFruit){
          othersSeries = chart.series[0]; //if it's a fruit, get "Other Fruit" series
        }
        else{
          othersSeries = chart.series[1]; //else get "Other Veg" series
        }
        updateOthersData(this, othersSeries);
    }
    
    function updateOthersData(currentSeries, othersSeries){
        var othersData = othersSeries.options.data;
        if(currentSeries.visible){ //add values only when the series is already visible and is to be hidden
            othersData[0].y += currentSeries.options.data[0].y;
            othersData[1].y += currentSeries.options.data[1].y;
        }
        else{ //subtract values only when data is already hidden and is to be shown
            othersData[0].y -= currentSeries.options.data[0].y;
            othersData[1].y -= currentSeries.options.data[1].y;
        }
     othersSeries.update({data:othersData}); //update the series
    }   
    

Here is the fiddle.

Upvotes: 2

Related Questions