I have 3 Highcharts charts on a webpage with a jQuery-UI tabs navigation system - one chart per tab. In only one of these charts I added an arrow to the plotted line. This arrow gets generated inside an IIFE (see the code sample below). Otherwise the Highcharts functions are pretty standard.
The problem occurs when I try to switch tabs and present the data for the other two charts: the arrow is being drawn on the charts that shouldn't have any arrows.
The erroneous arrow isn't always drawn on the other charts - never on the first render, and usually only after the user has switched tabs two or three times, then the arrow appears where it shouldn't. I also noticed that this IIFE is being called each time a chart is rendered (even from the other tabs).
I don't know how Highcharts works internally but each one of my charts is attached to a different DOM element (by ID), therefore Highcharts shouldn't mix the charts when the arrow is being rendered.
Does anyone have any idea why this is happening?
(function (H) {
var arrowCheck = false, //This variable helps the arrow to be responsive
pathTag;
H.wrap(H.Series.prototype, 'drawGraph', function (proceed) {
// Now apply the original function with the original arguments,
// which are sliced off this function's arguments
// This section takes care of the arrow of the graph
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var arrowLength = 14,
arrowWidth = 7,
series = this,
data = series.data,
segments = data,
lastSeg = segments[segments.length - 1],
path = [],
lastPoint = null,
nextLastPoint = null;
if (typeof (lastSeg) === "undefined") {
return;
}
if (lastSeg.y === 0) {
lastPoint = segments[segments.length - 2];
nextLastPoint = segments[segments.length - 1];
} else {
lastPoint = segments[segments.length - 1];
nextLastPoint = segments[segments.length - 2];
}
var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
(lastPoint.plotY - nextLastPoint.plotY));
if (angle < 0) angle = Math.PI + angle;
path.push('M', lastPoint.plotX, lastPoint.plotY);
if (lastPoint.plotX > nextLastPoint.plotX) {
if (arrowCheck === true) {
pathTag = doc.getElementById("arrow");
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
'L',
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX + arrowLength * Math.sin(angle),
lastPoint.plotY + arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX - arrowWidth * Math.cos(angle),
lastPoint.plotY + arrowWidth * Math.sin(angle),
'Z'
);
} else {
if (arrowCheck === true) {
pathTag = doc.getElementById("arrow");
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
lastPoint.plotY + arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX - arrowLength * Math.sin(angle),
lastPoint.plotY - arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle),
'Z'
);
}
series.chart.renderer.path(path)
.attr({
fill: series.color,
id: 'arrow'
})
.add(series.group);
arrowCheck = true;
});
}(Highcharts));
Here a JSFiddle example (you just need to resize the section where the Charts are to see how the arrow jumps to the wrong chart)