Search code examples
javascriptjqueryhighchartssynchronizationtooltip

Highcharts synchronized charts combining with other charts


I am currently building a highcharts dashboard but experience a problem. If I try to combine highcharts synchronized charts with other graphs, the tooltip goes wrong with other graphs. If you move over the synchronized graphs, the tooltip moves along in the other graphs and remains visible.

To show what I mean, I made the following example:

JSFiddle

$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;

for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
// Find coordinates within the chart
event = chart.pointer.normalize(e.originalEvent);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);

if (point) {
  point.highlight(e);
}
}
});

Highcharts.Pointer.prototype.reset = function() {
return undefined;
};

Highcharts.Point.prototype.highlight = function(event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};

function syncExtremes(e) {
var thisChart = this.chart;

if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
  if (chart !== thisChart) {
    if (chart.xAxis[0].setExtremes) { // It is null while updating
      chart.xAxis[0].setExtremes(
        e.min,
        e.max,
        undefined,
        false, {
          trigger: 'syncExtremes'
        }
      );
    }
  }
});
}
}

I suspect this is the problem

Highcharts.charts

As a result, I think the tooltip is applied to all highcharts charts.

Hopefully you can help me to solve this problem!


Solution

  • You are right, the problem is Highcharts.chart array, which contains all charts on the page. In your case, a good idea is to add extra property to chart options to indicate synced charts, for example:

        .highcharts({
          chart: {
            isSynced: true, // our own property
            height: 100,
            marginLeft: 40, // Keep all charts left aligned
            spacingTop: 20,
            spacingBottom: 20
          },
          ...
        });
    

    Now filter out these charts:

    $('#container').bind('mousemove touchmove touchstart', function(e) {
      var chart,
        point,
        i,
        event;
    
      for (i = 0; i < Highcharts.charts.length; i = i + 1) {
        chart = Highcharts.charts[i];
    
        // Only charts in sync:
        if (chart && chart.options.chart.isSynced) {
          // Find coordinates within the chart
          event = chart.pointer.normalize(e.originalEvent);
          // Get the hovered point
          point = chart.series[0].searchPoint(event, true);
    
          if (point) {
            point.highlight(e);
          }
        }
      }
    });
    

    Demo with fixed: https://jsfiddle.net/BlackLabel/e3jdhjLo/5/