with my current configs, I can't get tooltips to appear. I am using the latest version of Chart.js, with the latest luxon, and the luxon-chartjs plugin via cdn.
i am using a logarithmic Y axis and cartesian timeline x-axis
i can only get a tooltip to appear when I include a blank callback for label. However, that tooltip that appears only has the unformatted date of the datapoint and no other info. when i ask the label callback to return something, nothing is displayed... when i include a blank callback for title or return anything in the title callback, this works and is displayed. i have hacked together a tooltip but in previous versions I've had no issue with the chart automagically creating these for me.
here is my current code and the working fiddle
let maxArray, correctArray, incorrectArray, objectArray
let yourImage = new Image()
yourImage.src = `https://res.cloudinary.com/behaviorreportcard/image/upload/w_10,h_18,c_scale/v1623785517/Untitled_10_qbwmx4.png`;
let ctx = document.getElementById('myChart').getContext('2d');
Chart.defaults.font.size = '10px';
Chart.defaults.plugins.tooltip.enabled = true
const Interval = luxon.Interval,
DateTime = luxon.DateTime,
Duration = luxon.Duration;
let minTime = "2017-01-19",
maxTime = "2017-04-01",
start = DateTime.fromISO(minTime),
end = DateTime.fromISO(maxTime),
duration = Duration.fromObject({
days: 1
});
function getStart() {
let newStart
if (start.weekday != 7) {
return start.minus({
days: start.weekday
}).toFormat("yyyy-MM-dd")
} else {
return start.toFormat("yyyy-MM-dd")
}
}
let emptyArray = Interval.fromDateTimes(start, end).splitBy(duration).map(t => ({
date: t.s.toFormat("yyyy-MM-dd"),
correct: null,
incorrect: null
}));
let incomingData = [{
date: '2017-01-01',
correct: 10,
incorrect: 20
},
{
date: '2017-01-02',
correct: 10,
incorrect: 0.09
},
{
date: '2017-01-03',
correct: 0.9,
incorrect: null
}, {
date: '2017-01-04',
correct: 3,
incorrect: 0.09
}, {
date: '2017-01-27',
correct: 5,
incorrect: 0.09
}, {
date: '2017-01-28',
correct: 10,
incorrect: null
}, {
date: '2017-02-19',
correct: null,
incorrect: 50
}, {
date: '2017-02-20',
correct: 75,
incorrect: 50
}, {
date: '2017-02-28',
correct: 60,
incorrect: 0.085
}, {
date: '2017-03-01',
correct: 75,
incorrect: null
}, {
date: '2017-03-02',
correct: 10,
incorrect: null
}
]
let returns = []
emptyArray.forEach(x => {
let objToReplace = incomingData.find(o => o.date === x.date)
let objIndex = incomingData.indexOf(objToReplace);
if (objIndex != -1) {
returns.push(incomingData[objIndex])
} else {
returns.push(x)
}
})
let dates = []
let corrects = []
let incorrects = []
let nulls = []
let nullVal = 0.025
returns.forEach(x => {
dates.push(x.date)
if (x.correct != null && x.incorrect != null) {
nulls.push(null)
} else if (x.correct == null && x.incorrect != null) {
nulls.push(nullVal)
}
if (x.incorrect == null) {
incorrects.push(null)
} else {
incorrects.push(x.incorrect)
}
if (x.correct == null) {
corrects.push(null)
} else {
corrects.push(x.correct)
}
})
function returnList(key) {
return returns.map(x => {
return x[key]
})
}
function returnNulls() {
let list = []
returns.forEach(x => {
if ((x.correct != null && x.incorrect == null) || (x.correct == null && x.incorrect != null)) {
list.push(nullVal)
} else {
list.push(null)
}
})
return list
}
console.log(returnNulls())
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: returnList('date'),
datasets: [{
label: 'none',
data: returnNulls(),
spanGaps: false,
pointStyle: yourImage,
},
{
label: 'Corrects',
data: returnList('correct'),
borderWidth: 1,
pointRadius: 5,
spanGaps: false,
fill: false,
borderColor: 'green',
pointStyle: 'circle'
},
{
label: 'Incorrects',
data: returnList('incorrect'),
fill: false,
spanGaps: false,
borderColor: 'red',
pointStyle: 'triangle',
pointRadius: 5,
borderWidth: 1
}
]
},
options: {
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
interaction: {
mode: 'nearest'
},
plugins: {
tooltip: {
enabled: true,
callbacks: {
label: function(item) {},
title: function(item) {
let date = item[0].label.split(',').slice(0, 2).join(',')
let dataSet = item[0].dataset.label
if (dataSet == 'none') {
return
}
return date + '\n' + dataSet
}
}
},
legend: {
display: true,
position: 'bottom',
labels: {
filter: (x, y) => {
if (!x.text.includes('none')) {
return x
}
},
usePointStyle: 'true',
fontColor: 'black',
fontSize: 12
}
},
title: {
display: true,
text: 'Your daily average results for chapter __',
fontColor: 'black',
fontSize: 18,
}
},
scales: {
x: {
ticks: {
font: {
size: 12
}
},
min: getStart(),
max: '2017-03-31',
type: 'time',
time: {
unit: 'day',
stepSize: 7
}
},
y: {
type: 'logarithmic',
max: 100,
min: 0.01,
ticks: {
autoSkip: false,
callback: function(value,
index,
values) {
switch (value) {
case 1:
return '1 per minute';
case 0.1:
return '.1/min';
case 0.01:
return '.01/min';
case 0.001:
return '.001/min';
case 10:
return '10 per min';
case 100:
return '100 per min';
case 1000:
return '1000 per min';
}
},
}
},
},
},
}
);
the HTML
<div id='chart' class='chart' width='400px' height='100%'>
<canvas id="myChart" class='chart' ></canvas>
</div>
and the scripts I'm calling out to
https://cdn.jsdelivr.net/npm/chart.js@3.3.2/dist/chart.min.js
https://cdnjs.cloudflare.com/ajax/libs/luxon/1.27.0/luxon.min.js
https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.1