Reputation: 283
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
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