From 9ba01cf721114a2ad025dfcc5a5b4f5fb7b406d0 Mon Sep 17 00:00:00 2001 From: Jon Rimmer Date: Sat, 9 Feb 2019 19:45:46 +0000 Subject: [PATCH 1/9] Add onLeave callback to legend --- samples/legend/callbacks.html | 131 ++++++++++++++++++++++++++++++ samples/samples.js | 3 + src/plugins/plugin.legend.js | 25 +++++- test/specs/plugin.legend.tests.js | 50 ++++++++++++ 4 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 samples/legend/callbacks.html diff --git a/samples/legend/callbacks.html b/samples/legend/callbacks.html new file mode 100644 index 00000000000..bfb7f831005 --- /dev/null +++ b/samples/legend/callbacks.html @@ -0,0 +1,131 @@ + + + + + Line Chart + + + + + + +
+
+ +
+ + + + diff --git a/samples/samples.js b/samples/samples.js index 29ed1ff8190..bb0463f7e6e 100644 --- a/samples/samples.js +++ b/samples/samples.js @@ -148,6 +148,9 @@ }, { title: 'Point style', path: 'legend/point-style.html' + }, { + title: 'Callbacks', + path: 'legend/callbacks.html' }] }, { title: 'Tooltip', diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 2e832f98afd..65394b1d416 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -30,6 +30,7 @@ defaults._set('global', { }, onHover: null, + onLeave: null, labels: { boxWidth: 40, @@ -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; }, @@ -471,7 +475,7 @@ var Legend = Element.extend({ var changed = false; if (type === 'mousemove') { - if (!opts.onHover) { + if (!opts.onHover && !opts.onLeave) { return; } } else if (type === 'click') { @@ -485,6 +489,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 @@ -494,21 +499,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; } }); diff --git a/test/specs/plugin.legend.tests.js b/test/specs/plugin.legend.tests.js index fee715bdb13..e970c596a82 100644 --- a/test/specs/plugin.legend.tests.js +++ b/test/specs/plugin.legend.tests.js @@ -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, @@ -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]); + }); + }); }); From 336d4b2e545cded23c864faa04a78f589c8a9109 Mon Sep 17 00:00:00 2001 From: Jon Rimmer Date: Sat, 9 Feb 2019 23:57:59 +0000 Subject: [PATCH 2/9] Fix field privacy and eixstence check --- src/plugins/plugin.legend.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 65394b1d416..edb0933d490 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -108,7 +108,10 @@ var Legend = Element.extend({ this.legendHitBoxes = []; // Contains the currently hovered legend item - this.hoveredItem = null; + /** + * @private + */ + this._hoveredItem = null; // Are we in doughnut mode which has a different data type this.doughnutMode = false; @@ -518,12 +521,12 @@ var Legend = Element.extend({ } } - if (type === 'mousemove' && me.hoveredItem !== hoveredItem) { - if (me.hoveredItem) { - opts.onLeave.call(me, e.native, me.hoveredItem); + if (opts.onLeave && type === 'mousemove' && me._hoveredItem !== hoveredItem) { + if (me._hoveredItem) { + opts.onLeave.call(me, e.native, me._hoveredItem); changed = true; } - me.hoveredItem = hoveredItem; + me._hoveredItem = hoveredItem; } return changed; From 0d442a72ee0edb52702c3abaeceeacf4b110bdaf Mon Sep 17 00:00:00 2001 From: Jon Rimmer Date: Sun, 10 Feb 2019 00:18:17 +0000 Subject: [PATCH 3/9] Remove comment --- src/plugins/plugin.legend.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index edb0933d490..4cd9d72839a 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -107,7 +107,6 @@ var Legend = Element.extend({ // Contains hit boxes for each dataset (in dataset order) this.legendHitBoxes = []; - // Contains the currently hovered legend item /** * @private */ From 95b9c61827d7eb04156e4a84f7586215817df0e1 Mon Sep 17 00:00:00 2001 From: Jon Rimmer Date: Mon, 11 Feb 2019 23:34:58 +0000 Subject: [PATCH 4/9] Fix comment indentation --- src/plugins/plugin.legend.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 4cd9d72839a..e79eb1af996 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -108,8 +108,8 @@ var Legend = Element.extend({ this.legendHitBoxes = []; /** - * @private - */ + * @private + */ this._hoveredItem = null; // Are we in doughnut mode which has a different data type From 6ee892ae85ea18095c0cc5f08bcb708e2ba5bc0a Mon Sep 17 00:00:00 2001 From: Jon Rimmer Date: Tue, 12 Feb 2019 20:26:42 +0000 Subject: [PATCH 5/9] Fix sample title and path --- samples/legend/callbacks.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/legend/callbacks.html b/samples/legend/callbacks.html index bfb7f831005..06313626e06 100644 --- a/samples/legend/callbacks.html +++ b/samples/legend/callbacks.html @@ -2,8 +2,8 @@ - Line Chart - + Legend Callbacks +