Attach a click event on a Highcharts series crosshair
Highcharts is a very powerful charting library written in pure JavaScript, offering an easy way of adding interactive charts to your web site or web application. Highcharts currently supports a lot of chart types such as line, spline, area, areaspline, column, bar, pie, scatter, angular gauges, arearange and so on.
Preface
If you don’t already knew it, you can attach events on several Highcharts components like legend, tooltips, series and especially series points but not on a series crosshair. If you don’t know charts series events you can learn more about it here (line charts events).
To know what is a series crosshair, just hover the different columns of the above chart example. The highlight effect on the entire column is called a crosshair, and the column a category.
So now you get the concept, the goal is to attach a click event on a series crosshair but it’s not possible with the actual Highcharts API so we need to make it ourselves.
Step 1: What do we really want
Firstly, we need to define what we want to do: easy you say ? You’re right! Highchars comes with its own utility called wrap
, which wraps an existing prototype method and allows you to add your own code before or after it. So the solution is to extend Highcharts’s drawCrosshair
method and add our own event function!
Step 2: Let’s code it!
Now we know how to do it*, let’s dev a little snippet:
Some explanations about the above code :
The
wrap
function accepts theparent
object as the first argument, thename
of the function to wrap as the second, and acallback replacement function
as the third. The original function is passed as the first argument to the replacement function, and original arguments follow after that.
Given that a crosshair is associated to an axis (yAxis so a category here), we need to add the chrosshair click event on the Axis Highcharts property to make it available for all Highcharts instances. So pass H.Axis.prototype
as first argument to tell Highcharts you want to modify a prototype of the Axis property of the Highcharts constructor.
Then we need to tell the wrap
method which prototype of Highcharts.Axis
we want to override. drawCrosshair
is an existing method designed to draw the crosshair canvas
on a chart category (axis). Since this method already exists and as said above, the drawCrosshair
will be replaced by the code written into the replacement function (passed as third argument of the wrap
method) and passed as first argument of this replacement function in order to improve it (because we doesn’t want to clear all the code but improve it by the piece of code given).
Finally, the replacement function is passed as third argument of the wrap
method with an argument (named proceed
here) that is equal to the original Highcharts.Axis.drawCrosshair
method.
So in the above code (inside the replacement function) axis
is an alias to this
which refers to the current Axis instance (a chart could have several axises (categories), so it creates several instances).
The
apply()
method calls a function with a giventhis
value andarguments
provided as an array (or an array-like object).
The above code executes proceed
witch is the equivalent to Highcharts.Axis.drawCrosshair
so for the moment, nothing really change compared to the original native method.
And here’s the code responsible of our crosshair click event!
What’s important is to check if axis.cross
is defined because it’s not on init and it globally represents our series crosshair. We’re also looking for a clickOnCrosshair
object with a callback method inside the chart configuration object.
If all conditions are satisfied, then we call the callback function given in the chart options object with the click event and the hovered point’s data as arguments.
You simply need to set the above code into the xAxis object in your chart options, and set whatever actions in the callback functions. In the example it shows the name of the category and it logs the axis instance, the click event and the hovered point data.
Here is the final result :
I hope you understand everything. If not, feel free to ask in the comments!
*I’m sorry. I couldn’t resist! ↑