Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2940d95

Browse filesBrowse files
authored
Merge pull request #1646 from plotly/recompute-hover-on-click
Recompute hover on click to increase click robustness
2 parents ffb3791 + 0acdea4 commit 2940d95
Copy full SHA for 2940d95

File tree

5 files changed

+35
-9
lines changed
Filter options

5 files changed

+35
-9
lines changed

‎src/components/fx/click.js

Copy file name to clipboardExpand all lines: src/components/fx/click.js
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,19 @@
99
'use strict';
1010

1111
var Registry = require('../../registry');
12+
var hover = require('./hover').hover;
1213

13-
module.exports = function click(gd, evt) {
14+
module.exports = function click(gd, evt, subplot) {
1415
var annotationsDone = Registry.getComponentMethod('annotations', 'onClick')(gd, gd._hoverdata);
1516

17+
// fallback to fail-safe in case the plot type's hover method doesn't pass the subplot.
18+
// Ternary, for example, didn't, but it was caught because tested.
19+
if(subplot !== undefined) {
20+
// The true flag at the end causes it to re-run the hover computation to figure out *which*
21+
// point is being clicked. Without this, clicking is somewhat unreliable.
22+
hover(gd, evt, subplot, true);
23+
}
24+
1625
function emitClick() { gd.emit('plotly_click', {points: gd._hoverdata, event: evt}); }
1726

1827
if(gd._hoverdata && evt && evt.target) {

‎src/components/fx/hover.js

Copy file name to clipboardExpand all lines: src/components/fx/hover.js
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ var HOVERTEXTPAD = constants.HOVERTEXTPAD;
6666
//
6767
// We wrap the hovers in a timer, to limit their frequency.
6868
// The actual rendering is done by private function _hover.
69-
exports.hover = function hover(gd, evt, subplot) {
69+
exports.hover = function hover(gd, evt, subplot, noHoverEvent) {
7070
if(typeof gd === 'string') gd = document.getElementById(gd);
7171
if(gd._lastHoverTime === undefined) gd._lastHoverTime = 0;
7272

@@ -78,13 +78,13 @@ exports.hover = function hover(gd, evt, subplot) {
7878
// Is it more than 100ms since the last update? If so, force
7979
// an update now (synchronously) and exit
8080
if(Date.now() > gd._lastHoverTime + constants.HOVERMINTIME) {
81-
_hover(gd, evt, subplot);
81+
_hover(gd, evt, subplot, noHoverEvent);
8282
gd._lastHoverTime = Date.now();
8383
return;
8484
}
8585
// Queue up the next hover for 100ms from now (if no further events)
8686
gd._hoverTimer = setTimeout(function() {
87-
_hover(gd, evt, subplot);
87+
_hover(gd, evt, subplot, noHoverEvent);
8888
gd._lastHoverTime = Date.now();
8989
gd._hoverTimer = undefined;
9090
}, constants.HOVERMINTIME);
@@ -168,8 +168,8 @@ exports.loneHover = function loneHover(hoverItem, opts) {
168168
};
169169

170170
// The actual implementation is here:
171-
function _hover(gd, evt, subplot) {
172-
if(subplot === 'pie' || subplot === 'sankey') {
171+
function _hover(gd, evt, subplot, noHoverEvent) {
172+
if((subplot === 'pie' || subplot === 'sankey') && !noHoverEvent) {
173173
gd.emit('plotly_hover', {
174174
event: evt.originalEvent,
175175
points: [evt]
@@ -505,7 +505,7 @@ function _hover(gd, evt, subplot) {
505505
}
506506

507507
// don't emit events if called manually
508-
if(!evt.target || !hoverChanged(gd, evt, oldhoverdata)) return;
508+
if(!evt.target || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
509509

510510
if(oldhoverdata) {
511511
gd.emit('plotly_unhover', {

‎src/plots/cartesian/graph_interact.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/graph_interact.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ module.exports = function initInteractions(gd) {
9797
};
9898

9999
maindrag.onclick = function(evt) {
100-
Fx.click(gd, evt);
100+
Fx.click(gd, evt, subplot);
101101
};
102102

103103
// corner draggers

‎src/plots/ternary/ternary.js

Copy file name to clipboardExpand all lines: src/plots/ternary/ternary.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ proto.initInteractions = function() {
631631
};
632632

633633
dragger.onclick = function(evt) {
634-
Fx.click(gd, evt);
634+
Fx.click(gd, evt, _this.id);
635635
};
636636

637637
dragElement.init(dragOptions);

‎test/jasmine/tests/hover_label_test.js

Copy file name to clipboardExpand all lines: test/jasmine/tests/hover_label_test.js
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,23 @@ describe('hover info', function() {
587587
Plotly.plot(gd, data, layout).then(done);
588588
});
589589

590+
it('should skip the hover event if explicitly instructed', function(done) {
591+
var hoverHandler = jasmine.createSpy();
592+
gd.on('plotly_hover', hoverHandler);
593+
594+
var gdBB = gd.getBoundingClientRect();
595+
var event = {clientX: gdBB.left + 300, clientY: gdBB.top + 200};
596+
597+
Promise.resolve().then(function() {
598+
Fx.hover(gd, event, 'xy', true);
599+
})
600+
.then(function() {
601+
expect(hoverHandler).not.toHaveBeenCalled();
602+
})
603+
.catch(fail)
604+
.then(done);
605+
});
606+
590607
it('should emit events only if the event looks user-driven', function(done) {
591608
var hoverHandler = jasmine.createSpy();
592609
gd.on('plotly_hover', hoverHandler);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.