From 5522b91de0c75272527abd1bf60e47732e6f0bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 18 Feb 2019 15:50:41 -0500 Subject: [PATCH 1/3] fix scattercarpet attr description + add mock with mode:text --- src/traces/scattercarpet/attributes.js | 25 ++++----- test/image/baselines/scattercarpet-text.png | Bin 0 -> 37006 bytes test/image/mocks/scattercarpet-text.json | 53 ++++++++++++++++++++ 3 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 test/image/baselines/scattercarpet-text.png create mode 100644 test/image/mocks/scattercarpet-text.json diff --git a/src/traces/scattercarpet/attributes.js b/src/traces/scattercarpet/attributes.js index 594b8407d05..4dac8de07bb 100644 --- a/src/traces/scattercarpet/attributes.js +++ b/src/traces/scattercarpet/attributes.js @@ -34,33 +34,26 @@ module.exports = { a: { valType: 'data_array', editType: 'calc', - description: [ - 'Sets the quantity of component `a` in each data point.', - 'If `a`, `b`, and `c` are all provided, they need not be', - 'normalized, only the relative values matter. If only two', - 'arrays are provided they must be normalized to match', - '`ternary.sum`.' - ].join(' ') + description: 'Sets the a-axis coordinates.' }, b: { valType: 'data_array', editType: 'calc', - description: [ - 'Sets the quantity of component `a` in each data point.', - 'If `a`, `b`, and `c` are all provided, they need not be', - 'normalized, only the relative values matter. If only two', - 'arrays are provided they must be normalized to match', - '`ternary.sum`.' - ].join(' ') + description: 'Sets the b-axis coordinates.' }, mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), text: extendFlat({}, scatterAttrs.text, { description: [ - 'Sets text elements associated with each (a,b,c) point.', + 'Sets text elements associated with each (a,b) point.', + 'If a single string, the same string appears over', + 'all the data points.', + 'If an array of strings, the items are mapped in order to the', + 'the data points in (a,b).', + 'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,', + 'these elements will be seen in the hover labels.' 'If a single string, the same string appears over', 'all the data points.', 'If an array of strings, the items are mapped in order to the', - 'the data points in (a,b,c).' ].join(' ') }), line: { diff --git a/test/image/baselines/scattercarpet-text.png b/test/image/baselines/scattercarpet-text.png new file mode 100644 index 0000000000000000000000000000000000000000..fb67389676b1d5805c4e0a7a404d8d2a89d7c56e GIT binary patch literal 37006 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 literal 0 HcmV?d00001 diff --git a/test/image/mocks/scattercarpet-text.json b/test/image/mocks/scattercarpet-text.json new file mode 100644 index 00000000000..0e419094786 --- /dev/null +++ b/test/image/mocks/scattercarpet-text.json @@ -0,0 +1,53 @@ +{ + "data": [ + { + "type": "carpet", + "a": [0.1, 0.2, 0.3], + "b": [1, 2, 3], + "y": [ + [1, 2.2, 3], + [1.5, 2.7, 3.5], + [1.7, 2.9, 3.7] + ], + "cheaterslope": 1, + "aaxis": { + "title": "a", + "tickmode": "linear", + "dtick": 0.05 + }, + "baxis": { + "title": "b", + "tickmode": "linear", + "dtick": 0.5 + } + }, + { + "type": "scattercarpet", + "name": "b = 1.5", + "mode": "markers+text", + "a": [0.05, 0.15, 0.25, 0.35], + "b": [1.5, 1.5, 1.5, 1.5], + "text": ["a", "b", "c", "d"] + }, + { + "type": "scattercarpet", + "name": "b = 2", + "mode": "markers+lines+text", + "a": [0.05, 0.15, 0.25, 0.35], + "b": [2, 2, 2, 2], + "text": ["a", "b", "c", "d"] + }, + { + "type": "scattercarpet", + "name": "b = 2.5", + "mode": "text", + "a": [0.05, 0.15, 0.25, 0.35], + "b": [2.5, 2.5, 2.5, 2.5], + "text": ["a", "b", "c", "d"] + } + ], + "layout": { + "title": "scattercarpet with text", + "hovermode": "closest" + } +} From 8229e62ed83f7c3b4fff4236c26894792309c8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 18 Feb 2019 15:51:09 -0500 Subject: [PATCH 2/3] fix histogram 'text' description --- src/traces/histogram/attributes.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/traces/histogram/attributes.js b/src/traces/histogram/attributes.js index 5391922a702..5cd5f20f0a4 100644 --- a/src/traces/histogram/attributes.js +++ b/src/traces/histogram/attributes.js @@ -12,6 +12,7 @@ var barAttrs = require('../bar/attributes'); var hovertemplateAttrs = require('../../components/fx/hovertemplate_attributes'); var makeBinAttrs = require('./bin_attributes'); var constants = require('./constants'); +var extendFlat = require('../../lib/extend').extendFlat; module.exports = { x: { @@ -29,7 +30,14 @@ module.exports = { ].join(' ') }, - text: barAttrs.text, + text: extendFlat({}, barAttrs.text, { + description: [ + 'Sets hover text elements associated with each bar.', + 'If a single string, the same string appears over all bars.', + 'If an array of string, the items are mapped in order to the', + 'this trace\'s coordinates.' + ].join(' ') + }), orientation: barAttrs.orientation, histfunc: { From 0842b6c4217c623f1fd781919c73ca45b5c9e8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 18 Feb 2019 15:52:26 -0500 Subject: [PATCH 3/3] add 'hovertext' attr to all traces that support hover 'text' - where 'hovertext' has priority over 'text' --- src/traces/barpolar/attributes.js | 4 ++- src/traces/barpolar/defaults.js | 2 +- src/traces/box/attributes.js | 3 ++ src/traces/box/calc.js | 3 +- src/traces/box/defaults.js | 1 + src/traces/candlestick/attributes.js | 1 + src/traces/candlestick/defaults.js | 1 + src/traces/choropleth/attributes.js | 3 ++ src/traces/choropleth/defaults.js | 1 + src/traces/cone/attributes.js | 8 +++++ src/traces/cone/convert.js | 2 +- src/traces/cone/defaults.js | 1 + src/traces/contour/attributes.js | 1 + src/traces/contour/defaults.js | 1 + src/traces/contourcarpet/attributes.js | 1 + src/traces/heatmap/attributes.js | 5 +++ src/traces/heatmap/calc.js | 3 +- src/traces/heatmap/convert_column_xyz.js | 8 +++++ src/traces/heatmap/defaults.js | 1 + src/traces/heatmap/hover.js | 4 ++- src/traces/histogram/attributes.js | 3 ++ src/traces/histogram/defaults.js | 4 +-- src/traces/isosurface/attributes.js | 7 ++++ src/traces/isosurface/convert.js | 2 +- src/traces/isosurface/defaults.js | 1 + src/traces/mesh3d/attributes.js | 8 +++++ src/traces/mesh3d/convert.js | 2 +- src/traces/mesh3d/defaults.js | 1 + src/traces/ohlc/attributes.js | 8 +++++ src/traces/ohlc/calc.js | 2 ++ src/traces/ohlc/defaults.js | 1 + src/traces/scattercarpet/attributes.js | 7 ++++ src/traces/scattercarpet/defaults.js | 1 + src/traces/scattercarpet/hover.js | 9 +++-- src/traces/splom/attributes.js | 4 +++ src/traces/splom/defaults.js | 1 + src/traces/streamtube/attributes.js | 7 ++++ src/traces/streamtube/convert.js | 2 +- src/traces/streamtube/defaults.js | 1 + src/traces/surface/attributes.js | 7 ++++ src/traces/surface/convert.js | 2 +- src/traces/surface/defaults.js | 1 + src/traces/violin/attributes.js | 1 + test/jasmine/tests/barpolar_test.js | 34 +++++++++++++++++++ test/jasmine/tests/box_test.js | 16 +++++++++ test/jasmine/tests/carpet_test.js | 12 +++++++ test/jasmine/tests/choropleth_test.js | 14 ++++++++ test/jasmine/tests/cone_test.js | 15 ++++++++ test/jasmine/tests/finance_test.js | 14 ++++++++ test/jasmine/tests/gl3d_plot_interact_test.js | 14 ++++++++ test/jasmine/tests/hover_label_test.js | 32 +++++++++++++++++ test/jasmine/tests/isosurface_test.js | 18 ++++++++++ test/jasmine/tests/splom_test.js | 13 +++++++ test/jasmine/tests/streamtube_test.js | 6 ++++ test/jasmine/tests/violin_test.js | 16 +++++++++ 55 files changed, 326 insertions(+), 14 deletions(-) diff --git a/src/traces/barpolar/attributes.js b/src/traces/barpolar/attributes.js index 0bc594a2878..e6540f1a6c6 100644 --- a/src/traces/barpolar/attributes.js +++ b/src/traces/barpolar/attributes.js @@ -58,7 +58,9 @@ module.exports = { 'this trace\'s coordinates.' ].join(' ') }), - // hovertext: barAttrs.hovertext, + hovertext: extendFlat({}, barAttrs.hovertext, { + description: 'Same as `text`.' + }), // textposition: {}, // textfont: {}, diff --git a/src/traces/barpolar/defaults.js b/src/traces/barpolar/defaults.js index 6619d60056c..4265f46d7ab 100644 --- a/src/traces/barpolar/defaults.js +++ b/src/traces/barpolar/defaults.js @@ -33,8 +33,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('width'); coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); - // coerce('hovertext'); // var textPosition = coerce('textposition'); // var hasBoth = Array.isArray(textPosition) || textPosition === 'auto'; diff --git a/src/traces/box/attributes.js b/src/traces/box/attributes.js index 7bfd9bce3ce..136e064b78c 100644 --- a/src/traces/box/attributes.js +++ b/src/traces/box/attributes.js @@ -72,6 +72,9 @@ module.exports = { 'To be seen, trace `hoverinfo` must contain a *text* flag.' ].join(' ') }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + description: 'Same as `text`.' + }), whiskerwidth: { valType: 'number', min: 0, diff --git a/src/traces/box/calc.js b/src/traces/box/calc.js index 02fa7a15d0e..0e424c5223d 100644 --- a/src/traces/box/calc.js +++ b/src/traces/box/calc.js @@ -212,7 +212,8 @@ function initNestedArray(len) { function arraysToCalcdata(pt, trace, i) { var trace2calc = { - text: 'tx' + text: 'tx', + hovertext: 'htx' }; for(var k in trace2calc) { diff --git a/src/traces/box/defaults.js b/src/traces/box/defaults.js index b3d6500e5d4..9051230526c 100644 --- a/src/traces/box/defaults.js +++ b/src/traces/box/defaults.js @@ -100,6 +100,7 @@ function handlePointsDefaults(traceIn, traceOut, coerce, opts) { coerce('unselected.marker.size'); coerce('text'); + coerce('hovertext'); } else { delete traceOut.marker; } diff --git a/src/traces/candlestick/attributes.js b/src/traces/candlestick/attributes.js index 1f39192eb20..4b3fede5f3e 100644 --- a/src/traces/candlestick/attributes.js +++ b/src/traces/candlestick/attributes.js @@ -50,6 +50,7 @@ module.exports = { decreasing: directionAttrs(OHLCattrs.decreasing.line.color.dflt), text: OHLCattrs.text, + hovertext: OHLCattrs.hovertext, whiskerwidth: extendFlat({}, boxAttrs.whiskerwidth, { dflt: 0 }), hoverlabel: OHLCattrs.hoverlabel, diff --git a/src/traces/candlestick/defaults.js b/src/traces/candlestick/defaults.js index 6f21faead45..f4e2f6d64a4 100644 --- a/src/traces/candlestick/defaults.js +++ b/src/traces/candlestick/defaults.js @@ -31,6 +31,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleDirection(traceIn, traceOut, coerce, 'decreasing'); coerce('text'); + coerce('hovertext'); coerce('whiskerwidth'); layout._requestRangeslider[traceOut.xaxis] = true; diff --git a/src/traces/choropleth/attributes.js b/src/traces/choropleth/attributes.js index 07548ef5c6d..5e68b2b7f71 100644 --- a/src/traces/choropleth/attributes.js +++ b/src/traces/choropleth/attributes.js @@ -36,6 +36,9 @@ module.exports = extendFlat({ text: extendFlat({}, scatterGeoAttrs.text, { description: 'Sets the text elements associated with each location.' }), + hovertext: extendFlat({}, scatterGeoAttrs.hovertext, { + description: 'Same as `text`.' + }), marker: { line: { color: scatterGeoMarkerLineAttrs.color, diff --git a/src/traces/choropleth/defaults.js b/src/traces/choropleth/defaults.js index 952e0f9aaa6..47d84b91ae0 100644 --- a/src/traces/choropleth/defaults.js +++ b/src/traces/choropleth/defaults.js @@ -30,6 +30,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('locationmode'); coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); coerce('marker.line.color'); diff --git a/src/traces/cone/attributes.js b/src/traces/cone/attributes.js index e2a2f062fe2..0df3c8d9964 100644 --- a/src/traces/cone/attributes.js +++ b/src/traces/cone/attributes.js @@ -159,6 +159,14 @@ var attrs = { 'these elements will be seen in the hover labels.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + arrayOk: true, + editType: 'calc', + description: 'Same as `text`.' + }, hovertemplate: hovertemplateAttrs({editType: 'calc'}, {keys: ['norm']}) }; diff --git a/src/traces/cone/convert.js b/src/traces/cone/convert.js index ee74707a413..dcdfcb9d5f1 100644 --- a/src/traces/cone/convert.js +++ b/src/traces/cone/convert.js @@ -40,7 +40,7 @@ proto.handlePick = function(selection) { Math.sqrt(uu * uu + vv * vv + ww * ww) ]; - var text = this.data.text; + var text = this.data.hovertext || this.data.text; if(Array.isArray(text) && text[selectIndex] !== undefined) { selection.textLabel = text[selectIndex]; } else if(text) { diff --git a/src/traces/cone/defaults.js b/src/traces/cone/defaults.js index 7237edba166..3b6f1d5fc91 100644 --- a/src/traces/cone/defaults.js +++ b/src/traces/cone/defaults.js @@ -52,6 +52,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); // disable 1D transforms (for now) diff --git a/src/traces/contour/attributes.js b/src/traces/contour/attributes.js index 82055b84201..4e48ff14beb 100644 --- a/src/traces/contour/attributes.js +++ b/src/traces/contour/attributes.js @@ -31,6 +31,7 @@ module.exports = extendFlat({ y0: heatmapAttrs.y0, dy: heatmapAttrs.dy, text: heatmapAttrs.text, + hovertext: heatmapAttrs.hovertext, transpose: heatmapAttrs.transpose, xtype: heatmapAttrs.xtype, ytype: heatmapAttrs.ytype, diff --git a/src/traces/contour/defaults.js b/src/traces/contour/defaults.js index aa6cb7c8842..1dddb34d561 100644 --- a/src/traces/contour/defaults.js +++ b/src/traces/contour/defaults.js @@ -33,6 +33,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); var isConstraint = (coerce('contours.type') === 'constraint'); diff --git a/src/traces/contourcarpet/attributes.js b/src/traces/contourcarpet/attributes.js index 680ccec80cd..6bcec99d63f 100644 --- a/src/traces/contourcarpet/attributes.js +++ b/src/traces/contourcarpet/attributes.js @@ -36,6 +36,7 @@ module.exports = extendFlat({ b0: heatmapAttrs.y0, db: heatmapAttrs.dy, text: heatmapAttrs.text, + hovertext: heatmapAttrs.hovertext, transpose: heatmapAttrs.transpose, atype: heatmapAttrs.xtype, btype: heatmapAttrs.ytype, diff --git a/src/traces/heatmap/attributes.js b/src/traces/heatmap/attributes.js index 9bf083d8098..89cc79bf02c 100644 --- a/src/traces/heatmap/attributes.js +++ b/src/traces/heatmap/attributes.js @@ -33,6 +33,11 @@ module.exports = extendFlat({ editType: 'calc', description: 'Sets the text elements associated with each z value.' }, + hovertext: { + valType: 'data_array', + editType: 'calc', + description: 'Same as `text`.' + }, transpose: { valType: 'boolean', dflt: false, diff --git a/src/traces/heatmap/calc.js b/src/traces/heatmap/calc.js index 13b4fdb61d4..32a82f76d3c 100644 --- a/src/traces/heatmap/calc.js +++ b/src/traces/heatmap/calc.js @@ -131,7 +131,8 @@ module.exports = function calc(gd, trace) { x: xArray, y: yArray, z: z, - text: trace._text || trace.text + text: trace._text || trace.text, + hovertext: trace._hovertext || trace.hovertext }; if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn; diff --git a/src/traces/heatmap/convert_column_xyz.js b/src/traces/heatmap/convert_column_xyz.js index cbc70c57a9e..ace8224f877 100644 --- a/src/traces/heatmap/convert_column_xyz.js +++ b/src/traces/heatmap/convert_column_xyz.js @@ -18,6 +18,8 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, var col2 = ax2.makeCalcdata(trace, var2Name); var textCol = trace.text; var hasColumnText = (textCol !== undefined && Lib.isArray1D(textCol)); + var hoverTextCol = trace.hovertext; + var hasColumnHoverText = (hoverTextCol !== undefined && Lib.isArray1D(hoverTextCol)); var i, j; var col1dv = Lib.distinctVals(col1); @@ -26,6 +28,7 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, var col2vals = col2dv.vals; var newArrays = []; var text; + var hovertext; for(i = 0; i < arrayVarNames.length; i++) { newArrays[i] = Lib.init2dArray(col2vals.length, col1vals.length); @@ -34,6 +37,9 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, if(hasColumnText) { text = Lib.init2dArray(col2vals.length, col1vals.length); } + if(hasColumnHoverText) { + hovertext = Lib.init2dArray(col2vals.length, col1vals.length); + } for(i = 0; i < colLen; i++) { if(col1[i] !== BADNUM && col2[i] !== BADNUM) { @@ -48,6 +54,7 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, } if(hasColumnText) text[i2][i1] = textCol[i]; + if(hasColumnHoverText) hovertext[i2][i1] = hoverTextCol[i]; } } @@ -57,4 +64,5 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, trace['_' + arrayVarNames[j]] = newArrays[j]; } if(hasColumnText) trace._text = text; + if(hasColumnHoverText) trace._hovertext = hovertext; }; diff --git a/src/traces/heatmap/defaults.js b/src/traces/heatmap/defaults.js index 6e2933cbc91..a245af88d95 100644 --- a/src/traces/heatmap/defaults.js +++ b/src/traces/heatmap/defaults.js @@ -29,6 +29,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); handleStyleDefaults(traceIn, traceOut, coerce, layout); diff --git a/src/traces/heatmap/hover.js b/src/traces/heatmap/hover.js index df7873aaa5b..0105156f1ca 100644 --- a/src/traces/heatmap/hover.js +++ b/src/traces/heatmap/hover.js @@ -93,7 +93,9 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay if(zmask && !zmask[ny][nx]) zVal = undefined; var text; - if(Array.isArray(cd0.text) && Array.isArray(cd0.text[ny])) { + if(Array.isArray(cd0.hovertext) && Array.isArray(cd0.hovertext[ny])) { + text = cd0.hovertext[ny][nx]; + } else if(Array.isArray(cd0.text) && Array.isArray(cd0.text[ny])) { text = cd0.text[ny][nx]; } diff --git a/src/traces/histogram/attributes.js b/src/traces/histogram/attributes.js index 5cd5f20f0a4..d9e3136fff7 100644 --- a/src/traces/histogram/attributes.js +++ b/src/traces/histogram/attributes.js @@ -38,6 +38,9 @@ module.exports = { 'this trace\'s coordinates.' ].join(' ') }), + hovertext: extendFlat({}, barAttrs.hovertext, { + description: 'Same as `text`.' + }), orientation: barAttrs.orientation, histfunc: { diff --git a/src/traces/histogram/defaults.js b/src/traces/histogram/defaults.js index 747559f352a..51fbb8ce4f9 100644 --- a/src/traces/histogram/defaults.js +++ b/src/traces/histogram/defaults.js @@ -31,6 +31,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } coerce('text'); + coerce('hovertext'); + coerce('hovertemplate'); var orientation = coerce('orientation', (y && !x) ? 'h' : 'v'); var sampleLetter = orientation === 'v' ? 'x' : 'y'; @@ -58,8 +60,6 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout // autobin(x|y) are only included here to appease Plotly.validate coerce('autobin' + sampleLetter); - coerce('hovertemplate'); - handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); Lib.coerceSelectionMarkerOpacity(traceOut, coerce); diff --git a/src/traces/isosurface/attributes.js b/src/traces/isosurface/attributes.js index c6af7cc065a..fd170ae05b1 100644 --- a/src/traces/isosurface/attributes.js +++ b/src/traces/isosurface/attributes.js @@ -226,6 +226,13 @@ var attrs = module.exports = overrideAll(extendFlat({ 'these elements will be seen in the hover labels.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + arrayOk: true, + description: 'Same as `text`.' + }, hovertemplate: hovertemplateAttrs() }, diff --git a/src/traces/isosurface/convert.js b/src/traces/isosurface/convert.js index f636d5be583..5272cd0187b 100644 --- a/src/traces/isosurface/convert.js +++ b/src/traces/isosurface/convert.js @@ -73,7 +73,7 @@ proto.handlePick = function(selection) { this.data.value[selectIndex] ]; - var text = this.data.text; + var text = this.data.hovertext || this.data.text; if(Array.isArray(text) && text[selectIndex] !== undefined) { selection.textLabel = text[selectIndex]; } else if(text) { diff --git a/src/traces/isosurface/defaults.js b/src/traces/isosurface/defaults.js index 5fcb750081b..48b19dffa44 100644 --- a/src/traces/isosurface/defaults.js +++ b/src/traces/isosurface/defaults.js @@ -84,6 +84,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout // Coerce remaining properties [ 'text', + 'hovertext', 'hovertemplate', 'lighting.ambient', 'lighting.diffuse', diff --git a/src/traces/mesh3d/attributes.js b/src/traces/mesh3d/attributes.js index dea5596c3c0..bd90dfb8e86 100644 --- a/src/traces/mesh3d/attributes.js +++ b/src/traces/mesh3d/attributes.js @@ -90,6 +90,14 @@ module.exports = extendFlat({ 'these elements will be seen in the hover labels.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + arrayOk: true, + editType: 'calc', + description: 'Same as `text`.' + }, hovertemplate: hovertemplateAttrs({editType: 'calc'}), delaunayaxis: { diff --git a/src/traces/mesh3d/convert.js b/src/traces/mesh3d/convert.js index 250c480b44e..7c2cc23d651 100644 --- a/src/traces/mesh3d/convert.js +++ b/src/traces/mesh3d/convert.js @@ -40,7 +40,7 @@ proto.handlePick = function(selection) { this.data.z[selectIndex] ]; - var text = this.data.text; + var text = this.data.hovertext || this.data.text; if(Array.isArray(text) && text[selectIndex] !== undefined) { selection.textLabel = text[selectIndex]; } else if(text) { diff --git a/src/traces/mesh3d/defaults.js b/src/traces/mesh3d/defaults.js index c46204a11c2..d4b5c6fcb89 100644 --- a/src/traces/mesh3d/defaults.js +++ b/src/traces/mesh3d/defaults.js @@ -88,6 +88,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); // disable 1D transforms diff --git a/src/traces/ohlc/attributes.js b/src/traces/ohlc/attributes.js index 317212cbd0b..c2051f24a2c 100644 --- a/src/traces/ohlc/attributes.js +++ b/src/traces/ohlc/attributes.js @@ -104,6 +104,14 @@ module.exports = { 'this trace\'s sample points.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + arrayOk: true, + editType: 'calc', + description: 'Same as `text`.' + }, tickwidth: { valType: 'number', diff --git a/src/traces/ohlc/calc.js b/src/traces/ohlc/calc.js index ea8545e0d56..094e7384b40 100644 --- a/src/traces/ohlc/calc.js +++ b/src/traces/ohlc/calc.js @@ -56,6 +56,7 @@ function calcCommon(gd, trace, x, ya, ptFunc) { var c = ya.makeCalcdata(trace, 'close'); var hasTextArray = Array.isArray(trace.text); + var hasHovertextArray = Array.isArray(trace.hovertext); // we're optimists - before we have any changing data, assume increasing var increasing = true; @@ -87,6 +88,7 @@ function calcCommon(gd, trace, x, ya, ptFunc) { pt.dir = increasing ? 'increasing' : 'decreasing'; if(hasTextArray) pt.tx = trace.text[i]; + if(hasHovertextArray) pt.htx = trace.hovertext[i]; cd.push(pt); } else { diff --git a/src/traces/ohlc/defaults.js b/src/traces/ohlc/defaults.js index 3e5675dfd5e..32723023ba4 100644 --- a/src/traces/ohlc/defaults.js +++ b/src/traces/ohlc/defaults.js @@ -31,6 +31,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleDirection(traceIn, traceOut, coerce, 'decreasing'); coerce('text'); + coerce('hovertext'); coerce('tickwidth'); layout._requestRangeslider[traceOut.xaxis] = true; diff --git a/src/traces/scattercarpet/attributes.js b/src/traces/scattercarpet/attributes.js index 4dac8de07bb..c263e3b333a 100644 --- a/src/traces/scattercarpet/attributes.js +++ b/src/traces/scattercarpet/attributes.js @@ -51,9 +51,16 @@ module.exports = { 'the data points in (a,b).', 'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,', 'these elements will be seen in the hover labels.' + ].join(' ') + }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + description: [ + 'Sets hover text elements associated with each (a,b) point.', 'If a single string, the same string appears over', 'all the data points.', 'If an array of strings, the items are mapped in order to the', + 'the data points in (a,b).', + 'To be seen, trace `hoverinfo` must contain a *text* flag.' ].join(' ') }), line: { diff --git a/src/traces/scattercarpet/defaults.js b/src/traces/scattercarpet/defaults.js index 61d28ba75b5..cea51be903d 100644 --- a/src/traces/scattercarpet/defaults.js +++ b/src/traces/scattercarpet/defaults.js @@ -44,6 +44,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout traceOut._length = len; coerce('text'); + coerce('hovertext'); var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; coerce('mode', defaultMode); diff --git a/src/traces/scattercarpet/hover.js b/src/traces/scattercarpet/hover.js index 16882588ca8..3f71bd0fbaf 100644 --- a/src/traces/scattercarpet/hover.js +++ b/src/traces/scattercarpet/hover.js @@ -6,10 +6,10 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var scatterHover = require('../scatter/hover'); +var fillHoverText = require('../scatter/fill_hover_text'); module.exports = function hoverPoints(pointData, xval, yval, hovermode) { var scatterPointData = scatterHover(pointData, xval, yval, hovermode); @@ -57,6 +57,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) { var xy = carpet.evalxy([], i0, j0, ti, tj); newPointData.yLabel = xy[1].toFixed(3); + delete newPointData.text; var text = []; function textPart(ax, val) { @@ -76,12 +77,16 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) { var hoverinfo = cdi.hi || trace.hoverinfo; var parts = hoverinfo.split('+'); - if(parts.indexOf('all') !== -1) parts = ['a', 'b']; + if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'text']; if(parts.indexOf('a') !== -1) textPart(carpet.aaxis, cdi.a); if(parts.indexOf('b') !== -1) textPart(carpet.baxis, cdi.b); text.push('y: ' + newPointData.yLabel); + if(parts.indexOf('text') !== -1) { + fillHoverText(cdi, trace, text); + } + newPointData.extraText = text.join('
'); } diff --git a/src/traces/splom/attributes.js b/src/traces/splom/attributes.js index 79dff01442a..a850bacfca6 100644 --- a/src/traces/splom/attributes.js +++ b/src/traces/splom/attributes.js @@ -124,6 +124,10 @@ module.exports = { 'this trace\'s (x,y) coordinates.' ].join(' ') }), + hovertext: extendFlat({}, scatterGlAttrs.hovertext, { + description: 'Same as `text`.' + }), + hovertemplate: hovertemplateAttrs(), marker: markerAttrs, diff --git a/src/traces/splom/defaults.js b/src/traces/splom/defaults.js index 1a268cef365..c27536ee0f8 100644 --- a/src/traces/splom/defaults.js +++ b/src/traces/splom/defaults.js @@ -39,6 +39,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); diff --git a/src/traces/streamtube/attributes.js b/src/traces/streamtube/attributes.js index 4dfbd303912..c1a4c08810e 100644 --- a/src/traces/streamtube/attributes.js +++ b/src/traces/streamtube/attributes.js @@ -132,6 +132,13 @@ var attrs = { 'Note that streamtube traces do not support array `text` values.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + editType: 'calc', + description: 'Same as `text`.' + }, hovertemplate: hovertemplateAttrs({editType: 'calc'}, { keys: [ 'tubex', 'tubey', 'tubez', diff --git a/src/traces/streamtube/convert.js b/src/traces/streamtube/convert.js index d663c262fb5..ced5c0b1508 100644 --- a/src/traces/streamtube/convert.js +++ b/src/traces/streamtube/convert.js @@ -55,7 +55,7 @@ proto.handlePick = function(selection) { selection.data.divergence ]; - selection.textLabel = this.data.text; + selection.textLabel = this.data.hovertext || this.data.text; return true; } diff --git a/src/traces/streamtube/defaults.js b/src/traces/streamtube/defaults.js index e8bae6160d5..f118a41f665 100644 --- a/src/traces/streamtube/defaults.js +++ b/src/traces/streamtube/defaults.js @@ -53,6 +53,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); // disable 1D transforms (for now) diff --git a/src/traces/surface/attributes.js b/src/traces/surface/attributes.js index 5a573dc9f23..cf34be68e7e 100644 --- a/src/traces/surface/attributes.js +++ b/src/traces/surface/attributes.js @@ -124,6 +124,13 @@ var attrs = module.exports = overrideAll(extendFlat({ 'these elements will be seen in the hover labels.' ].join(' ') }, + hovertext: { + valType: 'string', + role: 'info', + dflt: '', + arrayOk: true, + description: 'Same as `text`.' + }, hovertemplate: hovertemplateAttrs(), surfacecolor: { diff --git a/src/traces/surface/convert.js b/src/traces/surface/convert.js index 74397d78ae5..488d55419ae 100644 --- a/src/traces/surface/convert.js +++ b/src/traces/surface/convert.js @@ -96,7 +96,7 @@ proto.handlePick = function(selection) { } } - var text = this.data.text; + var text = this.data.hovertext || this.data.text; if(Array.isArray(text) && text[k] && text[k][j] !== undefined) { selection.textLabel = text[k][j]; } else if(text) { diff --git a/src/traces/surface/defaults.js b/src/traces/surface/defaults.js index 3ca1cf856db..0e83b883fce 100644 --- a/src/traces/surface/defaults.js +++ b/src/traces/surface/defaults.js @@ -42,6 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); coerce('text'); + coerce('hovertext'); coerce('hovertemplate'); // Coerce remaining properties diff --git a/src/traces/violin/attributes.js b/src/traces/violin/attributes.js index ba71026aadf..bd26d9afc41 100644 --- a/src/traces/violin/attributes.js +++ b/src/traces/violin/attributes.js @@ -146,6 +146,7 @@ module.exports = { marker: boxAttrs.marker, text: boxAttrs.text, + hovertext: boxAttrs.hovertext, box: { visible: { diff --git a/test/jasmine/tests/barpolar_test.js b/test/jasmine/tests/barpolar_test.js index 76bf9bc943d..8de6bd291fc 100644 --- a/test/jasmine/tests/barpolar_test.js +++ b/test/jasmine/tests/barpolar_test.js @@ -163,6 +163,40 @@ describe('Test barpolar hover:', function() { extraText: 'r: 1
θ: 0°
A', color: '#1f77b4' } + }, { + desc: 'with custom hovertext scalar', + traces: [{ + r: [1, 2, 3], + theta: [0, 90, 180], + hovertext: 'TEXT', + text: 'nop!' + }], + xval: 1, + yval: 0, + exp: { + index: 0, + x: 263.33, + y: 200, + extraText: 'r: 1
θ: 0°
TEXT', + color: '#1f77b4' + } + }, { + desc: 'with custom hovertext array', + traces: [{ + r: [1, 2, 3], + theta: [0, 90, 180], + hovertext: ['A', 'B', 'C'], + text: ['n', 'o', 'p'] + }], + xval: 1, + yval: 0, + exp: { + index: 0, + x: 263.33, + y: 200, + extraText: 'r: 1
θ: 0°
A', + color: '#1f77b4' + } }, { desc: 'works with bars with offsets', traces: [{ diff --git a/test/jasmine/tests/box_test.js b/test/jasmine/tests/box_test.js index 694735de757..ab8d0f1294e 100644 --- a/test/jasmine/tests/box_test.js +++ b/test/jasmine/tests/box_test.js @@ -317,6 +317,22 @@ describe('Test box hover:', function() { }, nums: 'look:0.7', name: '' + }, { + desc: 'only hovertext items on hover', + patch: function(fig) { + fig.data.forEach(function(trace) { + trace.boxpoints = 'all'; + trace.hoveron = 'points'; + trace.text = trace.y.map(function(v) { return 'NOT THIS:' + v; }); + trace.hovertext = trace.y.map(function(v) { return 'look:' + v; }); + trace.hoverinfo = 'text'; + }); + fig.layout.hovermode = 'closest'; + fig.layout.xaxis = {range: [-0.565, 1.5]}; + return fig; + }, + nums: 'look:0.7', + name: '' }, { desc: 'orientation:h | hovermode:y', mock: require('@mocks/box_grouped_horz.json'), diff --git a/test/jasmine/tests/carpet_test.js b/test/jasmine/tests/carpet_test.js index ffc385f940c..3fada7b2e71 100644 --- a/test/jasmine/tests/carpet_test.js +++ b/test/jasmine/tests/carpet_test.js @@ -657,6 +657,18 @@ describe('scattercarpet hover labels', function() { .then(done); }); + it('should generate hover label (with hovertext array)', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/scattercarpet.json')); + fig.data[5].hovertext = ['A', 'B', 'C', 'D']; + fig.data[5].text = ['N', 'O', 'P', '!']; + + run( + [200, 200], fig, + [['a: 0.200', 'b: 3.500', 'y: 2.900', 'D'], 'a = 0.2'] + ) + .then(done); + }); + it('should generate hover label with \'hoverinfo\' set', function(done) { var fig = Lib.extendDeep({}, require('@mocks/scattercarpet.json')); fig.data[5].hoverinfo = 'a+y'; diff --git a/test/jasmine/tests/choropleth_test.js b/test/jasmine/tests/choropleth_test.js index 6d1985ec70d..ba745b55d2c 100644 --- a/test/jasmine/tests/choropleth_test.js +++ b/test/jasmine/tests/choropleth_test.js @@ -152,6 +152,20 @@ describe('Test choropleth hover:', function() { .then(done); }); + it('should generate hover labels from `hovertext`', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/geo_first.json')); + fig.data[1].hovertext = ['tExT', 'TeXt', '-text-']; + fig.data[1].text = ['N', 'O', 'P']; + fig.data[1].hoverinfo = 'text'; + + run( + [400, 160], + fig, + ['-text-', null] + ) + .then(done); + }); + it('should generate hover label with custom styling', function(done) { var fig = Lib.extendDeep({}, require('@mocks/geo_first.json')); fig.data[1].hoverlabel = { diff --git a/test/jasmine/tests/cone_test.js b/test/jasmine/tests/cone_test.js index f43b106666b..80e11ae16bd 100644 --- a/test/jasmine/tests/cone_test.js +++ b/test/jasmine/tests/cone_test.js @@ -298,6 +298,21 @@ describe('Test cone interactions', function() { ].join('\n') }); + return Plotly.restyle(gd, 'hovertext', 'look'); + }) + .then(delay(20)) + .then(_hover) + .then(function() { + assertHoverLabelContent({ + name: 'trace 0', + nums: [ + 'x: 2', 'y: 2', 'z: 2', + 'u: 0', 'v: 3', 'w: 0', + 'norm: 3.00', + 'look' + ].join('\n') + }); + return Plotly.restyle(gd, 'hovertemplate', 'NORM : %{norm}
at %{x},%{y},%{z}LOOKOUT'); }) .then(delay(20)) diff --git a/test/jasmine/tests/finance_test.js b/test/jasmine/tests/finance_test.js index 52ce663fb57..2fee00f27dd 100644 --- a/test/jasmine/tests/finance_test.js +++ b/test/jasmine/tests/finance_test.js @@ -1217,6 +1217,20 @@ describe('finance trace hover:', function() { exp: { extraText: 'A' } + }, { + type: type, + desc: 'just scalar hovertext', + traces: [{hoverinfo: 'text', hovertext: 'SCALAR', text: 'NOP'}], + exp: { + extraText: 'SCALAR' + } + }, { + type: type, + desc: 'just array hovertext', + traces: [{hoverinfo: 'text', hovertext: ['A', 'B'], text: ['N', 'O', 'P']}], + exp: { + extraText: 'A' + } }, { type: type, desc: 'just array text with array hoverinfo', diff --git a/test/jasmine/tests/gl3d_plot_interact_test.js b/test/jasmine/tests/gl3d_plot_interact_test.js index 91c881f5faf..ba520930978 100644 --- a/test/jasmine/tests/gl3d_plot_interact_test.js +++ b/test/jasmine/tests/gl3d_plot_interact_test.js @@ -342,9 +342,15 @@ describe('Test gl3d plots', function() { return Plotly.restyle(gd, 'text', 'yo!'); }) + .then(_hover) .then(function() { assertHoverText(null, null, null, 'yo!'); + return Plotly.restyle(gd, 'hovertext', 'ONE TWO'); + }) + .then(function() { + assertHoverText(null, null, null, 'ONE TWO'); + return Plotly.restyle(gd, 'hovertemplate', '!!! %{z} !!!'); }) .then(function() { @@ -428,6 +434,14 @@ describe('Test gl3d plots', function() { .then(function() { assertHoverText(null, null, null, 'yo!'); }) + .then(function() { + return Plotly.restyle(gd, 'hovertext', [ + text.map(function(tx) { return tx + ' !!'; }) + ]); + }) + .then(function() { + assertHoverText(null, null, null, 'ts: 3\nhz: 4\nftt:5 !!'); + }) .then(function() { return Plotly.restyle(gd, 'hovertemplate', '%{x}-%{y}-%{z}'); }) diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index b5ff4bc0e9f..c8178a78fe2 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -655,6 +655,18 @@ describe('hover info', function() { name: 'one' }); }) + .then(function() { + return Plotly.restyle(gd, 'hovertext', [ + [['A', 'B', 'C'], ['X', 'Y', 'Z']] + ], [1]); + }) + .then(function() { + _hover(gd, 250, 100); + assertHoverLabelContent({ + nums: 'x: 1\ny: 3\nz: 2\nY', + name: 'two' + }); + }) .catch(failTest) .then(done); }); @@ -766,6 +778,18 @@ describe('hover info', function() { name: 'one' }); }) + .then(function() { + return Plotly.restyle(gd, 'hovertext', [ + [['A', 'B', 'C'], ['X', 'Y', 'Z']] + ]); + }) + .then(function() { + _hover(gd, 250, 50); + assertHoverLabelContent({ + nums: 'x: 1\ny: 3\nz: 2\nY', + name: 'two' + }); + }) .then(function() { return Plotly.restyle(gd, 'hovertemplate', '(%{x},%{y}) -- %{z}trace %{data.name}'); }) @@ -1071,6 +1095,14 @@ describe('hover info', function() { axis: '3.3' }); }) + .then(function() { return Plotly.restyle(gd, 'hovertext', 'LOOK'); }) + .then(function() { + _hover(gd, 250, 200); + assertHoverLabelContent({ + nums: '3\nLOOK', + axis: '3.3' + }); + }) .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/isosurface_test.js b/test/jasmine/tests/isosurface_test.js index 3b821063aa8..b55b235fc12 100644 --- a/test/jasmine/tests/isosurface_test.js +++ b/test/jasmine/tests/isosurface_test.js @@ -398,6 +398,24 @@ describe('Test isosurface', function() { ].join('\n') }); }) + .then(function() { + return Plotly.restyle(gd, 'hovertext', [ + fig.data[0].value.map(function(v) { return '!! ' + v + ' !!'; }) + ]); + }) + .then(delay(20)) + .then(_hover4) + .then(function() { + assertHoverLabelContent({ + nums: [ + 'x: 0.4', + 'y: 100μ', + 'z: −4', + 'value: −1.3', + '!! -1.3 !!' + ].join('\n') + }); + }) .then(function() { return Plotly.restyle(gd, 'hovertemplate', '%{value}
(%{x},%{y},%{z})!!'); }) diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index 815671aa976..e1058a3224a 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -1360,6 +1360,19 @@ describe('Test splom hover:', function() { nums: 'Apr 2003', axis: 'Jan 2000', evtPts: [{x: '2000-01-01', y: '2003-04-21', pointNumber: 0}] + }, { + desc: 'with hovertext', + patch: function(fig) { + fig.data.forEach(function(t) { + t.hovertext = 'LOOK'; + t.text = 'NOP'; + }); + fig.layout.hovermode = 'closest'; + return fig; + }, + nums: '(2.6, 7.7)\nLOOK', + name: 'Virginica', + evtPts: [{x: 2.6, y: 7.7, pointNumber: 18, curveNumber: 2}] }, { desc: 'with a hovertemplate', patch: function(fig) { diff --git a/test/jasmine/tests/streamtube_test.js b/test/jasmine/tests/streamtube_test.js index 1316e90c92e..43528a8df9a 100644 --- a/test/jasmine/tests/streamtube_test.js +++ b/test/jasmine/tests/streamtube_test.js @@ -359,6 +359,12 @@ describe('@noCI Test streamtube hover', function() { .then(_hover) .then(function() { assertHoverLabelContent({nums: '!SCALAR TX!'}); + return Plotly.restyle(gd, 'hovertext', 'SCALAR HOVERTEXT !!'); + }) + .then(delay(20)) + .then(_hover) + .then(function() { + assertHoverLabelContent({nums: 'SCALAR HOVERTEXT !!'}); }) .catch(failTest) .then(done); diff --git a/test/jasmine/tests/violin_test.js b/test/jasmine/tests/violin_test.js index 9cca890e9c7..5b0f6ee9da4 100644 --- a/test/jasmine/tests/violin_test.js +++ b/test/jasmine/tests/violin_test.js @@ -424,6 +424,22 @@ describe('Test violin hover:', function() { pos: [180, 240], nums: 'look:0.7', name: '' + }, { + desc: 'only hovertext items on hover', + patch: function(fig) { + fig.data.forEach(function(trace) { + trace.points = 'all'; + trace.hoveron = 'points'; + trace.hovertext = trace.y.map(function(v) { return 'look:' + v; }); + trace.text = trace.y.map(function(v) { return 'NOT THIS:' + v; }); + trace.hoverinfo = 'text'; + }); + fig.layout.hovermode = 'closest'; + return fig; + }, + pos: [180, 240], + nums: 'look:0.7', + name: '' }, { desc: 'one-sided violin under hovermode closest', // hoveron: 'kde+points'