Skip to content

February 1, 2013

Highcharts selection event callback: exposing mouse event clientX & clientY info

by Joe Kuan

I have been manually doing this change in my own versions of Highcharts for couple years and it is not been done in the latest version (pre 3.0). This minor feature probably too trivial to consider. However, after recent discussion with Torsein, he thinks this is a good idea and it will be put in Highcharts 3.0 code base.

Basically, the current Highcharts selection event callback (chart.events.selection) only passes the selection object as an argument. This selection object does not contain any mouse event. This is fine except that you want to create some form of popup menu selections for the selected region in the graph. In order to display the popup menu, you need to know the current mouse event pageX & pageY (or clientX & clientY) values to display next to the mouse pointer. The following screenshot is generated from my change for the AppQoS product:

Highcharts selection ExtJs popup menu

The following is a section of Highcharts v2.3.5 code to export selection event data, selectionData:

    function drop() {
      if (mouseTracker.selectionMarker) {
        var selectionData = {
            xAxis: [],
            yAxis: []
          },
          selectionBox = mouseTracker.selectionMarker.getBBox(),
          selectionLeft = selectionBox.x - chart.plotLeft,
          selectionTop = selectionBox.y - chart.plotTop,
          runZoom;
          .....

To include the mouse event, simply apply the following changes:

    function drop(e) {
      if (mouseTracker.selectionMarker) {
        var selectionData = {
            xAxis: [],
            yAxis: [],
            originalEvent: (e.originalEvent) ? e.originalEvent : e
          },
          selectionBox = mouseTracker.selectionMarker.getBBox(),
          selectionLeft = selectionBox.x - chart.plotLeft,
          selectionTop = selectionBox.y - chart.plotTop,
          runZoom;
          .....

So lets use ExtJs to build a popup menu from highlighting a region of graph

    chart: {
        ....,
        events: {
            selection: function(evt) {
                // Create popup menus with selection's xAxis[0].min
                // and xAxis[0].max embedded inside
                var menu = Ext.create('Ext.menu.Menu', {
                    ....
                });

                // Is this event generated from touch or pointer
                // based device
                var selEvt = null;
                if (selection.originalEvent.type == 'touchend') {
                    selEvt = evt.originalEvent.changedTouches[0];
                } else if (evt.originalEvent.type == 'mouseup') {
                    selEvt = evt.originalEvent;
                }

                selEvt && menu.showAt(selEvt.clientX, selEvt.clientY);
             }
        },
        .....
    }

If you want the highlighted region to stay while the popup menu appears (like the above screenshot), then you need to calibrate with the selectionMarker object a bit more. First, you will need to export the selectionMarker object into selectionData. Secondly, you will need to comment out the line that destroys the selectionMarker object.

    function drop(e) {
      if (mouseTracker.selectionMarker) {
        var selectionData = {
            xAxis: [],
            yAxis: [],
            originalEvent: (e.originalEvent) ? e.originalEvent : e,
            mouseTracker: mouseTracker
          },
          .....
        // Comment out the following line and let the popup menu to destroy it
        // mouseTracker.selectionMarker = mouseTracker.selectionMarker.destroy();
      }
      ....
    }

Then in your ExtJs Menu object specifier, you can do something like the followings:

                // Create popup menus with selection's xAxis[0].min
                // and xAxis[0].max embedded inside
                var menu = Ext.create('Ext.menu.Menu', {
                    listeners: {
                        scope: evt.mouseTracker,
                        hide: function() {
                           (this.selectionMarker) && 
                               (this.selectionMarker = this.selectionMarker.destroy());
                        },
                        destroy: function() {
                           (this.selectionMarker) && 
                               (this.selectionMarker = this.selectionMarker.destroy());
                        }
                    },
                    items: [ ... ],
                    ....
                });
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

%d bloggers like this: