Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically open and close Chart.js tooltip

Chart.js 2.2.1

Any idea how to trigger the code that runs when I hover over a datapoint, and that runs when I move the mouse off? I need to programmatically show and hide a chart's tooltip.

openTip(oChart, datasetIndex, pointIndex){
   // how to open a specific tooltip?
}
closeTip(oChart, datasetIndex, pointIndex){
   // how to close the same tooltip?
}

I would show sample code if I could, but I don't even know where to start. The chart method docs haven't helped.

JSFiddle

like image 572
BeetleJuice Avatar asked Sep 02 '16 01:09

BeetleJuice


3 Answers

I would be careful accessing/modifying private variables that begin with _. You may find yourself with unexpected behavior. Why not trigger the canvas mousemove event

  function openToolTip (myChart, index) {

    var mouseMoveEvent, meta, point, rectangle, value;

    meta = myChart.getDatasetMeta(0);
    rectangle = myChart.canvas.getBoundingClientRect();
    point = meta.data[index].getCenterPoint();

    mouseMoveEvent = new MouseEvent('mousemove', {
      clientX: rectangle.left + point.x,
      clientY: rectangle.top + point.y
    });
    
    myChart.canvas.dispatchEvent(mouseMoveEvent);

  },

To close the tooltip just trigger the mouseout event

  function closeToolTip (myChart) {

    var mouseOutEvent = new MouseEvent('mouseout');
    return myChart.canvas.dispatchEvent(mouseOutEvent);

  }
like image 151
jwerre Avatar answered Nov 12 '22 15:11

jwerre


The code below will handle one or more tooltips.

function openTip(oChart,datasetIndex,pointIndex){
   if(window.oChart.tooltip._active == undefined)
      window.oChart.tooltip._active = []
   var activeElements = window.oChart.tooltip._active;
   var requestedElem = window.oChart.getDatasetMeta(datasetIndex).data[pointIndex];
   for(var i = 0; i < activeElements.length; i++) {
       if(requestedElem._index == activeElements[i]._index)  
          return;
   }
   activeElements.push(requestedElem);
   //window.oChart.tooltip._view.body = window.oChart.getDatasetMeta(datasetIndex).data;
   window.oChart.tooltip._active = activeElements;
   window.oChart.tooltip.update(true);
   window.oChart.draw();
}

function closeTip(oChart,datasetIndex,pointIndex){
   var activeElements = window.oChart.tooltip._active;
   if(activeElements == undefined || activeElements.length == 0)
     return;
   var requestedElem = window.oChart.getDatasetMeta(datasetIndex).data[pointIndex];
   for(var i = 0; i < activeElements.length; i++) {
       if(requestedElem._index == activeElements[i]._index)  {
          activeElements.splice(i, 1);
          break;
       }
   }
   window.oChart.tooltip._active = activeElements;
   window.oChart.tooltip.update(true);
   window.oChart.draw();
}

Complete solution provided by @BeetleJuice - https://jsfiddle.net/ucvvvnm4/5/

like image 20
Raghav Tandon Avatar answered Nov 12 '22 15:11

Raghav Tandon


For Chart.js@3 here's official solution: https://www.chartjs.org/docs/latest/samples/advanced/programmatic-events.html

function triggerTooltip(chart) {
  const tooltip = chart.tooltip;
  if (tooltip.getActiveElements().length > 0) {
    tooltip.setActiveElements([], {x: 0, y: 0});
  } else {
    const chartArea = chart.chartArea;
    tooltip.setActiveElements([
      {
        datasetIndex: 0,
        index: 2,
      }, {
        datasetIndex: 1,
        index: 2,
      }
    ],
    {
      x: (chartArea.left + chartArea.right) / 2,
      y: (chartArea.top + chartArea.bottom) / 2,
    });
  }

  chart.update();
}
like image 1
Georgiy Bukharov Avatar answered Nov 12 '22 15:11

Georgiy Bukharov