diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index a568c503f8d..947285096dd 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -14,7 +14,6 @@ var Drawing = require('../drawing'); var Color = require('../color'); var dragElement = require('../dragelement'); var Axes = require('../../plots/cartesian/axes'); -var alignPeriod = require('../../plots/cartesian/align_period'); var Registry = require('../../registry'); var helpers = require('./helpers'); @@ -491,6 +490,7 @@ function _hover(gd, evt, subplot, noHoverEvent) { if(hoverdistance !== 0) { if(trace._module && trace._module.hoverPoints) { var newPoints = trace._module.hoverPoints(pointData, xval, yval, _mode, { + finiteRange: true, hoverLayer: fullLayout._hoverlayer }); @@ -643,10 +643,13 @@ function _hover(gd, evt, subplot, noHoverEvent) { } } - hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; }); + var sortHoverData = function() { + hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; }); - // move period positioned points to the end of list - hoverData = orderPeriod(hoverData, hovermode); + // move period positioned points and box/bar-like traces to the end of the list + hoverData = orderRangePoints(hoverData, hovermode); + }; + sortHoverData(); // If in compare mode, select every point at position if( @@ -654,7 +657,6 @@ function _hover(gd, evt, subplot, noHoverEvent) { hoverData[0].length !== 0 && hoverData[0].trace.type !== 'splom' // TODO: add support for splom ) { - var initLen = hoverData.length; var winningPoint = hoverData[0]; var customXVal = customVal('x', winningPoint, fullLayout); @@ -662,61 +664,30 @@ function _hover(gd, evt, subplot, noHoverEvent) { findHoverPoints(customXVal, customYVal); - // also find start, middle and end point for period - var axLetter = hovermode.charAt(0); - if(winningPoint.trace[axLetter + 'period']) { - var v = winningPoint[axLetter + 'LabelVal']; - var ax = winningPoint[axLetter + 'a']; - var T = {}; - T[axLetter + 'period'] = winningPoint.trace[axLetter + 'period']; - T[axLetter + 'period0'] = winningPoint.trace[axLetter + 'period0']; - - T[axLetter + 'periodalignment'] = 'start'; - var start = alignPeriod(T, ax, axLetter, [v])[0]; - - T[axLetter + 'periodalignment'] = 'middle'; - var middle = alignPeriod(T, ax, axLetter, [v])[0]; - - T[axLetter + 'periodalignment'] = 'end'; - var end = alignPeriod(T, ax, axLetter, [v])[0]; - - if(axLetter === 'x') { - findHoverPoints(start, customYVal); - findHoverPoints(middle, customYVal); - findHoverPoints(end, customYVal); - } else { - findHoverPoints(customXVal, start); - findHoverPoints(customXVal, middle); - findHoverPoints(customXVal, end); - } - - var k; - var seen = {}; - for(k = 0; k < initLen; k++) { - seen[hoverData[k].trace.index] = true; + var finalPoints = []; + var seen = {}; + var insert = function(hd) { + var type = hd.trace.type; + var key = ( + type === 'box' || + type === 'violin' || + type === 'ohlc' || + type === 'candlestick' + ) ? hoverDataKey(hd) : hd.trace.index; + if(!seen[key]) { + seen[key] = true; + finalPoints.push(hd); } + }; - // remove non-period aditions and traces that seen before - for(k = hoverData.length - 1; k >= initLen; k--) { - if( - seen[hoverData[k].trace.index] || - !hoverData[k].trace[axLetter + 'period'] - ) { - hoverData.splice(k, 1); - } - } + // insert the winnig point first + insert(winningPoint); + // override from the end + for(var k = hoverData.length - 1; k > 0; k--) { + insert(hoverData[k]); } - - // Remove duplicated hoverData points - // note that d3 also filters identical points in the rendering steps - var repeated = {}; - hoverData = hoverData.filter(function(hd) { - var key = hoverDataKey(hd); - if(!repeated[key]) { - repeated[key] = true; - return repeated[key]; - } - }); + hoverData = finalPoints; + sortHoverData(); } // lastly, emit custom hover/unhover events @@ -820,9 +791,7 @@ function createHoverText(hoverData, opts, gd) { var xa = c0.xa; var ya = c0.ya; var axLetter = hovermode.charAt(0); - var v0 = c0[axLetter + 'LabelVal']; var t0 = c0[axLetter + 'Label']; - var t00 = (String(t0) || '').split(' ')[0]; var outerContainerBB = outerContainer.node().getBoundingClientRect(); var outerTop = outerContainerBB.top; var outerWidth = outerContainerBB.width; @@ -1011,44 +980,13 @@ function createHoverText(hoverData, opts, gd) { } label.attr('transform', strTranslate(lx, ly)); - - // remove the "close but not quite" points - // because of error bars, only take up to a space - hoverData = filterClosePoints(hoverData); }); - function filterClosePoints(hoverData) { - return hoverData.filter(function(d) { - if(d.zLabelVal !== undefined) return true; - if((d[axLetter + 'Label'] || '').split(' ')[0] === t00) return true; - if(d.trace[axLetter + 'period']) { - var v = d[axLetter + 'LabelVal']; - var ax = d[axLetter + 'a']; - var trace = {}; - trace[axLetter + 'period'] = d.trace[axLetter + 'period']; - trace[axLetter + 'period0'] = d.trace[axLetter + 'period0']; - - trace[axLetter + 'periodalignment'] = 'start'; - var start = alignPeriod(trace, ax, axLetter, [v])[0]; - - trace[axLetter + 'periodalignment'] = 'end'; - var end = alignPeriod(trace, ax, axLetter, [v])[0]; - - if(v0 >= start && v0 < end) return true; - } - - return false; - }); - } - // Show a single hover label if(helpers.isUnifiedHover(hovermode)) { // Delete leftover hover labels from other hovermodes container.selectAll('g.hovertext').remove(); - // similarly to compare mode, we remove the "close but not quite together" points - if((t0 !== undefined) && (c0.distance <= opts.hoverdistance)) hoverData = filterClosePoints(hoverData); - // Return early if nothing is hovered on if(hoverData.length === 0) return; @@ -1929,23 +1867,29 @@ function plainText(s, len) { }); } -function orderPeriod(hoverData, hovermode) { +function orderRangePoints(hoverData, hovermode) { var axLetter = hovermode.charAt(0); var first = []; + var second = []; var last = []; for(var i = 0; i < hoverData.length; i++) { var d = hoverData[i]; - if(d.trace[axLetter + 'period']) { + if( + Registry.traceIs(d.trace, 'bar-like') || + Registry.traceIs(d.trace, 'box-violin') + ) { last.push(d); + } else if(d.trace[axLetter + 'period']) { + second.push(d); } else { first.push(d); } } - return first.concat(last); + return first.concat(second).concat(last); } function customVal(axLetter, winningPoint, fullLayout) { diff --git a/src/traces/bar/hover.js b/src/traces/bar/hover.js index 93539145d3e..2c0ba4d86ba 100644 --- a/src/traces/bar/hover.js +++ b/src/traces/bar/hover.js @@ -9,8 +9,8 @@ var getLineWidth = require('./helpers').getLineWidth; var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText; var BADNUM = require('../../constants/numerical').BADNUM; -function hoverPoints(pointData, xval, yval, hovermode) { - var barPointData = hoverOnBars(pointData, xval, yval, hovermode); +function hoverPoints(pointData, xval, yval, hovermode, opts) { + var barPointData = hoverOnBars(pointData, xval, yval, hovermode, opts); if(barPointData) { var cd = barPointData.cd; @@ -24,7 +24,7 @@ function hoverPoints(pointData, xval, yval, hovermode) { } } -function hoverOnBars(pointData, xval, yval, hovermode) { +function hoverOnBars(pointData, xval, yval, hovermode, opts) { var cd = pointData.cd; var trace = cd[0].trace; var t = cd[0].t; @@ -67,6 +67,8 @@ function hoverOnBars(pointData, xval, yval, hovermode) { }; function inbox(_minPos, _maxPos, maxDistance) { + if(opts.finiteRange) maxDistance = 0; + // add a little to the pseudo-distance for wider bars, so that like scatter, // if you are over two overlapping bars, the narrower one wins. return Fx.inbox(_minPos - posVal, _maxPos - posVal, diff --git a/src/traces/funnel/hover.js b/src/traces/funnel/hover.js index 02687c1921e..21493dcb208 100644 --- a/src/traces/funnel/hover.js +++ b/src/traces/funnel/hover.js @@ -4,8 +4,8 @@ var opacity = require('../../components/color').opacity; var hoverOnBars = require('../bar/hover').hoverOnBars; var formatPercent = require('../../lib').formatPercent; -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var point = hoverOnBars(pointData, xval, yval, hovermode); +module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) { + var point = hoverOnBars(pointData, xval, yval, hovermode, opts); if(!point) return; var cd = point.cd; diff --git a/src/traces/histogram/hover.js b/src/traces/histogram/hover.js index 317c632e984..8b3f26e20c1 100644 --- a/src/traces/histogram/hover.js +++ b/src/traces/histogram/hover.js @@ -3,8 +3,8 @@ var barHover = require('../bar/hover').hoverPoints; var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText; -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var pts = barHover(pointData, xval, yval, hovermode); +module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) { + var pts = barHover(pointData, xval, yval, hovermode, opts); if(!pts) return; diff --git a/src/traces/ohlc/hover.js b/src/traces/ohlc/hover.js index e189c828733..5800303db40 100644 --- a/src/traces/ohlc/hover.js +++ b/src/traces/ohlc/hover.js @@ -23,7 +23,7 @@ function hoverPoints(pointData, xval, yval, hovermode) { return hoverOnPoints(pointData, xval, yval, hovermode); } -function getClosestPoint(pointData, xval, yval, hovermode) { +function _getClosestPoint(pointData, xval, yval, hovermode) { var cd = pointData.cd; var xa = pointData.xa; var trace = cd[0].trace; @@ -95,7 +95,7 @@ function hoverSplit(pointData, xval, yval, hovermode) { var t = cd[0].t; var closeBoxData = []; - var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); + var closestPoint = _getClosestPoint(pointData, xval, yval, hovermode); // skip the rest (for this trace) if we didn't find a close point if(!closestPoint) return []; @@ -150,7 +150,7 @@ function hoverOnPoints(pointData, xval, yval, hovermode) { var trace = cd[0].trace; var t = cd[0].t; - var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); + var closestPoint = _getClosestPoint(pointData, xval, yval, hovermode); // skip the rest (for this trace) if we didn't find a close point if(!closestPoint) return []; diff --git a/src/traces/waterfall/hover.js b/src/traces/waterfall/hover.js index 95950200cc4..b7b0ed23444 100644 --- a/src/traces/waterfall/hover.js +++ b/src/traces/waterfall/hover.js @@ -10,8 +10,8 @@ var DIRSYMBOL = { decreasing: delta.DECREASING.SYMBOL }; -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var point = hoverOnBars(pointData, xval, yval, hovermode); +module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) { + var point = hoverOnBars(pointData, xval, yval, hovermode, opts); if(!point) return; var cd = point.cd; diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 221fbbf5d8f..62d74d99d71 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -2296,7 +2296,7 @@ describe('bar hover', function() { function _hover(gd, xval, yval, hovermode) { var pointData = getPointData(gd); - var pts = Bar.hoverPoints(pointData, xval, yval, hovermode); + var pts = Bar.hoverPoints(pointData, xval, yval, hovermode, {}); if(!pts) return false; var pt = pts[0]; @@ -2663,8 +2663,8 @@ describe('bar hover', function() { barmode: m }) .then(function() { - var pt0 = Bar.hoverPoints(getPointData(gd, 0), 0, 1, 'x')[0]; - var pt1 = Bar.hoverPoints(getPointData(gd, 1), 0, 1, 'x')[0]; + var pt0 = Bar.hoverPoints(getPointData(gd, 0), 0, 1, 'x', {})[0]; + var pt1 = Bar.hoverPoints(getPointData(gd, 1), 0, 1, 'x', {})[0]; expect(pt0.yLabelVal).toBe(0, 'y label value for data[0]'); expect(pt1.yLabelVal).toBe(1, 'y label value for data[1]'); diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index 32c076f005e..e318b1706ce 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -1309,7 +1309,7 @@ describe('funnel hover', function() { function _hover(gd, xval, yval, hovermode) { var pointData = getPointData(gd); - var pts = Funnel.hoverPoints(pointData, xval, yval, hovermode); + var pts = Funnel.hoverPoints(pointData, xval, yval, hovermode, {}); if(!pts) return false; var pt = pts[0]; diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 371c28932c9..9db86bcb2d5 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -920,37 +920,37 @@ describe('hover info', function() { fontFamily: 'Arial', fontColor: 'rgb(0, 100, 200)' }, { - bgcolor: 'rgb(255, 127, 14)', + bgcolor: 'rgb(227, 119, 194)', bordercolor: 'rgb(68, 68, 68)', fontSize: 13, fontFamily: 'Arial', fontColor: 'rgb(68, 68, 68)' }, { - bgcolor: 'rgb(0, 200, 0)', + bgcolor: 'rgb(140, 86, 75)', bordercolor: 'rgb(255, 255, 255)', fontSize: 13, fontFamily: 'Arial', fontColor: 'rgb(255, 255, 255)' }, { - bgcolor: 'rgb(150, 0, 0)', + bgcolor: 'rgb(150, 0, 200)', bordercolor: 'rgb(255, 255, 255)', fontSize: 13, fontFamily: 'Arial', fontColor: 'rgb(255, 255, 255)' }, { - bgcolor: 'rgb(150, 0, 200)', + bgcolor: 'rgb(150, 0, 0)', bordercolor: 'rgb(255, 255, 255)', fontSize: 13, fontFamily: 'Arial', fontColor: 'rgb(255, 255, 255)' }, { - bgcolor: 'rgb(140, 86, 75)', + bgcolor: 'rgb(0, 200, 0)', bordercolor: 'rgb(255, 255, 255)', fontSize: 13, fontFamily: 'Arial', fontColor: 'rgb(255, 255, 255)' }, { - bgcolor: 'rgb(227, 119, 194)', + bgcolor: 'rgb(255, 127, 14)', bordercolor: 'rgb(68, 68, 68)', fontSize: 13, fontFamily: 'Arial', @@ -1714,40 +1714,6 @@ describe('hover info', function() { }) .then(done, done.fail); }); - - it('should avoid overlaps on *too close* pts are filtered out', function(done) { - Plotly.newPlot(gd, [ - {name: 'A', x: [9, 10], y: [9, 10]}, - {name: 'B', x: [8, 9], y: [9, 10]}, - {name: 'C', x: [9, 10], y: [10, 11]} - ], { - hovermode: 'x', - xaxis: {range: [0, 100]}, - yaxis: {range: [0, 100]}, - width: 700, - height: 450 - }) - .then(function() { _hover(gd, 67, 239); }) - .then(function() { - var nodesA = hoverInfoNodes('A'); - var nodesC = hoverInfoNodes('C'); - - // Ensure layout correct - assertLabelsInsideBoxes(nodesA, 'A'); - assertLabelsInsideBoxes(nodesC, 'C'); - assertSecondaryRightToPrimaryBox(nodesA, 'A'); - assertSecondaryRightToPrimaryBox(nodesC, 'C'); - - // Ensure stacking, finally - var boxA = nodesA.primaryBox.getBoundingClientRect(); - var boxC = nodesC.primaryBox.getBoundingClientRect(); - - // Be robust against floating point arithmetic and subtle future layout changes - expect(calcLineOverlap(boxA.top, boxA.bottom, boxC.top, boxC.bottom)) - .toBeWithin(0, 1); - }) - .then(done, done.fail); - }); }); describe('constraints info graph viewport', function() { @@ -2312,7 +2278,7 @@ describe('hover info on stacked subplots', function() { y: 0 })); - expect(gd._hoverdata[1]).toEqual(jasmine.objectContaining( + expect(gd._hoverdata[2]).toEqual(jasmine.objectContaining( { curveNumber: 1, pointNumber: 0, @@ -2320,7 +2286,7 @@ describe('hover info on stacked subplots', function() { y: 0 })); - expect(gd._hoverdata[2]).toEqual(jasmine.objectContaining( + expect(gd._hoverdata[1]).toEqual(jasmine.objectContaining( { curveNumber: 2, pointNumber: 0, @@ -4708,25 +4674,245 @@ describe('hovermode: (x|y)unified', function() { .then(done, done.fail); }); - it('shares filtering logic with compare mode x', function(done) { - var mock = require('@mocks/27.json'); - var mockCopy = Lib.extendDeep({}, mock); + it('should display hover for scatter and bars at various intervals (default hoverdistance)', function(done) { + Plotly.newPlot(gd, { + data: [{ + name: 'bar', + type: 'bar', + y: [10, 30] + }, { + name: 'scatter', + type: 'scatter', + x: [0, 0.2, 0.4, 0.6, 0.8, 1], + y: [21, 22, 23, 24, 25, 26] + }], + layout: { + hovermode: 'x unified', + showlegend: false, + width: 500, + height: 500, + margin: { + t: 50, + b: 50, + l: 50, + r: 50 + } + } + }) + .then(function() { + _hover(gd, { xpx: 100, ypx: 200 }); + assertLabel({title: '0', items: [ + 'bar : 10', + 'scatter : 21' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 200, ypx: 200 }); + assertLabel({title: '0.6', items: [ + 'bar : (1, 30)', + 'scatter : 24' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 300, ypx: 200 }); + assertLabel({title: '1', items: [ + 'bar : 30', + 'scatter : 26' + ]}); + }) + .then(done, done.fail); + }); - Plotly.newPlot(gd, mockCopy) - .then(function(gd) { - _hover(gd, { xval: '2002' }); - assertElementCount('g.hovertext', 2); + it('should display hover for scatter and bars at various intervals (case of hoverdistance: -1) tests finitRange', function(done) { + Plotly.newPlot(gd, { + data: [{ + name: 'bar', + type: 'bar', + y: [10, 30] + }, { + name: 'scatter', + type: 'scatter', + x: [0, 0.2, 0.4, 0.6, 0.8, 1], + y: [21, 22, 23, 24, 25, 26] + }], + layout: { + hoverdistance: -1, + hovermode: 'x unified', + showlegend: false, + width: 500, + height: 500, + margin: { + t: 50, + b: 50, + l: 50, + r: 50 + } + } + }) + .then(function() { + _hover(gd, { xpx: 100, ypx: 200 }); + assertLabel({title: '0', items: [ + 'bar : 10', + 'scatter : 21' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 200, ypx: 200 }); + assertLabel({title: '0.6', items: [ + 'bar : (1, 30)', + 'scatter : 24' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 300, ypx: 200 }); + assertLabel({title: '1', items: [ + 'bar : 30', + 'scatter : 26' + ]}); + }) + .then(done, done.fail); + }); - return Plotly.relayout(gd, 'hovermode', 'x unified'); - }) - .then(function() { - _hover(gd, { xval: '2002' }); - assertLabel({title: '2002.042', items: [ - 'Market income : 0.5537845', - 'Market incom... : 0.4420997' - ]}); - }) - .then(done, done.fail); + it('should pick the bar which is closest to the winning point no the bar that close to the cursor', function(done) { + Plotly.newPlot(gd, { + data: [{ + name: 'bar', + type: 'bar', + y: [10, 20, 30] + }, { + name: 'scatter', + type: 'scatter', + x: [0, 0.49, 1, 1.51, 2], + y: [21, 22, 23, 24, 25] + }], + layout: { + hoverdistance: -1, + hovermode: 'x unified', + showlegend: false, + width: 500, + height: 500, + margin: { + t: 50, + b: 50, + l: 50, + r: 50 + } + } + }) + .then(function() { + _hover(gd, { xpx: 0, ypx: 200 }); + assertLabel({title: '0', items: [ + 'bar : 10', + 'scatter : 21' + ]}); + + _hover(gd, { xpx: 100, ypx: 200 }); + assertLabel({title: '0.49', items: [ + 'bar : (0, 10)', + 'scatter : 22' + ]}); + + _hover(gd, { xpx: 150, ypx: 200 }); + assertLabel({title: '0.49', items: [ + 'bar : (0, 10)', + 'scatter : 22' + ]}); + + _hover(gd, { xpx: 200, ypx: 200 }); + assertLabel({title: '1', items: [ + 'bar : 20', + 'scatter : 23' + ]}); + + _hover(gd, { xpx: 250, ypx: 200 }); + assertLabel({title: '1.51', items: [ + 'bar : (2, 30)', + 'scatter : 24' + ]}); + + _hover(gd, { xpx: 300, ypx: 200 }); + assertLabel({title: '1.51', items: [ + 'bar : (2, 30)', + 'scatter : 24' + ]}); + + _hover(gd, { xpx: 400, ypx: 200 }); + assertLabel({title: '2', items: [ + 'bar : 30', + 'scatter : 25' + ]}); + }) + .then(done, done.fail); + }); + + it('should display hover for two high-res scatter at different various intervals', function(done) { + var x1 = []; + var y1 = []; + var x2 = []; + var y2 = []; + var i, t; + + function r100(v) { + return Math.round(v * 100); + } + + for(i = 0; i <= 1800; i++) { + t = i / 180 * Math.PI; + x1.push(r100(t / 5)); + y1.push(r100(Math.sin(t))); + } + + for(i = 0; i <= 360; i++) { + t = i / 180 * Math.PI; + x2.push(r100(t)); + y2.push(r100(Math.sin(t))); + } + + Plotly.newPlot(gd, { + data: [{ + name: 'high', + x: x1, + y: y1 + }, { + name: 'low', + x: x2, + y: y2 + }], + layout: { + hovermode: 'x unified', + showlegend: false, + width: 500, + height: 500, + margin: { + t: 50, + b: 50, + l: 50, + r: 50 + } + } + }) + .then(function() { + _hover(gd, { xpx: 100, ypx: 200 }); + assertLabel({title: '157', items: [ + 'high : 100', + 'low : 100' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 175, ypx: 200 }); + assertLabel({title: '275', items: [ + 'high : 93', + 'low : (274, 39)' + ]}); + }) + .then(function() { + _hover(gd, { xpx: 350, ypx: 200 }); + assertLabel({title: '550', items: [ + 'high : 68', + 'low : −71' + ]}); + }) + .then(done, done.fail); }); it('case of scatter points on period bars', function(done) { @@ -5029,6 +5215,7 @@ describe('hovermode: (x|y)unified', function() { _hover(gd, { xpx: 100, ypx: 200 }); assertLabel({title: 'Jan 1, 2000', items: [ + 'bar : (Dec, 2)', 'scatter : 1.1' ]}); @@ -5106,22 +5293,20 @@ describe('hovermode: (x|y)unified', function() { _hover(gd, { xpx: 40, ypx: 200 }); assertLabel({title: 'Jan', items: [ 'bar : (Jan 1, 2000, 1)', - 'start : 1', - 'end : 1' + 'start : 1' ]}); _hover(gd, { xpx: 100, ypx: 200 }); - assertLabel({title: 'Jan 1, 2000', items: [ - 'bar : 1', - 'start : (Jan, 1)', - 'end : (Jan, 1)' + assertLabel({title: 'Jan', items: [ + 'bar : (Jan 1, 2000, 1)', + 'start : 1' ]}); _hover(gd, { xpx: 360, ypx: 200 }); - assertLabel({title: 'Feb 1, 2000', items: [ - 'bar : 2', + assertLabel({title: 'Jan', items: [ + 'bar : (Feb 1, 2000, 2)', 'start : (Feb, 2)', - 'end : (Feb, 2)' + 'end : 1' ]}); _hover(gd, { xpx: 400, ypx: 200 }); @@ -5162,10 +5347,10 @@ describe('hovermode: (x|y)unified', function() { .then(function(gd) { _hover(gd, {curveNumber: 0}); - assertLabel({title: 'Apr 13, 2014, 15:21:11', items: [ + assertLabel({title: 'Apr 13, 2014, 15:21:15', items: [ 'Outdoor (wun... : (Apr 13, 2014, 15:26:12, 69.4)', - '1st Floor (N... : (Apr 13, 2014, 15:21:15, 74.8)', - '2nd Floor (R... : 73.625', + '1st Floor (N... : 74.8', + '2nd Floor (R... : (Apr 13, 2014, 15:21:11, 73.625)', 'Attic (Ardui... : (Apr 13, 2014, 15:26:34, 98.49)' ]}); }) diff --git a/test/jasmine/tests/violin_test.js b/test/jasmine/tests/violin_test.js index 4b111891583..a8dbd926bcf 100644 --- a/test/jasmine/tests/violin_test.js +++ b/test/jasmine/tests/violin_test.js @@ -537,8 +537,8 @@ describe('Test violin hover:', function() { name: ['', '', '', '', '', ''], axis: 'Sat', hoverLabelPos: [ - [364, 270], [352, 270], [339, 270], - [346, 270], [349, 270], [387, 270] + [364, 270], [387, 270], [339, 270], + [346, 270], [349, 270], [352, 270] ] }, { desc: 'single horizontal violin', diff --git a/test/jasmine/tests/waterfall_test.js b/test/jasmine/tests/waterfall_test.js index eb675ee6d2f..70952a9db45 100644 --- a/test/jasmine/tests/waterfall_test.js +++ b/test/jasmine/tests/waterfall_test.js @@ -1345,7 +1345,7 @@ describe('waterfall hover', function() { function _hover(gd, xval, yval, hovermode) { var pointData = getPointData(gd); - var pts = Waterfall.hoverPoints(pointData, xval, yval, hovermode); + var pts = Waterfall.hoverPoints(pointData, xval, yval, hovermode, {}); if(!pts) return false; var pt = pts[0];