Flot Tooltips with the Stack Plugin for Bar Graphs

The Stack plugin that comes bundled with Flot is a nice way to create segmented bar graphs whose combined height is the sum of the segments.

http://people.iola.dk/olau/flot/examples/stacking.html

Internally the Stack plugin does this by adjusting the y values in the datapoints array.

Flot also has the ability to create good looking tooltips with some simple javascript like these (make sure to click the Enable Tooltips box)

http://people.iola.dk/olau/flot/examples/interacting.html

I noticed an issue using these in combination, however. Stack adjusts the y values for the points, and tooltip's 'plothover' uses those values when it determines what to write in the tooltip, so your upper segment's tooltip value ends up as the total for the whole bar!


There is a quick fix by looping through the original data set for that particular x value and data set's label. If they match, it uses the original value for the tooltip, which prints the correct smaller value, solving the problem.

The data set is built as a json object in a controller, in the format {data:[[x,y],[x,y]],label:"some label"], etc. The X axis happens to be date values, so note that in the x tooltip section.  The updated tooltip function with the loops looks like this:

$(chart.element).bind("plothover", function (event, pos, item) {
  $("#x").text(pos.x.toFixed(2));
  $("#y").text(pos.y.toFixed(2));
 
  var original_point;
  if (item){
    if (chart.format.series.stack) {
      for (var i = 0; i < chart.data.length; i++) {
        if(chart.data[i].label == item.series.label ){
          for (var j = 0; j < chart.data[1].data.length; j++) {
            if(chart.data[i].data[j][0] == item.datapoint[0]){
              original_point = chart.data[i].data[j][1];
            }
          }
        }
      }   
    }
    $("#tooltip").remove();
    var jsDay = new Date(item.datapoint[0]);
    var x = jsDay.getFullYear() +"/"+(jsDay.getMonth() + 1)+"/"+jsDay.getDate();
    if(original_point != null){
      var y = original_point;
    }
    else{
      var y = item.datapoint[1];
    }
    showTooltip(item.pageX, item.pageY,
    x + " <br>" +  item.series.label + ": " + y);
  }
});