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();
}
});
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;
}
});
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/
As simple as
myChartObject.legend.update({
enabled:true
});
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.
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();
});
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
);
Related
Currently I'm using css to remove my y-axis grid lines and labels like in the below image.
CSS:
.highcharts-yaxis-grid path:nth-child(1),.highcharts-yaxis-grid path:nth-child(2),
.highcharts-yaxis-grid path:nth-child(4),.highcharts-yaxis-grid path:nth-child(5){ stroke:transparent !important; }
.highcharts-yaxis-labels text:nth-child(1),.highcharts-yaxis-labels text:nth-child(2),
.highcharts-yaxis-labels text:nth-child(4),.highcharts-yaxis-labels text:nth-child(5){ fill:transparent !important; }
Whenever I download the chart as an image they reappear which makes sense as it doesn't see the css file I'm using.
I've tried to search for an answer on highcharts or anything on the net and haven't had luck, so here I am presenting this question.
For example in the load event you can remove specific labels and gridLines:
chart: {
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
gridLines[2].remove();
ticks[tickPositions[2]].label.element.remove();
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/5m0s7th2/
API Reference: https://api.highcharts.com/highcharts/chart.events.load
Using the accepted answer I did this in a loop to avoid losing my middle gridline and tick val.
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
var i = 4;
while(i > -1){
if(i !== 2){
gridLines[i].remove(); // the whole array element is removed from gridLines, so we're doing this backwards
ticks[tickPositions[i]].label.element.remove();
}
i--;
}
}
}
It became a problem when I was starting from 0 using either the accepted answer or my loop. Hope this helps anyone who may have a ton of gridlines.
I am using combine high charts. I need to hide a particular pie chart and column chart data while clicking a particular legend. If i use:
series[i].data[index].remove()
That removes the value but not able to show that value again while clicking the legend.
series[i].data[index].hide()
Refer to this JSFidddle - Example which I tried but I get an error like This is not function. How do I solve this?
You can use hide method on point SVG graphic element:
events: {
legendItemClick: function(e) {
var index = this.index;
var chart = this.series.chart;
var series = chart.series;
var len = series.length - 1;
if (this.visible) {
series[0].points[index].graphic.hide();
} else {
series[0].points[index].graphic.show();
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/d8uaxefo/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#hide
I know that the font color for the tooltip labels can be changed with the toolTipFontColor option, but that forces me to give one colour for all labels. Is there a way to set the colour for a label to, say, white, but then change it to red if a condition holds. I was thinking of something using the customTooltips option but any solution is welcome.
Example of what I'd like to do:
if (difference[i] >= 0) {
tooltipFontColor: "#FFF"
} else {
tooltipFontColor: "#F00"
}
The trick is that the difference array can have some values above zero and some below. I want Chart.js to somehow understand that and follow through with the colours.
Thanks!
Different Colors for Toooltip Based on Value
Preview
Script
new Chart(ctx).Line(data, {
// take over the tooltip binding
tooltipEvents: [],
onAnimationComplete: function () {
// copy of chart.js binding except that ...
Chart.helpers.bindEvents(this, ["mousemove", "touchstart", "touchmove"], function (evt) {
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function (point) {
point.restore(['fillColor', 'strokeColor']);
});
Chart.helpers.each(activePoints, function (activePoint) {
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
// ... we set the font color before the tooltip is shown
if (activePoints.length !== 0) {
if (activePoints[0].value >= 0)
this.options.tooltipFontColor = "#FFF";
else
this.options.tooltipFontColor = "#F00";
}
this.showTooltip(activePoints);
});
}
});
Fiddle - http://jsfiddle.net/uajz17yp/
I have a chart and implemented seriesClick event. When User clicks it loads dataA, when user click again it loads dataB. It is fully implemented and it is functional. However my question is how to fix chart area and legend area.
Legend length differs in dataA and dataB, therefore when user click on series, chart is not stay stable, it adjusts automatically. I do not want my chart to adjust automatically.
my SeriesClick event implementation is as follows:
function clickEvent (e) {
if (!isHover) {
chart.options.series = dataSeries2;
chart.redraw();
isHover = true;
}
else if (isHover) {
var chart = $("#chart").data("kendoChart");
chart.options.series = dataSeries;
chart.redraw();
isHover = false;
}
}
Here is the jsfiddle:
http://jsfiddle.net/3yhbyy2g/72/
There is no API yet for setting plot area to have fixed width, all you can do right now is give an escape character (\n) in your legend label.
stats = stats.map(function(x) {
return { x: x[0], y: x[1], k: x[2],name:"my title\nis too\nlengty" };
});
I found this in their forum, hope that will help you out.
I can't find way to update marginTop value of already created chart.
Check out my example:
http://jsfiddle.net/TZaEV/4/
var btn = $('#btn');
btn.click(function(){
// do changes
});
I need to change chart.marginTop value without creating chart object again. (When I click on trigger button, for example).
var btn = $('#btn');
btn.click(function(){
chart.optionsMarginTop += 20;
chart.isDirtyBox = true; // this makes your chart redraw
chart.redraw();
});
Demo
This one worked for me:
const chart = $("#container").highcharts();
chart.options.chart.marginTop = 100;
chart.isDirtyBox = true;
chart.redraw();
How about using Chart.update() function?
chart.update({
chart: {
marginTop: 30
}
});
API Reference:
http://api.highcharts.com/highcharts/Chart.update
http://api.highcharts.com/highcharts/chart.marginTop
Example:
http://jsfiddle.net/neo0xb2w/