Skip to content

Commit 923871a

Browse files
committed
Merge pull request #575 from plotly/general-subplot-hover
Generalize hover picking routine
2 parents 476818c + 7ff5ca9 commit 923871a

File tree

6 files changed

+79
-38
lines changed

6 files changed

+79
-38
lines changed

src/plots/cartesian/graph_interact.js

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -310,27 +310,45 @@ function hover(gd, evt, subplot) {
310310

311311
if(!subplot) subplot = 'xy';
312312

313+
// if the user passed in an array of subplots,
314+
// use those instead of finding overlayed plots
315+
var subplots = Array.isArray(subplot) ? subplot : [subplot];
316+
313317
var fullLayout = gd._fullLayout,
314-
plotinfo = fullLayout._plots[subplot],
315-
316-
//If the user passed in an array of subplots, use those instead of finding overlayed plots
317-
subplots = Array.isArray(subplot) ?
318-
subplot :
319-
// list of all overlaid subplots to look at
320-
[subplot].concat(plotinfo.overlays
321-
.map(function(pi) { return pi.id; })),
322-
323-
xaArray = subplots.map(function(spId) {
324-
var ternary = (gd._fullLayout[spId] || {})._ternary;
325-
if(ternary) return ternary.xaxis;
326-
return Axes.getFromId(gd, spId, 'x');
327-
}),
328-
yaArray = subplots.map(function(spId) {
329-
var ternary = (gd._fullLayout[spId] || {})._ternary;
330-
if(ternary) return ternary.yaxis;
331-
return Axes.getFromId(gd, spId, 'y');
332-
}),
333-
hovermode = evt.hovermode || fullLayout.hovermode;
318+
plots = fullLayout._plots || [],
319+
plotinfo = plots[subplot];
320+
321+
// list of all overlaid subplots to look at
322+
if(plotinfo) {
323+
var overlayedSubplots = plotinfo.overlays.map(function(pi) {
324+
return pi.id;
325+
});
326+
327+
subplots = subplots.concat(overlayedSubplots);
328+
}
329+
330+
var len = subplots.length,
331+
xaArray = new Array(len),
332+
yaArray = new Array(len);
333+
334+
for(var i = 0; i < len; i++) {
335+
var spId = subplots[i];
336+
337+
// 'cartesian' case
338+
var plotObj = plots[spId];
339+
if(plotObj) {
340+
xaArray[i] = plotObj.xaxis;
341+
yaArray[i] = plotObj.yaxis;
342+
continue;
343+
}
344+
345+
// other subplot types
346+
var _subplot = fullLayout[spId]._subplot;
347+
xaArray[i] = _subplot.xaxis;
348+
yaArray[i] = _subplot.yaxis;
349+
}
350+
351+
var hovermode = evt.hovermode || fullLayout.hovermode;
334352

335353
if(['x', 'y', 'closest'].indexOf(hovermode) === -1 || !gd.calcdata ||
336354
gd.querySelector('.zoombox') || gd._dragging) {

src/plots/ternary/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ exports.plot = function plotTernary(gd) {
3838
for(var i = 0; i < ternaryIds.length; i++) {
3939
var ternaryId = ternaryIds[i],
4040
fullTernaryData = Plots.getSubplotData(fullData, 'ternary', ternaryId),
41-
ternary = fullLayout[ternaryId]._ternary;
41+
ternary = fullLayout[ternaryId]._subplot;
4242

4343
// If ternary is not instantiated, create one!
4444
if(ternary === undefined) {
@@ -50,7 +50,7 @@ exports.plot = function plotTernary(gd) {
5050
fullLayout
5151
);
5252

53-
fullLayout[ternaryId]._ternary = ternary;
53+
fullLayout[ternaryId]._subplot = ternary;
5454
}
5555

5656
ternary.plot(fullTernaryData, fullLayout, gd._promises);
@@ -62,7 +62,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
6262

6363
for(var i = 0; i < oldTernaryKeys.length; i++) {
6464
var oldTernaryKey = oldTernaryKeys[i];
65-
var oldTernary = oldFullLayout[oldTernaryKey]._ternary;
65+
var oldTernary = oldFullLayout[oldTernaryKey]._subplot;
6666

6767
if(!newFullLayout[oldTernaryKey] && !!oldTernary) {
6868
oldTernary.plotContainer.remove();

src/plots/ternary/ternary.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -675,19 +675,6 @@ proto.initInteractions = function() {
675675
dragger.onclick = function(evt) {
676676
fx.click(gd, evt);
677677
};
678-
679-
// make a fake plotinfo for fx.hover
680-
// it hardly uses it, could probably be refactored out...
681-
// but specifying subplot by name does seem nice for js applications
682-
// that want to hook into this.
683-
if(!gd._fullLayout._plots) gd._fullLayout._plots = {};
684-
gd._fullLayout._plots[_this.id] = {
685-
overlays: [],
686-
xaxis: _this.xaxis,
687-
yaxis: _this.yaxis,
688-
x: function() { return _this.xaxis; },
689-
y: function() { return _this.yaxis; }
690-
};
691678
};
692679

693680
function removeZoombox(gd) {

src/traces/scatterternary/plot.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@ var scatterPlot = require('../scatter/plot');
1313

1414

1515
module.exports = function plot(ternary, data) {
16+
var plotContainer = ternary.plotContainer;
17+
18+
// remove all nodes inside the scatter layer
19+
plotContainer.select('.scatterlayer').selectAll('*').remove();
20+
1621
// mimic cartesian plotinfo
1722
var plotinfo = {
1823
x: function() { return ternary.xaxis; },
1924
y: function() { return ternary.yaxis; },
20-
plot: ternary.plotContainer
25+
plot: plotContainer
2126
};
2227

2328
var calcdata = new Array(data.length),

test/jasmine/tests/hover_label_test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,34 @@ describe('hover info on stacked subplots', function() {
574574
});
575575
});
576576
});
577+
578+
579+
describe('hover info on overlaid subplots', function() {
580+
'use strict';
581+
582+
afterEach(destroyGraphDiv);
583+
584+
it('should respond to hover', function(done) {
585+
var mock = require('@mocks/autorange-tozero-rangemode.json');
586+
587+
Plotly.plot(createGraphDiv(), mock.data, mock.layout).then(function() {
588+
mouseEvent('mousemove', 775, 352);
589+
590+
var axisText = d3.selectAll('g.axistext'),
591+
hoverText = d3.selectAll('g.hovertext');
592+
593+
expect(axisText.size()).toEqual(1, 'with 1 label on axis');
594+
expect(hoverText.size()).toEqual(2, 'with 2 labels on the overlaid pts');
595+
596+
expect(axisText.select('text').html()).toEqual('1', 'with correct axis label');
597+
598+
var textNodes = hoverText.selectAll('text');
599+
600+
expect(textNodes[0][0].innerHTML).toEqual('Take Rate', 'with correct hover labels');
601+
expect(textNodes[0][1].innerHTML).toEqual('0.35', 'with correct hover labels');
602+
expect(textNodes[1][0].innerHTML).toEqual('Revenue', 'with correct hover labels');
603+
expect(textNodes[1][1].innerHTML).toEqual('2,352.5', 'with correct hover labels');
604+
605+
}).then(done);
606+
});
607+
});

test/jasmine/tests/scatterternary_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ describe('scatterternary hover', function() {
285285

286286
beforeEach(function() {
287287
var cd = gd.calcdata,
288-
ternary = gd._fullLayout.ternary._ternary;
288+
ternary = gd._fullLayout.ternary._subplot;
289289

290290
pointData = {
291291
index: false,

0 commit comments

Comments
 (0)