ps0604
ps0604

Reputation: 1071

Highcharts plugin: show/hide tooltips on click

In this plunk, when the user clicks on a chart tooltip they make it 'sticky' (i.e. on mouse out the tooltip does not hide). When the tooltip is clicked again, then it disappears. Many tooltips could be displayed simultaneously (until the user clicks on them).

I (unsuccessfully) attempted to achieve this with a Highcharts plugin. Each tooltip has a sticky flag; if the sticky flag is true, then the tooltip shouldn't be hidden on mouse out. If the flag is false, on mouse out the tooltip should disappear (normal behavior).

See below the plugin. Any ideas to make it work?

(function (H) {

    // hide tooltip _only_ if 'sticky' attribute is not set
    H.wrap(H.Tooltip.prototype, 'hide', function (proceed) {
        if (typeof this.sticky === 'undefined' || this.sticky === false)
              proceed.apply(this);
    });


    // on tooltip click, set on the 'sticky' attribute
    H.Chart.prototype.callbacks.push(function (chart) {

            H.addEvent(chart.container, 'click', function (e) {

                // detect here that the tooltip was clicked 
                // and set the 'sticky' attribute
                this.sticky = true;
            });

    });


}(Highcharts));

Upvotes: 0

Views: 1591

Answers (1)

ps0604
ps0604

Reputation: 1071

I made it work in this plunk with a Highcharts plugin. If you click on the tooltip, you make it sticky. Click on it again, and it disappears. Even chart.getSVG() shows the tooltips correctly.

The only issue is that I had to use global variables/functions that I couldn't get rid of, so any input will be appreciated.

Javascript:

var delTooltip = function (series,item) {
    var children = chart.container.firstChild.children;
    for (var i=0;i<children.length;i++) {
        var class2 = children[i].getAttribute('class');
        if (class2 === 'highcharts-tooltip' ) {

        //detect rect with series and item 
        var grandchildren = children[i].children;

        for (var j=0;j<grandchildren.length;j++){
            var series2 = null,
                item2 = null;
            series2 = grandchildren[j].getAttribute('data-series');
            if (typeof series2 !== 'undefined')
              item2 = grandchildren[j].getAttribute('data-item');

             if (item == item2 && series == series2) {
                 chart.container.firstChild.removeChild(children[i]);
                 var temp = chart.options.tooltip.hideDelay;
                 chart.options.tooltip.hideDelay = 0;
                 chart.tooltip.hide();
                 chart.options.tooltip.hideDelay = temp;
             }

           }
         }
     }
 };

 var hoveredPoint = null;
 var chart = null;

$(document).ready(function() {

   (function (H) {

    H.wrap(H.Tooltip.prototype, 'refresh', function (proceed, points) {
        proceed.apply(this, Array.prototype.slice.call(arguments, 1));
        hoveredPoint = { series: points.series.index, item: points.x };
    });

    // on tooltip click, set on the 'sticky' attribute
    H.Chart.prototype.callbacks.push(function (chart) {

            H.addEvent(chart.tooltip.label.element, 'click', function (e) {
                cloneTooltip(chart);
            });

    });

}(Highcharts));



chart = new Highcharts.Chart({
    chart: {
        renderTo: 'container'
    },
    tooltip: {
        animation: false
    },
    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    },

    plotOptions: {
        series: {
            cursor: 'pointer'
        }
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]        
    },{
        data: [19.9, 31.5, 46.4, 229.2, 124.0, 126.0, 125.6, 128.5, 116.4, 294.1, 125.6, 154.4]        
    }]
  });

});


  var cloneTooltip = function(chart){

    var clonedTooltip = chart.tooltip.label.element.cloneNode(true);
    var bb = chart.tooltip.label.element.getBBox();
    var w = bb.width;
    var h = bb.height;

    // create rect with onclick event (g element cannot accept click)
    var svgns = "http://www.w3.org/2000/svg";
    var rect = document.createElementNS(svgns, 'rect');
    rect.setAttributeNS(null, 'x', '0');
    rect.setAttributeNS(null, 'y', '0');
    rect.setAttributeNS(null, 'height', h);
    rect.setAttributeNS(null, 'width', w);
    rect.setAttributeNS(null, 'fill-opacity', '0');
    rect.setAttributeNS(null, 'data-series', hoveredPoint.series);
    rect.setAttributeNS(null, 'data-item', hoveredPoint.item);
    rect.setAttributeNS(null, 'onclick', 'delTooltip(' + hoveredPoint.series + ',' +  hoveredPoint.item + ')');
    clonedTooltip.appendChild(rect);

    chart.container.firstChild.appendChild(clonedTooltip);
};

Upvotes: 1

Related Questions