Call addSeries() from within addSeries event - highcharts

I want to add a reference series to my charts (i.e. a reference price). Axis.addPlotLine() does it, but I want to be able to toggle this series from the legend; a plain plotLine does not show up in the graph's legend.
Another reason why plotLine does not seem like a good solution is that it does not get accounted for by the viewport calculations. Which means that toggling other series might lead to the plotLine appearing outside the viewport due to zooming.
The simplest way to accomplish what I want would be, to add a dynamic series via chart.addSeries. But it's impossible to call this method from within a triggered addSeries event because chart.addSeries is set to null while in the event handler.
Tying in to the redraw event creates a whole lot of difficulties as well, because render() can't be called anymore.
How would you go about it?
Update:
As per the comment of Pawel Fus, I unsuccessfully tried the following:
[…]
events: {
load: function (event) {
foo = this;
},
addSeries: function(event) {
console.log(foo) // returns chart object as expected
console.log(foo.addSeries) // undefined
}
}

Solution is to store addSeries on load event, and use stored function when adding series. Live example: http://jsfiddle.net/3bQne/808/
events: {
load: function (event) {
foo = this.addSeries;
},
addSeries: function (event) {
if (iterator) {
iterator--;
foo.call(this, {
data: [100, 200, 100, 100, 200, 300]
});
}
}
},

Still you can stick with plotLine only.
If the position of the line is static that is the best way.
If the position is dynamic then you can still go with plotLine.
There are events for adding and removing plotLine on the fly.
API link
removePLotLine() : http://api.highcharts.com/highcharts#Axis.removePlotLine
addPlotLine() : http://api.highcharts.com/highcharts#Axis.addPlotLine
I hope this will help you.

Related

Reset yAxis Min and Max on drilldown

I have seen similar questions just like these (even with similar title) but none of them provide the answer I need.
I have a bar-negative-stack chart with drilldown.
In order to keep the Y-axis centered, I am calculating the maximum value among the series and setting it as the extremes of the chart.
The thing is I haven't find a good place to put this logic. I have tried putting it on redraw or render events but, since I am changing the yAxis, this causes a stackoverflow.
What I have so far that is more or less working is having the drilldown event set up with a setTimeout to delay the calculation, otherwise it would get the values before the drilldown. I would need some event like drilldownFinish.
Here's a working fiddle with this drilldown logic (not on negative-bar-stack though): http://jsfiddle.net/6qpq78do/
Any ideas on how to do this without a setTimeout?
Thanks
Maximum callstack exceeded message is caused by setExtremes function. Its third argument is redraw - it's true by default: https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
So setExtremes will call the redraw event again and the redraw event will call setExtremes and so on...
The solution here is to create a flag (redrawEnbaled) that is going to control the access to the logic placed in redrawEvent and prevent this infinite recursive loop:
var redrawEnabled = true;
(...)
events: {
redraw: function() {
if (redrawEnabled) {
redrawEnabled = false;
let values = [];
this.series.forEach(s => {
s.yData.forEach(v => values.push(Math.abs(v)));
});
let max = values.reduce((acc, val) => (acc > val) ? acc : val, 0);
this.yAxis[0].setExtremes(-max, max);
redrawEnabled = true;
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/zjuy21k5/

Toggle connectNulls with button

I am just starting out with Highstock and I want to provide our users with the option of toggling the connection of the null data points via a button. Here is how I have tried to solve it: jsFiddle
// create the chart
var chart = new Highcharts.StockChart({
[...]
plotOptions : {
series : {
connectNulls : false // default
}
},
[...]
});
// Toggle connect nulls
var connectNulls = true;
$('#connectNulls').click(function() {
chart.plotOptions.series.connectNulls = connectNulls;
connectNulls = !connectNulls;
});
But it has no impact on the graph. All the examples I've found so far concerning toggling on chart configuration are doing dynamic manipulation on the series via the update method, but for the connectNulls I guess this is not possible.
I can always repaint the graph from scratch but I want to avoid this if possible. Say if one user has zoomed into the graph, repainting would cause the zoom to be lost.
Any suggestions?
You can use series.update() and then modify this param.
http://jsfiddle.net/vsmn60gL/3/

Highcharts: what is the difference between event.target and event.currentTarget

I am new to Highcharts.
I have the following for a column chart:
xAxis: {
....
events: {
afterSetExtremes: function(event) {
//do some work here.
//event has a property called target
//event has another property called currentTarget
}
}
...
}
I notice that event has two properties that seem to be identical (I am not sure). Are they the same? Any differnce? I need to know the final x values shown on a chart after zooming.
Thanks and regards.
Assuming you are using jQuery, it would be the same as those in jQuery events
event.currentTarget Returns: Element
Description: The current DOM element within the event bubbling phase.
Read More # http://api.jquery.com/event.currenttarget/
event.target Returns: Element
Description: The DOM element that initiated the event.
Read More # http://api.jquery.com/event.target/

want to customize/extend wicked-charts legend item click event

I have implemented a wicked-chart which shows 4 series in the legend. Now I want to handle the series click event in legend and update some values outside the wicked highchart.
To be specific, I want to implement exactly like this jsfiddle but in java wicked-chart.
plotOptions:
{
series: {
events: {
legendItemClick: function(event) {
//Do something here
return false;
}
}
I did search all the methods of PlotOptions class but could get something similar to highcharts legendItemClick event.
My solution was not to find alternative for legendItemClick in wicket-charts as they do not have one. Instead I did this:
In your page html, give id="chart". Doing this highcharts shall fix your id to "chartVar" instead of changing it at each run.
<div wicket:id="chart" id="chart"></div>
In your javascript, define your series click using .highcharts-legend-item as below.
var onSeriesClick = function() {
var that = this;
for (var i=0;i<chartVar.series.length;i++)
{
$(".highcharts-legend-item:contains(" + chartVar.series[i].name + ")").click(function(){
// your legend click logic goes here
});
}
}

HighCharts Keep Vertical Line on Click Event

Using this example: http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/stock/demo/candlestick-and-volume/
When you hover over points on the chart, you get a nice vertical line showing you which point you're currently on. I want to modify the click event so that the vertical line stays when I hover away after a click. Changing the line color would be ideal on click, but not necessary.
If I click another point I'd want to remove any previous lines. Any ideas on how I could accomplish this?
The above solution like I said, is really cool, but is kind of a hack (getting the path of the crosshair) into the implementation details of highcharts, and may stop working in future releases, may not be totally cross browser (esp since <IE8 do not support SVG, the adding path may still work as it should be handled by highchart's add path method, but getting the crosshair's path may not work, I may be wrong, am an SVG noob). So here I give you the alternate solution of dynamically adding plotLines. PlotLines also allow some additional features like dashStyles, label etc.
get the axis and x value of point clicked (may not exactly overlap the crosshair)
var xValue = evt.xAxis[0].value;
var xAxis = evt.xAxis[0].axis;
Or
EDIT If you want to have the plotLine at the location of the crosshair and not the click position, you can use following formula (No direct API to get this, obtained from source code hence may stop working if code changes)
var chart = this;
var index = chart.inverted ? chart.plotHeight + chart.plotTop - evt.chartY : evt.chartX - chart.plotLeft;
var xValue = chart.series[0].tooltipPoints[index].x;
Add plotline
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
//dashStyle: 'dash',
id: myPlotLineId
});
You can cleanup existing plotline
$.each(xAxis.plotLinesAndBands,function(){
if(this.id===myPlotLineId)
{
this.destroy();
}
});
OR
try {
xAxis.removePlotLine(myPlotLineId);
} catch (err) {}
Putting the pieces together
var myPlotLineId="myPlotLine";
...
var chart=this;
index = chart.inverted ? chart.plotHeight + chart.plotTop - evt.chartY : evt.chartX - chart.plotLeft;
var xValue = chart.series[0].tooltipPoints[index];
// var xValue = evt.xAxis[0].value; // To use mouse position and not crosshair's position
var xAxis = evt.xAxis[0].axis;
$.each(xAxis.plotLinesAndBands,function(){
if(this.id===myPlotLineId)
{
this.destroy();
}
});
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
//dashStyle: 'dash',
id: myPlotLineId
});
...
Add plot lines at click position # jsFiddle
Persist crosshair/cursor as plot lines on click # jsFiddle
You can do it in several ways
Highchart has a very cool renderer that allows you to add various graphics to the chart. One of the options is to add a path I will be illustrating the same here.
We shall reuse the path of the crosshair and add the same to the chart with some additional styles like color you mentioned. The path of the crosshair can be optained as this.tooltip.crosshairs[0].d this is in string form and can be easily converted to an array using the Array.split() function
click: function() {
this.renderer.path(this.tooltip.crosshairs[0].d.split(" ")).attr({
'stroke-width': 2,
stroke: 'red'
}).add();
}
This will accomplish adding the line. You can store the returned object into a global variable and then when you are about to add another such line, you can destroy the existing one by calling Element.destroy()
var line;
...
chart:{
events: {
click: function() {
if (line) {
line.destroy();
}
line = this.renderer.path(this.tooltip.crosshairs[0].d.split(" ")).attr({
'stroke-width': 2,
stroke: 'red'
}).add();
}
}
...
Persist tooltip / crosshair on click # jsFiddle
Assuming you don't have much meta data to be shown along with the line, this is the easiest (or the coolest :) ) approach. You can also attach meta data if you want to using the renderer's text object etc.
An alternate way could be adding vertical plotLines to the xAxis
UPDATE
Refer my other solution to this question, that would work with zoom,scroll,etc

Resources