Skip to content

Commit e612205

Browse files
authored
Merge pull request #1523 from plotly/hovertext-on-hover
Add 'hovertext' attribute in scatter* traces
2 parents d3bd87f + 1bf54e2 commit e612205

30 files changed

+449
-72
lines changed

src/traces/bar/arrays_to_calcdata.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var mergeArray = require('../../lib').mergeArray;
1515
// arrayOk attributes, merge them into calcdata array
1616
module.exports = function arraysToCalcdata(cd, trace) {
1717
mergeArray(trace.text, cd, 'tx');
18+
mergeArray(trace.hovertext, cd, 'htx');
1819

1920
var marker = trace.marker;
2021
if(marker) {

src/traces/bar/attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ module.exports = {
4949
dy: scatterAttrs.dy,
5050

5151
text: scatterAttrs.text,
52+
hovertext: scatterAttrs.hovertext,
5253

5354
textposition: {
5455
valType: 'enumerated',

src/traces/bar/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3737
coerce('width');
3838

3939
coerce('text');
40+
coerce('hovertext');
4041

4142
var textPosition = coerce('textposition');
4243

src/traces/bar/hover.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
9999
pointData.xLabelVal = di.p;
100100
}
101101

102-
if(di.tx) pointData.text = di.tx;
102+
if(di.htx) pointData.text = di.htx;
103+
else if(trace.hovertext) pointData.text = trace.hovertext;
104+
else if(di.tx) pointData.text = di.tx;
105+
else if(trace.text) pointData.text = trace.text;
103106

104107
ErrorBars.hoverInfo(di, trace, pointData);
105108

src/traces/pie/attributes.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,27 @@ module.exports = {
7979

8080
text: {
8181
valType: 'data_array',
82-
description: 'Sets text elements associated with each sector.'
82+
description: [
83+
'Sets text elements associated with each sector.',
84+
'If trace `textinfo` contains a *text* flag, these elements will seen',
85+
'on the chart.',
86+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
87+
'these elements will be seen in the hover labels.'
88+
].join(' ')
89+
},
90+
hovertext: {
91+
valType: 'string',
92+
role: 'info',
93+
dflt: '',
94+
arrayOk: true,
95+
description: [
96+
'Sets hover text elements associated with each sector.',
97+
'If a single string, the same string appears for',
98+
'all data points.',
99+
'If an array of string, the items are mapped in order of',
100+
'this trace\'s sectors.',
101+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
102+
].join(' ')
83103
},
84104

85105
// 'see eg:'

src/traces/pie/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
4545

4646
var textData = coerce('text');
4747
var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent');
48+
coerce('hovertext');
4849

4950
coerce('hoverinfo', (layout._dataLength === 1) ? 'label+text+value+percent' : undefined);
5051

src/traces/pie/plot.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,16 @@ module.exports = function plot(gd, cdpie) {
110110
thisText = [];
111111

112112
if(hoverinfo.indexOf('label') !== -1) thisText.push(pt.label);
113-
if(trace2.text && trace2.text[pt.i] && hoverinfo.indexOf('text') !== -1) {
114-
thisText.push(trace2.text[pt.i]);
113+
if(hoverinfo.indexOf('text') !== -1) {
114+
if(trace2.hovertext) {
115+
thisText.push(
116+
Array.isArray(trace2.hovertext) ?
117+
trace2.hovertext[pt.i] :
118+
trace2.hovertext
119+
);
120+
} else if(trace2.text && trace2.text[pt.i]) {
121+
thisText.push(trace2.text[pt.i]);
122+
}
115123
}
116124
if(hoverinfo.indexOf('value') !== -1) thisText.push(helpers.formatPieValue(pt.v, separators));
117125
if(hoverinfo.indexOf('percent') !== -1) thisText.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators));

src/traces/scatter/arrays_to_calcdata.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var Lib = require('../../lib');
1616
module.exports = function arraysToCalcdata(cd, trace) {
1717

1818
Lib.mergeArray(trace.text, cd, 'tx');
19+
Lib.mergeArray(trace.hovertext, cd, 'htx');
1920
Lib.mergeArray(trace.customdata, cd, 'data');
2021
Lib.mergeArray(trace.textposition, cd, 'tp');
2122
if(trace.textfont) {

src/traces/scatter/attributes.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,23 @@ module.exports = {
8383
'If a single string, the same string appears over',
8484
'all the data points.',
8585
'If an array of string, the items are mapped in order to the',
86-
'this trace\'s (x,y) coordinates.'
86+
'this trace\'s (x,y) coordinates.',
87+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
88+
'these elements will be seen in the hover labels.'
89+
].join(' ')
90+
},
91+
hovertext: {
92+
valType: 'string',
93+
role: 'info',
94+
dflt: '',
95+
arrayOk: true,
96+
description: [
97+
'Sets hover text elements associated with each (x,y) pair.',
98+
'If a single string, the same string appears over',
99+
'all the data points.',
100+
'If an array of string, the items are mapped in order to the',
101+
'this trace\'s (x,y) coordinates.',
102+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
87103
].join(' ')
88104
},
89105
mode: {

src/traces/scatter/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3838

3939
coerce('customdata');
4040
coerce('text');
41+
coerce('hovertext');
4142
coerce('mode', defaultMode);
4243
coerce('ids');
4344

src/traces/scatter/hover.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
7272
yLabelVal: di.y
7373
});
7474

75-
if(di.tx) pointData.text = di.tx;
75+
if(di.htx) pointData.text = di.htx;
76+
else if(trace.hovertext) pointData.text = trace.hovertext;
77+
else if(di.tx) pointData.text = di.tx;
7678
else if(trace.text) pointData.text = trace.text;
7779

7880
ErrorBars.hoverInfo(di, trace, pointData);

src/traces/scatter3d/attributes.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,22 @@ module.exports = {
7272
'If a single string, the same string appears over',
7373
'all the data points.',
7474
'If an array of string, the items are mapped in order to the',
75-
'this trace\'s (x,y,z) coordinates.'
75+
'this trace\'s (x,y,z) coordinates.',
76+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
77+
'these elements will be seen in the hover labels.'
7678
].join(' ')
7779
}),
80+
hovertext: extendFlat({}, scatterAttrs.hovertext, {
81+
description: [
82+
'Sets text elements associated with each (x,y,z) triplet.',
83+
'If a single string, the same string appears over',
84+
'all the data points.',
85+
'If an array of string, the items are mapped in order to the',
86+
'this trace\'s (x,y,z) coordinates.',
87+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
88+
].join(' ')
89+
}),
90+
7891
mode: extendFlat({}, scatterAttrs.mode, // shouldn't this be on-par with 2D?
7992
{dflt: 'lines+markers'}),
8093
surfaceaxis: {

src/traces/scatter3d/convert.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,12 @@ proto.handlePick = function(selection) {
5858
selection.object = this.scatterPlot;
5959
this.scatterPlot.highlight(selection.data);
6060
}
61-
if(this.textLabels && this.textLabels[selection.data.index] !== undefined) {
62-
selection.textLabel = this.textLabels[selection.data.index];
61+
if(this.textLabels) {
62+
if(this.textLabels[selection.data.index] !== undefined) {
63+
selection.textLabel = this.textLabels[selection.data.index];
64+
} else {
65+
selection.textLabel = this.textLabels;
66+
}
6367
}
6468
else selection.textLabel = '';
6569

@@ -371,7 +375,7 @@ proto.update = function(data) {
371375
opacity: data.opacity
372376
};
373377

374-
this.textLabels = options.text;
378+
this.textLabels = data.hovertext || data.text;
375379

376380
if(this.mode.indexOf('text') !== -1) {
377381
if(this.textMarkers) this.textMarkers.update(textOptions);

src/traces/scatter3d/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3434
}
3535

3636
coerce('text');
37+
coerce('hovertext');
3738
coerce('mode');
3839

3940
if(subTypes.hasLines(traceOut)) {

src/traces/scattergeo/attributes.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,23 @@ module.exports = {
5656
'If a single string, the same string appears over',
5757
'all the data points.',
5858
'If an array of string, the items are mapped in order to the',
59-
'this trace\'s (lon,lat) or `locations` coordinates.'
59+
'this trace\'s (lon,lat) or `locations` coordinates.',
60+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
61+
'these elements will be seen in the hover labels.'
6062
].join(' ')
6163
}),
64+
hovertext: extendFlat({}, scatterAttrs.hovertext, {
65+
description: [
66+
'Sets hover text elements associated with each (lon,lat) pair',
67+
'or item in `locations`.',
68+
'If a single string, the same string appears over',
69+
'all the data points.',
70+
'If an array of string, the items are mapped in order to the',
71+
'this trace\'s (lon,lat) or `locations` coordinates.',
72+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
73+
].join(' ')
74+
}),
75+
6276
textfont: scatterAttrs.textfont,
6377
textposition: scatterAttrs.textposition,
6478

src/traces/scattergeo/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3232
}
3333

3434
coerce('text');
35+
coerce('hovertext');
3536
coerce('mode');
3637

3738
if(subTypes.hasLines(traceOut)) {

src/traces/scattergeo/hover.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,13 @@ function getExtraText(trace, pt, axis) {
101101
else if(hasLat) text.push('lat: ' + format(pt.lonlat[1]));
102102

103103
if(hasText) {
104-
var tx = pt.tx || trace.text;
104+
var tx;
105+
106+
if(pt.htx) tx = pt.htx;
107+
else if(trace.hovertext) tx = trace.hovertext;
108+
else if(pt.tx) tx = pt.tx;
109+
else if(trace.text) tx = trace.text;
110+
105111
if(!Array.isArray(tx)) text.push(tx);
106112
}
107113

src/traces/scattermapbox/attributes.js

+15-7
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,35 @@ module.exports = {
2727
// locations
2828
// locationmode
2929

30-
mode: {
31-
valType: 'flaglist',
32-
flags: ['lines', 'markers', 'text'],
30+
mode: extendFlat({}, scatterAttrs.mode, {
3331
dflt: 'markers',
34-
extras: ['none'],
35-
role: 'info',
3632
description: [
3733
'Determines the drawing mode for this scatter trace.',
3834
'If the provided `mode` includes *text* then the `text` elements',
3935
'appear at the coordinates. Otherwise, the `text` elements',
4036
'appear on hover.'
4137
].join(' ')
42-
},
38+
}),
4339

4440
text: extendFlat({}, scatterAttrs.text, {
4541
description: [
4642
'Sets text elements associated with each (lon,lat) pair',
4743
'If a single string, the same string appears over',
4844
'all the data points.',
4945
'If an array of string, the items are mapped in order to the',
50-
'this trace\'s (lon,lat) coordinates.'
46+
'this trace\'s (lon,lat) coordinates.',
47+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
48+
'these elements will be seen in the hover labels.'
49+
].join(' ')
50+
}),
51+
hovertext: extendFlat({}, scatterAttrs.hovertext, {
52+
description: [
53+
'Sets hover text elements associated with each (lon,lat) pair',
54+
'If a single string, the same string appears over',
55+
'all the data points.',
56+
'If an array of string, the items are mapped in order to the',
57+
'this trace\'s (lon,lat) coordinates.',
58+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
5159
].join(' ')
5260
}),
5361

src/traces/scattermapbox/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
4242
}
4343

4444
coerce('text');
45+
coerce('hovertext');
4546
coerce('mode');
4647

4748
if(subTypes.hasLines(traceOut)) {

src/traces/scattermapbox/hover.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,13 @@ function getExtraText(trace, di) {
8787
else if(hasLat) text.push('lat: ' + format(lonlat[1]));
8888

8989
if(isAll || hoverinfo.indexOf('text') !== -1) {
90-
var tx = di.tx || trace.text;
90+
var tx;
91+
92+
if(di.htx) tx = di.htx;
93+
else if(trace.hovertext) tx = trace.hovertext;
94+
else if(di.tx) tx = di.tx;
95+
else if(trace.text) tx = trace.text;
96+
9197
if(!Array.isArray(tx)) text.push(tx);
9298
}
9399

src/traces/scatterternary/attributes.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,19 @@ module.exports = {
7070
'If a single string, the same string appears over',
7171
'all the data points.',
7272
'If an array of strings, the items are mapped in order to the',
73-
'the data points in (a,b,c).'
73+
'the data points in (a,b,c).',
74+
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
75+
'these elements will be seen in the hover labels.'
76+
].join(' ')
77+
}),
78+
hovertext: extendFlat({}, scatterAttrs.hovertext, {
79+
description: [
80+
'Sets hover text elements associated with each (a,b,c) point.',
81+
'If a single string, the same string appears over',
82+
'all the data points.',
83+
'If an array of strings, the items are mapped in order to the',
84+
'the data points in (a,b,c).',
85+
'To be seen, trace `hoverinfo` must contain a *text* flag.'
7486
].join(' ')
7587
}),
7688
line: {

src/traces/scatterternary/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
6363
coerce('sum');
6464

6565
coerce('text');
66+
coerce('hovertext');
6667

6768
var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines';
6869
coerce('mode', defaultMode);

test/image/mocks/text_chart_arrays.json

+15
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
"top left",
4141
"top left"
4242
],
43+
"hovertext": [
44+
"Hover text\nA",
45+
"Hover text\rB",
46+
"Hover text\r\nC"
47+
],
4348
"type": "scatter",
4449
"uid": "459c77"
4550
},
@@ -83,6 +88,11 @@
8388
"bottom left",
8489
"bottom left"
8590
],
91+
"hovertext": [
92+
"Hover text G",
93+
"Hover text H",
94+
"Hover text I"
95+
],
8696
"type": "scatter",
8797
"uid": "f8361c"
8898
},
@@ -103,6 +113,11 @@
103113
"a",
104114
"",
105115
"b"
116+
],
117+
"hovertext": [
118+
"a (hover)",
119+
"",
120+
"b (hover)"
106121
]
107122
}
108123
],

0 commit comments

Comments
 (0)