17
votes

I'd like to be able to toggle the visibility of the legend of a chart when the user clicks a button.

I've tried hiding the legend using the undocumented destroy() method, however when I try to re-render the legend and it's items, the items appear in the top left of the chart instead of within the legend. The items also don't seem to have any of their event handlers attached (clicking on an item no longer toggles a series).

Is there a better way to do this? I have to support both SVG and VML implementations, so am looking for a solution that would address both.

JSFiddle Example

$('#updateLegend').on('click', function (e) {
    var enable = !chart.options.legend.enabled;
    chart.options.legend.enabled = enable;

    if (!enable) {
        chart.legend.destroy(); //"hide" legend
    } else {
        var allItems = chart.legend.allItems;

        //add legend items back to chart
        for (var i = 0; i < allItems.length; i++) {
            var item = allItems[i];
            item.legendItem.add();
            item.legendLine.add();
            item.legendSymbol.add();
        }

        //re-render the legend
        chart.legend.render();
    }
});
6
in fact there was a yet better way. see my solution.floww

6 Answers

14
votes

In case when you destroy legend, then you need to generate full legend. Simpler solution is use hide() / show() function for elements.

http://jsfiddle.net/sbochan/3Bh7b/1/

$('#updateLegend').click(function (e) {
        var legend = chart.legend; 

        if(legend.display) {
            legend.group.hide();
            legend.box.hide();
            legend.display = false;
        } else {

            legend.group.show();
            legend.box.show();
            legend.display = true;
        }
    });
14
votes

Here is an interesting solution I came up with - works for Highcharts3 and Highstocks1.3 https://bitbucket.org/jkowalleck/highcharts-legendextension

All you have to do is to add the HighchartsExtension I wrote to your HTML page, and you get 3 new functions added to the Chart:
myChart.legendHide() ,
myChart.legendShow() and
myChart.legendToggle()

See the examples:
in Highcharts with floating legend: http://jsfiddle.net/P2g6H/
in Highstocks with static legend: http://jsfiddle.net/ps6Pd/

6
votes

As simple as

myChartObject.legend.update({
   enabled:true
)};
5
votes

A fairly simple way to make this is to loop over the series and update them to not show in legend. This allows you to animate in and out of showing the legend and utilize the entire container space, as the methods are built in.

For example, toggling legend items would look like this:

$('#toggleButton').click(function() {
    for(i in chart.series)
        chart.series[i].update({ showInLegend: chart.series[i].options.showInLegend == null ? false : !chart.series[i].options.showInLegend }, false);
    chart.redraw();
});

See this JSFiddle demonstration for toggle, show and hide using buttons.

0
votes

Update a code little bit of selected answer. Now it will increase the space when show/hide legend.

$('#updateLegend').click(function (e) {
    var legend = chart.legend; 

    if(legend.display) {
        legend.group.hide();
        legend.box.hide();
        legend.display = false;
    } else {

        legend.group.show();
        legend.box.show();
        legend.display = true;
    }

    var series = chart.series[0];
        $(chart.series).each(function(){
            this.setVisible(true, false);
        });
        chart.redraw();

});
-1
votes

So far only working solution in the world:

for (i = 0; i < chart.series.length; i++)
          chart.series[i].options.showInLegend = true;
          chart.series[0].setData(chart.series[0].data);  

Rendering manually doesn't work (hiding legend.box etc, always if there are multiple pages in legend, then browser button stays). setData calls internal renderer which acts quite good and does all what is needed.
Hmm, maybe in the end you can do this:
chart.setSize( chartWidth, chartHeight+chart.legend.fullHeight, false );