benjamin.keen
benjamin.keen

Reputation: 1984

Highcharts: locating column group information on mouseover

I'm working on a rather complex Highcharts implementation and have run into a snag. I'm using a grouped column chart, with a series data structure very much like this:
http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/column-basic/

e.g.

series: [{
    name: 'Tokyo',
    data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0]
}, {
    name: 'New York',
    data: [83.6, 78.8, 98.5, 93.4, 106.0, 84.5]
},
... 

When the user mouses over any of the columns in a particular month, I'm trying to capture the following:

  1. the index of the month group (e.g. Jan == 0, Feb == 1 or something like that)
  2. the x,y and height,width coordinates of the entire group.

The problem is that "this" in plotOptions.column.events.mouseOver contains such a huge volume of data, I've been unable to identify where in the massive data structure that info exists. Also, it appears the mouseOver event is tied to the individual column being moused-over, rather than the group itself.

Any idea? (Thanks in advance!)

Upvotes: 2

Views: 1733

Answers (2)

Sebastian Bochan
Sebastian Bochan

Reputation: 37588

In mouseover venet for point, you have access to all parameters about column.

http://jsfiddle.net/amKuZ/

 mouseOver: function() {
                    $report.html('coordinate: x: ' +this.plotX+'coordinate y: ' +this.plotY+'column width' + this.pointWidth + ' x value:'+this.x);
                }

http://api.highcharts.com/highcharts#plotOptions.column.point.events.mouseOver

Upvotes: 1

cmptrgeekken
cmptrgeekken

Reputation: 8092

So I spent a bit of time looking into this and you're right, the event object passed into the mouseOver method is not all that helpful. I tried finding a reference to the currently-highlighted column, but to no avail. But, I found an alternate approach, relying on the DOM structure for the chart. This means it would probably break if they ever change the chart layout in a future version, but it should work for now.

The basic structure of the chart looks like this:

<g class="highcharts-series-group">
   <g class="highcharts-series">
      <rect x="11" y="223" width="5" height="55" />
      <rect x="61" y="199" width="5" height="79" />
      <rect x="111" y="160" width="5" height="118" />
      <rect x="161" y="135" width="5" height="143" />
      <rect x="211" y="118" width="5" height="160" />
      <rect x="261" y="83" width="5" height="195" />
      <!-- More <rect/>'s -->
   </g>
   <g class="highcharts-series">
      <rect x="19" y="185" width="5" height="93" />
      <rect x="69" y="191" width="5" height="87" />
      <rect x="119" y="169" width="5" height="109" />
      <rect x="169" y="175" width="5" height="103" />
      <rect x="219" y="161" width="5" height="117" />
      <rect x="269" y="184" width="5" height="94" />
      <!-- More <rect/>'s -->
   </g>
   <!-- More <g class="highcharts-series"/>'s -->
</g>

These correspond directly to the series information that was passed in on chart creation, with the x, y, width, and height attributes that I believe you're referring to. We can use this structure to use some old-fashioned event handling to retrieve the information you're looking for.

// Loop over each series element and bind a 
// 'mouseover' event to it.
$('.highcharts-series rect').on('mouseover', function() {
    var self = $(this);
    // Determine the offset (equal to the number of 'rect'
    // objects before it)
    var xIndex = self.prevAll('rect').length;
    var groupInfo = [];
    // Retrieve the '.highcharts-series-group' node
    // NOTE: $(this).parents('.highcharts-series-group')
    // does not appear to work (perhaps a limitation with 
    // jQuery and SVG?)
    $(this.parentNode.parentNode)
        // Loop over all series nodes within the current chart
        .find('.highcharts-series')
        .each(function(){
            // Retrieve the matching entry within each series
            // (represented by the nth 'rect' node)
            var element = $(this).find('rect:eq(' + xIndex + ')');
            if (!element.length) {
                return;
            }

            // Populate the Group Info element
            groupInfo.push({
                x: element.attr('x'),
                y: element.attr('y'),
                width: element.attr('width'),
                height: element.attr('height')
            });
        });

    // Do what you want with the groupInfo object and xIndex here:
    console.log(xIndex, groupInfo);
});

Upvotes: 3

Related Questions