score:15

Accepted answer

to achieve this you can extend the line graph to add an option to show/hide tool-tips on a per dataset basses. the annoying thing is there are only a few changes but whole methods have to be overridden to get the changes in there so the below looks like a lot but its basically 3 changes to the following methods

  • initialize - added option to store showtooltip option in each point

  • getpointsatevent - added check to make sure we want to disaply a tool tip when getting points

  • showtooltip - added check again to make sure we want to dispaly a tool tip

to then use it the chart is set up the same but instead you make it a linetooltip (thats what i have called the extended chart) and pass anextra option in the datasets call showtoolip.

 datasets: [{
        label: "my first dataset",
        fillcolor: "rgba(220,220,220,0.5)",
        strokecolor: "rgba(220,220,220,0.8)",
        highlightfill: "rgba(220,220,220,0.75)",
        highlightstroke: "rgba(220,220,220,1)",
        showtooltip: false, //new option don"t need to include it if you want to display but won"t hurt if you do
        data: [15, 10, 10, 10, 10, 10, 10]
    }, {
        label: "my second dataset",
        fillcolor: "rgba(220,220,220,0.5)",
        strokecolor: "rgba(220,220,220,0.8)",
        highlightfill: "rgba(220,220,220,0.75)",
        highlightstroke: "rgba(220,220,220,1)",
        showtooltip: false, //new option don"t need to include it if you want to display but won"t hurt if you do
        data: [100, 100, 100, 100, 100, 100, 100]
    }, {
        label: "my third dataset",
        fillcolor: "rgba(151,187,205,0.5)",
        strokecolor: "rgba(151,187,205,0.8)",
        highlightfill: "rgba(151,187,205,0.75)",
        highlightstroke: "rgba(151,187,205,1)",
        data: [28, 48, 40, 19, 86, 27, 90]
    }]

i have added bigger comment banners in the below code to try and highlight where the changes got made. i have also added this feature to my fork of chartjs as this could be useful to more people https://github.com/leighquince/chart.js, using this you can just use a normal line chart and add the showtooltip

below is the example of extending the line into a custom chart to include this feature, ive called in linetooltip as but could be called anything you like that.

chart.types.line.extend({

  name: "linetooltip",
  /*
   * we have to add one item in the init so need to rewrite it again here with the one edit
   */
  initialize: function(data) {
    //have to get the helpers as we are using this outside chart where it was declared
    var helpers = chart.helpers;
    //declare the extension of the default point, to cater for the options passed in to the constructor
    this.pointclass = chart.point.extend({
      strokewidth: this.options.pointdotstrokewidth,
      radius: this.options.pointdotradius,
      display: this.options.pointdot,
      hitdetectionradius: this.options.pointhitdetectionradius,
      ctx: this.chart.ctx,
      inrange: function(mousex) {
        return (math.pow(mousex - this.x, 2) < math.pow(this.radius + this.hitdetectionradius, 2));
      }
    });

    this.datasets = [];

    //set up tooltip events on the chart
    if (this.options.showtooltips) {
      helpers.bindevents(this, this.options.tooltipevents, function(evt) {
        var activepoints = (evt.type !== 'mouseout') ? this.getpointsatevent(evt) : [];
        this.eachpoints(function(point) {
          point.restore(['fillcolor', 'strokecolor']);
        });
        helpers.each(activepoints, function(activepoint) {
          activepoint.fillcolor = activepoint.highlightfill;
          activepoint.strokecolor = activepoint.highlightstroke;
        });
        this.showtooltip(activepoints);
      });
    }

    //iterate through each of the datasets, and build this into a property of the chart
    helpers.each(data.datasets, function(dataset) {
      var datasetobject = {
        label: dataset.label || null,
        fillcolor: dataset.fillcolor,
        strokecolor: dataset.strokecolor,
        pointcolor: dataset.pointcolor,
        pointstrokecolor: dataset.pointstrokecolor,
        showtooltip: dataset.showtooltip,
        points: []
      };

      this.datasets.push(datasetobject);


      helpers.each(dataset.data, function(datapoint, index) {
        //add a new point for each piece of data, passing any required data to draw.
        datasetobject.points.push(new this.pointclass({

          /*
           * set wether to show the tooltip or not, left this as being able to be undfined
           * and default to true
           */
          showtooltip: dataset.showtooltip === undefined ? true : dataset.showtooltip,
          value: datapoint,
          label: data.labels[index],
          datasetlabel: dataset.label,
          strokecolor: dataset.pointstrokecolor,
          fillcolor: dataset.pointcolor,
          highlightfill: dataset.pointhighlightfill || dataset.pointcolor,
          highlightstroke: dataset.pointhighlightstroke || dataset.pointstrokecolor
        }));
      }, this);

      this.buildscale(data.labels);


      this.eachpoints(function(point, index) {
        helpers.extend(point, {
          x: this.scale.calculatex(index),
          y: this.scale.endpoint
        });
        point.save();
      }, this);

    }, this);


    this.render();
  },
  /*
   * need to edit how points at event works so it only uses points that we want to show the tool tip for
   */
  getpointsatevent: function(e) {
    //have to get the helpers as we are using this outside chart where it was declared
    var helpers = chart.helpers;
    var pointsarray = [],
      eventposition = helpers.getrelativeposition(e);
    helpers.each(this.datasets, function(dataset) {
      helpers.each(dataset.points, function(point) {
        if (point.inrange(eventposition.x, eventposition.y) && point.showtooltip) pointsarray.push(point);
      });
    }, this);
    return pointsarray;
  },
  /*
   * also need to change how the core showtooltip functions as otherwise, it trys to be helpful
   * and grab any points it thinks also need to be displayed
   */
  showtooltip: function(chartelements, forceredraw) {
    //have to get the helpers as we are using this outside chart where it was declared
    var helpers = chart.helpers;
    var each = helpers.each;
    var indexof = helpers.indexof;
    var min = helpers.min;
    var max = helpers.min;
    // only redraw the chart if we've actually changed what we're hovering on.
    if (typeof this.activeelements === 'undefined') this.activeelements = [];

    var ischanged = (function(elements) {
      var changed = false;

      if (elements.length !== this.activeelements.length) {
        changed = true;
        return changed;
      }

      each(elements, function(element, index) {
        if (element !== this.activeelements[index]) {
          changed = true;
        }
      }, this);
      return changed;
    }).call(this, chartelements);

    if (!ischanged && !forceredraw) {
      return;
    } else {
      this.activeelements = chartelements;
    }
    this.draw();
    if (chartelements.length > 0) {
      // if we have multiple datasets, show a multitooltip for all of the data points at that index
      if (this.datasets && this.datasets.length > 1) {
        var dataarray,
          dataindex;

        for (var i = this.datasets.length - 1; i >= 0; i--) {
          dataarray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
          dataindex = indexof(dataarray, chartelements[0]);
          if (dataindex !== -1) {
            break;
          }
        }
        var tooltiplabels = [],
          tooltipcolors = [],
          medianposition = (function(index) {

            // get all the points at that particular index
            var elements = [],
              datacollection,
              xpositions = [],
              ypositions = [],
              xmax,
              ymax,
              xmin,
              ymin;
            helpers.each(this.datasets, function(dataset) {
              datacollection = dataset.points || dataset.bars || dataset.segments;
              /*
               *check to make sure we want to show the point
               */
              if (datacollection[dataindex] && datacollection[dataindex].hasvalue() && (datacollection[dataindex].showtooltip === undefined || datacollection[dataindex].showtooltip)) {
                elements.push(datacollection[dataindex]);
              }
            });

            helpers.each(elements, function(element) {
              xpositions.push(element.x);
              ypositions.push(element.y);


              //include any colour information about the element
              tooltiplabels.push(helpers.template(this.options.multitooltiptemplate, element));
              tooltipcolors.push({
                fill: element._saved.fillcolor || element.fillcolor,
                stroke: element._saved.strokecolor || element.strokecolor
              });

            }, this);

            ymin = min(ypositions);
            ymax = max(ypositions);

            xmin = min(xpositions);
            xmax = max(xpositions);

            return {
              x: (xmin > this.chart.width / 2) ? xmin : xmax,
              y: (ymin + ymax) / 2
            };
          }).call(this, dataindex);

        new chart.multitooltip({
          x: medianposition.x,
          y: medianposition.y,
          xpadding: this.options.tooltipxpadding,
          ypadding: this.options.tooltipypadding,
          xoffset: this.options.tooltipxoffset,
          fillcolor: this.options.tooltipfillcolor,
          textcolor: this.options.tooltipfontcolor,
          fontfamily: this.options.tooltipfontfamily,
          fontstyle: this.options.tooltipfontstyle,
          fontsize: this.options.tooltipfontsize,
          titletextcolor: this.options.tooltiptitlefontcolor,
          titlefontfamily: this.options.tooltiptitlefontfamily,
          titlefontstyle: this.options.tooltiptitlefontstyle,
          titlefontsize: this.options.tooltiptitlefontsize,
          cornerradius: this.options.tooltipcornerradius,
          labels: tooltiplabels,
          legendcolors: tooltipcolors,
          legendcolorbackground: this.options.multitooltipkeybackground,
          title: chartelements[0].label,
          chart: this.chart,
          ctx: this.chart.ctx
        }).draw();

      } else {
        each(chartelements, function(element) {
          var tooltipposition = element.tooltipposition();
          new chart.tooltip({
            x: math.round(tooltipposition.x),
            y: math.round(tooltipposition.y),
            xpadding: this.options.tooltipxpadding,
            ypadding: this.options.tooltipypadding,
            fillcolor: this.options.tooltipfillcolor,
            textcolor: this.options.tooltipfontcolor,
            fontfamily: this.options.tooltipfontfamily,
            fontstyle: this.options.tooltipfontstyle,
            fontsize: this.options.tooltipfontsize,
            caretheight: this.options.tooltipcaretsize,
            cornerradius: this.options.tooltipcornerradius,
            text: template(this.options.tooltiptemplate, element),
            chart: this.chart
          }).draw();
        }, this);
      }
    }
    return this;
  },

});




var ctx = document.getelementbyid("chart").getcontext("2d");
var data = {
  labels: ["january", "february", "march", "april", "may", "june", "july"],
  datasets: [{
    label: "my first dataset",
    fillcolor: "rgba(220,220,220,0.5)",
    strokecolor: "rgba(220,220,220,0.8)",
    highlightfill: "rgba(220,220,220,0.75)",
    highlightstroke: "rgba(220,220,220,1)",
    showtooltip: false, //to use just add this new option only really needs to present if setting to false
    data: [15, 10, 10, 10, 10, 10, 10]
  }, {
    label: "my second dataset",
    fillcolor: "rgba(220,220,220,0.5)",
    strokecolor: "rgba(220,220,220,0.8)",
    highlightfill: "rgba(220,220,220,0.75)",
    highlightstroke: "rgba(220,220,220,1)",
    showtooltip: false, //to use just add this new option only really needs to present if setting to false
    data: [100, 100, 100, 100, 100, 100, 100]
  }, {
    label: "my third dataset",
    fillcolor: "rgba(151,187,205,0.5)",
    strokecolor: "rgba(151,187,205,0.8)",
    highlightfill: "rgba(151,187,205,0.75)",
    highlightstroke: "rgba(151,187,205,1)",
    data: [28, 48, 40, 19, 86, 27, 90]
  }]
};


var mybarchart = new chart(ctx).linetooltip(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/1.0.2/chart.min.js"></script>
<canvas id="chart" width="600px"></canvas>

and a fiddle if you find that easy to view http://jsfiddle.net/leighking2/1lammwpt/


Related Query

More Query from same tag