diff --git a/draftlogs/5854_fix.md b/draftlogs/5854_fix.md new file mode 100644 index 00000000000..27de7da558a --- /dev/null +++ b/draftlogs/5854_fix.md @@ -0,0 +1 @@ +- Skip `"hoverinfo": "none"` trace display for hover modes [[#5854](https://github.com/plotly/plotly.js/pull/5854)], with thanks to @Domino987 for the contribution! diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index e9e92749801..6a8c8e9ea54 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -818,6 +818,8 @@ function createHoverText(hoverData, opts, gd) { var container = opts.container; var outerContainer = opts.outerContainer; var commonLabelOpts = opts.commonLabelOpts || {}; + // Early exit if no labels are drawn + if(hoverData.length === 0) return [[]]; // opts.fontFamily/Size are used for the common label // and as defaults for each hover label, though the individual labels @@ -1024,9 +1026,9 @@ function createHoverText(hoverData, opts, gd) { if(helpers.isUnifiedHover(hovermode)) { // Delete leftover hover labels from other hovermodes container.selectAll('g.hovertext').remove(); - + var groupedHoverData = hoverData.filter(function(data) {return data.hoverinfo !== 'none';}); // Return early if nothing is hovered on - if(hoverData.length === 0) return; + if(groupedHoverData.length === 0) return; // mock legend var mockLayoutIn = { @@ -1048,11 +1050,14 @@ function createHoverText(hoverData, opts, gd) { // prepare items for the legend mockLegend.entries = []; - for(var j = 0; j < hoverData.length; j++) { - var texts = getHoverLabelText(hoverData[j], true, hovermode, fullLayout, t0); + for(var j = 0; j < groupedHoverData.length; j++) { + var pt = groupedHoverData[j]; + if(pt.hoverinfo === 'none') continue; + + var texts = getHoverLabelText(pt, true, hovermode, fullLayout, t0); var text = texts[0]; var name = texts[1]; - var pt = hoverData[j]; + pt.name = name; if(name !== '') { pt.text = name + ' : ' + text; @@ -1087,7 +1092,7 @@ function createHoverText(hoverData, opts, gd) { var tbb = legendContainer.node().getBoundingClientRect(); var tWidth = tbb.width + 2 * HOVERTEXTPAD; var tHeight = tbb.height + 2 * HOVERTEXTPAD; - var winningPoint = hoverData[0]; + var winningPoint = groupedHoverData[0]; var avgX = (winningPoint.x0 + winningPoint.x1) / 2; var avgY = (winningPoint.y0 + winningPoint.y1) / 2; // When a scatter (or e.g. heatmap) point wins, it's OK for the hovelabel to occlude the bar and other points. @@ -1102,11 +1107,11 @@ function createHoverText(hoverData, opts, gd) { lyTop = avgY - HOVERTEXTPAD; lyBottom = avgY + HOVERTEXTPAD; } else { - lyTop = Math.min.apply(null, hoverData.map(function(c) { return Math.min(c.y0, c.y1); })); - lyBottom = Math.max.apply(null, hoverData.map(function(c) { return Math.max(c.y0, c.y1); })); + lyTop = Math.min.apply(null, groupedHoverData.map(function(c) { return Math.min(c.y0, c.y1); })); + lyBottom = Math.max.apply(null, groupedHoverData.map(function(c) { return Math.max(c.y0, c.y1); })); } } else { - lyTop = lyBottom = Lib.mean(hoverData.map(function(c) { return (c.y0 + c.y1) / 2; })) - tHeight / 2; + lyTop = lyBottom = Lib.mean(groupedHoverData.map(function(c) { return (c.y0 + c.y1) / 2; })) - tHeight / 2; } var lxRight, lxLeft; @@ -1115,11 +1120,11 @@ function createHoverText(hoverData, opts, gd) { lxRight = avgX + HOVERTEXTPAD; lxLeft = avgX - HOVERTEXTPAD; } else { - lxRight = Math.max.apply(null, hoverData.map(function(c) { return Math.max(c.x0, c.x1); })); - lxLeft = Math.min.apply(null, hoverData.map(function(c) { return Math.min(c.x0, c.x1); })); + lxRight = Math.max.apply(null, groupedHoverData.map(function(c) { return Math.max(c.x0, c.x1); })); + lxLeft = Math.min.apply(null, groupedHoverData.map(function(c) { return Math.min(c.x0, c.x1); })); } } else { - lxRight = lxLeft = Lib.mean(hoverData.map(function(c) { return (c.x0 + c.x1) / 2; })) - tWidth / 2; + lxRight = lxLeft = Lib.mean(groupedHoverData.map(function(c) { return (c.x0 + c.x1) / 2; })) - tWidth / 2; } var xOffset = xa._offset; diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 9ceeba1bcb2..69db628b1b6 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -4601,6 +4601,38 @@ describe('hovermode: (x|y)unified', function() { .then(done, done.fail); }); + it('should not display hover for display: none', function(done) { + Plotly.newPlot(gd, { + data: [{ + name: 'A', + y: [1] + }, { + name: 'B', + y: [2], + hoverinfo: 'none' + }], + layout: { + hovermode: 'x unified', + showlegend: false, + width: 500, + height: 500, + margin: { + t: 50, + b: 50, + l: 50, + r: 50 + } + } + }) + .then(function() { + _hover(gd, { xpx: 200, ypx: 200 }); + assertLabel({title: '0', items: [ + 'A : 1' + ]}); + }) + .then(done, done.fail); + }); + it('y unified should work for x/y cartesian traces', function(done) { var mockCopy = Lib.extendDeep({}, mock); mockCopy.layout.hovermode = 'y unified';