diff --git a/src/traces/ohlc/hover.js b/src/traces/ohlc/hover.js index c843fdf5951..3d2e82ea06b 100644 --- a/src/traces/ohlc/hover.js +++ b/src/traces/ohlc/hover.js @@ -101,7 +101,9 @@ function hoverSplit(pointData, xval, yval, hovermode) { // skip the rest (for this trace) if we didn't find a close point if(!closestPoint) return []; - var hoverinfo = trace.hoverinfo; + var cdIndex = closestPoint.index; + var di = cd[cdIndex]; + var hoverinfo = di.hi || trace.hoverinfo; var hoverParts = hoverinfo.split('+'); var isAll = hoverinfo === 'all'; var hasY = isAll || hoverParts.indexOf('y') !== -1; @@ -166,7 +168,7 @@ function hoverOnPoints(pointData, xval, yval, hovermode) { return t.labels[attr] + Axes.hoverLabelText(ya, trace[attr][i]); } - var hoverinfo = trace.hoverinfo; + var hoverinfo = di.hi || trace.hoverinfo; var hoverParts = hoverinfo.split('+'); var isAll = hoverinfo === 'all'; var hasY = isAll || hoverParts.indexOf('y') !== -1; diff --git a/src/traces/parcats/attributes.js b/src/traces/parcats/attributes.js index 7035c8ea45a..163f0599657 100644 --- a/src/traces/parcats/attributes.js +++ b/src/traces/parcats/attributes.js @@ -41,7 +41,8 @@ module.exports = { domain: domainAttrs({name: 'parcats', trace: true, editType: 'calc'}), hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { flags: ['count', 'probability'], - editType: 'plot' + editType: 'plot', + arrayOk: false // plotAttrs.hoverinfo description is appropriate }), hoveron: { diff --git a/test/jasmine/tests/finance_test.js b/test/jasmine/tests/finance_test.js index edb3c45514c..7d721f7b29d 100644 --- a/test/jasmine/tests/finance_test.js +++ b/test/jasmine/tests/finance_test.js @@ -1046,5 +1046,112 @@ describe('finance charts *special* handlers:', function() { .catch(failTest) .then(done); }); +}); + +describe('finance trace hover:', function() { + var gd; + + afterEach(destroyGraphDiv); + + function run(specs) { + gd = createGraphDiv(); + + var data = specs.traces.map(function(t) { + return Lib.extendFlat({ + type: specs.type, + open: [1, 2], + close: [2, 3], + high: [3, 4], + low: [0, 5] + }, t); + }); + + var layout = Lib.extendFlat({ + showlegend: false, + width: 400, + height: 400, + margin: {t: 0, b: 0, l: 0, r: 0, pad: 0} + }, specs.layout || {}); + + var xval = 'xval' in specs ? specs.xvals : 0; + var yval = 'yval' in specs ? specs.yvals : 1; + var hovermode = layout.hovermode || 'x'; + + return Plotly.plot(gd, data, layout).then(function() { + var results = gd.calcdata.map(function(cd) { + var trace = cd[0].trace; + var pointData = { + index: false, + distance: 20, + cd: cd, + trace: trace, + xa: gd._fullLayout.xaxis, + ya: gd._fullLayout.yaxis, + maxHoverDistance: 20 + }; + var pts = trace._module.hoverPoints(pointData, xval, yval, hovermode); + return pts ? pts[0] : {distance: Infinity}; + }); + + var actual = results[0]; + var exp = specs.exp; + + + for(var k in exp) { + var msg = '- key ' + k; + expect(actual[k]).toBe(exp[k], msg); + } + }); + } + ['ohlc', 'candlestick'].forEach(function(type) { + [{ + type: type, + desc: 'basic', + traces: [{}], + exp: { + extraText: 'open: 1
high: 3
low: 0
close: 2 ▲' + } + }, { + type: type, + desc: 'with scalar text', + traces: [{text: 'SCALAR'}], + exp: { + extraText: 'open: 1
high: 3
low: 0
close: 2 ▲
SCALAR' + } + }, { + type: type, + desc: 'with array text', + traces: [{text: ['A', 'B']}], + exp: { + extraText: 'open: 1
high: 3
low: 0
close: 2 ▲
A' + } + }, { + type: type, + desc: 'just scalar text', + traces: [{hoverinfo: 'text', text: 'SCALAR'}], + exp: { + extraText: 'SCALAR' + } + }, { + type: type, + desc: 'just array text', + traces: [{hoverinfo: 'text', text: ['A', 'B']}], + exp: { + extraText: 'A' + } + }, { + type: type, + desc: 'just array text with array hoverinfo', + traces: [{hoverinfo: ['text', 'text'], text: ['A', 'B']}], + exp: { + extraText: 'A' + } + }] + .forEach(function(specs) { + it('should generate correct hover labels ' + type + ' - ' + specs.desc, function(done) { + run(specs).catch(failTest).then(done); + }); + }); + }); });