Skip to content

Commit

Permalink
Add onLeave callback to legend
Browse files Browse the repository at this point in the history
  • Loading branch information
jonrimmer committed Feb 9, 2019
1 parent 0ed652b commit b6d8f96
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 4 deletions.
131 changes: 131 additions & 0 deletions samples/legend/callbacks.html
@@ -0,0 +1,131 @@
<!doctype html>
<html>

<head>
<title>Line Chart</title>
<script src="../../../dist/Chart.min.js"></script>
<script src="../utils.js"></script>
<style>
body, html {
height: 100%;
font-family: sans-serif;
}
canvas{
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}

#log {
position: absolute;
right: 0;
top: 0;
bottom: 0;
background-color: #EEE;
float: right;
width: 20%;
padding: 8px;
overflow-y: auto;
white-space: pre;
line-height: 1.5em;
}
</style>
</head>

<body>
<div id="log"></div>
<div style="width:75%;">
<canvas id="canvas"></canvas>
</div>
<script>
var logEntry = 1;
var logElement = document.getElementById('log');

function log(text) {
logElement.innerText += logEntry + '. ' + text + '\n';
logElement.scrollTop = logElement.scrollHeight;
logEntry++;
}

var config = {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
backgroundColor: window.chartColors.red,
borderColor: window.chartColors.red,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
fill: false,
}, {
label: 'My Second dataset',
fill: false,
backgroundColor: window.chartColors.blue,
borderColor: window.chartColors.blue,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}]
},
options: {
legend: {
onHover: function(event, legendItem) {
log('onHover: ' + legendItem.text);
},
onLeave: function(event, legendItem) {
log('onLeave: ' + legendItem.text);
},
onClick: function(event, legendItem) {
log('onClick:' + legendItem.text);
}
},
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
};

window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, config);
};
</script>
</body>

</html>
3 changes: 3 additions & 0 deletions samples/samples.js
Expand Up @@ -148,6 +148,9 @@
}, {
title: 'Point style',
path: 'legend/point-style.html'
}, {
title: 'Callbacks',
path: 'legend/callbacks.html'
}]
}, {
title: 'Tooltip',
Expand Down
25 changes: 21 additions & 4 deletions src/plugins/plugin.legend.js
Expand Up @@ -30,6 +30,7 @@ defaults._set('global', {
},

onHover: null,
onLeave: null,

labels: {
boxWidth: 40,
Expand Down Expand Up @@ -106,6 +107,9 @@ var Legend = Element.extend({
// Contains hit boxes for each dataset (in dataset order)
this.legendHitBoxes = [];

// Contains the currently hovered legend item
this.hoveredItem = null;

// Are we in doughnut mode which has a different data type
this.doughnutMode = false;
},
Expand Down Expand Up @@ -472,7 +476,7 @@ var Legend = Element.extend({
var changed = false;

if (type === 'mousemove') {
if (!opts.onHover) {
if (!opts.onHover && !opts.onLeave) {
return;
}
} else if (type === 'click') {
Expand All @@ -486,6 +490,7 @@ var Legend = Element.extend({
// Chart event already has relative position in it
var x = e.x;
var y = e.y;
var hoveredItem = null;

if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
// See if we are touching one of the dataset boxes
Expand All @@ -495,21 +500,33 @@ var Legend = Element.extend({

if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
// Touching an element
hoveredItem = me.legendItems[i];

if (type === 'click') {
// use e.native for backwards compatibility
opts.onClick.call(me, e.native, me.legendItems[i]);
changed = true;
break;
} else if (type === 'mousemove') {
// use e.native for backwards compatibility
opts.onHover.call(me, e.native, me.legendItems[i]);
changed = true;
if (opts.onHover) {
// use e.native for backwards compatibility
opts.onHover.call(me, e.native, me.legendItems[i]);
changed = true;
}
break;
}
}
}
}

if (type === 'mousemove' && me.hoveredItem !== hoveredItem) {
if (me.hoveredItem) {
opts.onLeave.call(me, e.native, me.hoveredItem);
changed = true;
}
me.hoveredItem = hoveredItem;
}

return changed;
}
});
Expand Down
50 changes: 50 additions & 0 deletions test/specs/plugin.legend.tests.js
Expand Up @@ -11,6 +11,7 @@ describe('Legend block tests', function() {
// a callback that will handle
onClick: jasmine.any(Function),
onHover: null,
onLeave: null,

labels: {
boxWidth: 40,
Expand Down Expand Up @@ -653,4 +654,53 @@ describe('Legend block tests', function() {
expect(chart.legend.options).toEqual(jasmine.objectContaining(Chart.defaults.global.legend));
});
});

describe('callbacks', function() {
it('should call onClick, onHover and onLeave at the correct times', function() {
var clickItem = null;
var hoverItem = null;
var leaveItem = null;

var chart = acquireChart({
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [{
data: [10, 20, 30, 100]
}]
},
options: {
legend: {
onClick: function(_, item) {
clickItem = item;
},
onHover: function(_, item) {
hoverItem = item;
},
onLeave: function(_, item) {
leaveItem = item;
}
}
}
});

var hb = chart.legend.legendHitBoxes[0];
var el = {
x: hb.left + (hb.width / 2),
y: hb.top + (hb.height / 2)
};

jasmine.triggerMouseEvent(chart, 'click', el);

expect(clickItem).toBe(chart.legend.legendItems[0]);

jasmine.triggerMouseEvent(chart, 'mousemove', el);

expect(hoverItem).toBe(chart.legend.legendItems[0]);

jasmine.triggerMouseEvent(chart, 'mousemove', chart.getDatasetMeta(0).data[0]);

expect(leaveItem).toBe(chart.legend.legendItems[0]);
});
});
});

0 comments on commit b6d8f96

Please sign in to comment.