dchadney
dchadney

Reputation: 283

Chart.js - custom tooltip with multiple values

I have a bar chart that I want to display a second label in the tooltip box that will be populated from my database. You can see from my code below that I have started to set it up so that multiple labels can be displayed in the tooltips (short,long) and also I want to be able to show multiple values coming from my database as labels.

For example I have a bridge ID of 135554 (bridge_id_grab) and that bridge is 35 years old (bridge_age_grab) and is located at milepost 13.34 (bridge_mp_grab).

So I want this to display in the tooltip as

"Bridge ID: 135554, Bridge Age: 35, Milepost: 13.34"

I think I am close - just can't figure out how to use get just one value for bridge_mp_grab - it's showing as a string of all the values in the database.

Here is my code:

             function Label(short, long) {
              this.short = short;
              this.long = long
             }
             Label.prototype.toString = function() {
              return this.short;
             }

        var barChartData2 = {
            //labels : bridge_id_grab,
            labels: [ 
              new Label("J", bridge_mp_grab), 
              new Label("F", "FEB"), 
              new Label("M", "MAR"),
              new Label("A", "APR"),
              new Label("M", "MAY"),
              new Label("J", "JUN"),
              new Label("J", "JUL")
            ],
            datasets : [
                {
                    label: "My First dataset",
                    fillColor : ["rgba(220,220,220,0.5)"],
                    strokeColor : "rgba(151,187,205,1)",
                    pointColor : "rgba(151,187,205,1)",
                    pointStrokeColor : "#fff",
                    data : bridge_age_grab,
                }
            ]
          }

            var context = document.getElementById('serviceLife').getContext('2d');

             window.myObjBar2 = new Chart(context).Bar(barChartData2, {
                scaleOverride : true,
                scaleSteps : 10,
                scaleStepWidth : 10,
                scaleStartValue : 0,
                barShowStroke: false,
                barStrokeWidth : 0,
                barValueSpacing : 2,
                 customTooltips: function (tooltip) {
                        var tooltipEl = $('#chartjs-tooltip');

                        if (!tooltip) {
                            tooltipEl.css({
                                opacity: 0
                            });
                            return;
                        }

                        // split out the label and value and make your own tooltip here
                        var parts = tooltip.text.split(":");
                        var re = new RegExp('\b', 'g');
                        var innerHtml = '<span><b>' + parts[1].trim() + '</b></span>';
                        tooltipEl.html(innerHtml);

                        tooltipEl.css({
                            opacity: 1,
                            // the minimum amount is half the maximum width of the tooltip that we set in CSS ...
                            // ... + the x scale padding so that it's not right at the edge
                            left: Math.max(75 + 10, tooltip.chart.canvas.offsetLeft + tooltip.x) + 'px',
                            top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
                            fontFamily: tooltip.fontFamily,
                            fontSize: tooltip.fontSize,
                            fontStyle: tooltip.fontStyle,
                        });
                    },
                animation: false,
                responsive: true,
                tooltipTemplate: "<%if (label){%><%=value%>: <%}%><%= label.long %>",
                maintainAspectRatio: true,
               onAnimationComplete: function () {

                    var ctx = this.chart.ctx;
                    ctx.font = this.scale.font;
                    ctx.fillStyle = this.scale.textColor
                    ctx.textAlign = "center";
                    ctx.textBaseline = "bottom";

                    this.datasets.forEach(function (dataset) {
                        dataset.bars.forEach(function (bar) {
                            ctx.fillText(bar.value, bar.x, bar.y - 5);
                        });
                    })
                }
            });

             var bars = myObjBar2.datasets[0].bars;
            for(i=0;i<bars.length;i++){
               var color="#07c602";
               //You can check for bars[i].value and put your conditions here

               if(bars[i].value<11){
                color="#07c602"
               }    
               else if(bars[i].value<21){
                color="#61e738"
               }    
               else if(bars[i].value<31){
                color="#b6f277"
               }    
               else if(bars[i].value<41){
                color="#ffffb2"
               }    
               else if(bars[i].value<51){
                color="#fed976"
               }    
               else if(bars[i].value<61){
                color="#feb24c"
               }                  
               else if(bars[i].value<71){
                color="#fd8d3c"
               }
               else if(bars[i].value<81){
                color="#fc4e2a"
               }                  
               else if(bars[i].value<91){
                color="#e31a1c"
               }
               else{
                color="#b10026"
               }

               bars[i].fillColor = color;

            }
            myObjBar2.update(); 

Here is a couple of fiddles that I am using as reference: https://jsfiddle.net/gf3g4b55/ http://jsfiddle.net/tpydnyx6/

Upvotes: 2

Views: 14974

Answers (1)

blurfus
blurfus

Reputation: 14041

I am not 100% sure of the desired output but this is my take.

In short, when you define your own customTooltips you are overriding the default tooltipTemplate stated in the options.

So, removing the customTooltips and defining an output format for the template yields the (I think) desired results.

To accomplish the output neatly, however, I added a new object called DataPoint and defined as this:

function DataPoint(id, age, milepost) {
    this.id = id;
    this.age = age;
    this.milepost = milepost;
    this.tooltip = "Bridge ID:" + id + ", Bridge Age: " + age +", Milepost: " + milepost;
}

DataPoint.prototype.toString = function () {
        return this.id;
};

This allows me to contain all the necessary data bits into one object (and then I only manipulate an array of those instead of multiple arrays)

Then, you set up your array of objects as your Labels for the table

 var barChartData2 = {
        labels: bridgeDataPoints, /* this is the array of DataPoints */
        datasets: [{
            fillColor: ["rgba(220,220,220,0.5)"],
            strokeColor: "rgba(151,187,205,1)",
            pointColor: "rgba(151,187,205,1)",
            pointStrokeColor: "#fff",
            data: bridge_age_grab,
        }]
    };

Finally, the tooltipTemplate was defined as follows:

OLD Version (prior to v3)

tooltipTemplate: "<%if (label){%><%=label.tooltip%><%}%>",

UPDATE: NEW for ChartJS v3

put it inside options object.

options: {
          tooltips: {
            callbacks: {
              label: function(tooltipItem, data) {
                  // console.log(tooltipItem);
                  // return 'id: ' + tooltipItem.xLabel.id+' | '+' age: '+tooltipItem.xLabel.age;
                },
                title: function(tooltipItem, data) {
                    // return 'Date: ' + tooltipItem[0].xLabel.date;
                    return 'id: ' + tooltipItem[0].xLabel.id+'\nage: ' + tooltipItem[0].xLabel.age;
                }
            }
          }
// try out your combinations
}

which means, if a label exists for each element, display the tooltip property for it. Since we defined the tooltip property for our DataPoint elements as this.tooltip = "Bridge ID:" + id + ", Bridge Age: " + age +", Milepost: " + milepost; the desired output is obtained.

Let me know if this helps.

See the updated fiddle here

Upvotes: 6

Related Questions