]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Update tooltip when the display position changes (#7469)
authorEvert Timberg <evert.timberg+github@gmail.com>
Thu, 25 Jun 2020 17:51:34 +0000 (13:51 -0400)
committerGitHub <noreply@github.com>
Thu, 25 Jun 2020 17:51:34 +0000 (13:51 -0400)
src/plugins/plugin.tooltip.js
test/specs/plugin.tooltip.tests.js

index 4016fd808cd2e630789535c8798130155716f1fc..6f239f64be3b2426029212b945e50f442a037be2 100644 (file)
@@ -1023,8 +1023,14 @@ export class Tooltip extends Element {
                        }
                }
 
+               // When there are multiple items shown, but the tooltip position is nearest mode
+               // an update may need to be made because our position may have changed even though
+               // the items are the same as before.
+               const position = positioners[options.position].call(me, active, e);
+               const positionChanged = this.caretX !== position.x || this.caretY !== position.y;
+
                // Remember Last Actives
-               changed = replay || !_elementsEqual(active, lastActive);
+               changed = replay || !_elementsEqual(active, lastActive) || positionChanged;
 
                // Only handle target event on tooltip change
                if (changed) {
index 3ead8db7bfc2de32e64da5c7c5a8d4134376553f..3478102b2d71e7331b44a44c0856c6b57a76ec5e 100644 (file)
@@ -884,7 +884,7 @@ describe('Core.Tooltip', function() {
                var firstPoint = meta.data[1];
 
                var tooltip = chart.tooltip;
-               spyOn(tooltip, 'update');
+               spyOn(tooltip, 'update').and.callThrough();
 
                afterEvent(chart, 'mousemove', function() {
                        expect(tooltip.update).toHaveBeenCalledWith(true);
@@ -904,6 +904,74 @@ describe('Core.Tooltip', function() {
                jasmine.triggerMouseEvent(chart, 'mousemove', firstPoint);
        });
 
+       it('Should update if active elements are the same, but the position has changed', function(done) {
+               const chart = window.acquireChart({
+                       type: 'line',
+                       data: {
+                               datasets: [{
+                                       label: 'Dataset 1',
+                                       data: [10, 20, 30],
+                                       pointHoverBorderColor: 'rgb(255, 0, 0)',
+                                       pointHoverBackgroundColor: 'rgb(0, 255, 0)'
+                               }, {
+                                       label: 'Dataset 2',
+                                       data: [40, 40, 40],
+                                       pointHoverBorderColor: 'rgb(0, 0, 255)',
+                                       pointHoverBackgroundColor: 'rgb(0, 255, 255)'
+                               }],
+                               labels: ['Point 1', 'Point 2', 'Point 3']
+                       },
+                       options: {
+                               scales: {
+                                       x: {
+                                               stacked: true,
+                                       },
+                                       y: {
+                                               stacked: true
+                                       }
+                               },
+                               tooltips: {
+                                       mode: 'nearest',
+                                       position: 'nearest',
+                                       intersect: true,
+                                       callbacks: {
+                                               title: function() {
+                                                       return 'registering callback...';
+                                               }
+                                       }
+                               }
+                       }
+               });
+
+               // Trigger an event over top of the
+               const meta = chart.getDatasetMeta(0);
+               const firstPoint = meta.data[1];
+
+               const meta2 = chart.getDatasetMeta(1);
+               const secondPoint = meta2.data[1];
+
+               const tooltip = chart.tooltip;
+               spyOn(tooltip, 'update');
+
+               afterEvent(chart, 'mousemove', function() {
+                       expect(tooltip.update).toHaveBeenCalledWith(true);
+
+                       // Reset calls
+                       tooltip.update.calls.reset();
+
+                       afterEvent(chart, 'mousemove', function() {
+                               expect(tooltip.update).toHaveBeenCalledWith(true);
+
+                               done();
+                       });
+                       // Second dispatch change event (same event), should update tooltip
+                       // because position mode is 'nearest'
+                       jasmine.triggerMouseEvent(chart, 'mousemove', secondPoint);
+               });
+               // First dispatch change event, should update tooltip
+               jasmine.triggerMouseEvent(chart, 'mousemove', firstPoint);
+       });
+
        describe('positioners', function() {
                it('Should call custom positioner with correct parameters and scope', function(done) {
 
@@ -945,7 +1013,7 @@ describe('Core.Tooltip', function() {
                        var fn = tooltipPlugin.positioners.test;
 
                        afterEvent(chart, 'mousemove', function() {
-                               expect(fn.calls.count()).toBe(1);
+                               expect(fn.calls.count()).toBe(2);
                                expect(fn.calls.first().args[0] instanceof Array).toBe(true);
                                expect(Object.prototype.hasOwnProperty.call(fn.calls.first().args[1], 'x')).toBe(true);
                                expect(Object.prototype.hasOwnProperty.call(fn.calls.first().args[1], 'y')).toBe(true);