Skip to content

Commit e446743

Browse files
authored
Merge pull request #5563 from plotly/xy-hoverformat
Add (x|y|z)hoverformat to a number of cartesian and gl3d traces
2 parents e3b8709 + aeba545 commit e446743

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+514
-51
lines changed

src/components/fx/hover.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,11 +1609,11 @@ function cleanPoint(d, hovermode) {
16091609

16101610
// and convert the x and y label values into formatted text
16111611
if(d.xLabelVal !== undefined) {
1612-
d.xLabel = ('xLabel' in d) ? d.xLabel : Axes.hoverLabelText(d.xa, d.xLabelVal);
1612+
d.xLabel = ('xLabel' in d) ? d.xLabel : Axes.hoverLabelText(d.xa, d.xLabelVal, trace.xhoverformat);
16131613
d.xVal = d.xa.c2d(d.xLabelVal);
16141614
}
16151615
if(d.yLabelVal !== undefined) {
1616-
d.yLabel = ('yLabel' in d) ? d.yLabel : Axes.hoverLabelText(d.ya, d.yLabelVal);
1616+
d.yLabel = ('yLabel' in d) ? d.yLabel : Axes.hoverLabelText(d.ya, d.yLabelVal, trace.yhoverformat);
16171617
d.yVal = d.ya.c2d(d.yLabelVal);
16181618
}
16191619

src/plots/cartesian/axes.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,16 +1361,23 @@ axes.tickText = function(ax, x, hover, noSuffixPrefix) {
13611361
* log axes (where negative values can't be displayed but can appear in hover text)
13621362
*
13631363
* @param {object} ax: the axis to format text for
1364-
* @param {number} val: calcdata value to format
1365-
* @param {Optional(number)} val2: a second value to display
1364+
* @param {number or array of numbers} values: calcdata value(s) to format
1365+
* @param {Optional(string)} hoverformat: trace (x|y)hoverformat to override axis.hoverformat
13661366
*
13671367
* @returns {string} `val` formatted as a string appropriate to this axis, or
1368-
* `val` and `val2` as a range (ie '<val> - <val2>') if `val2` is provided and
1369-
* it's different from `val`.
1368+
* first value and second value as a range (ie '<val1> - <val2>') if the second value is provided and
1369+
* it's different from the first value.
13701370
*/
1371-
axes.hoverLabelText = function(ax, val, val2) {
1372-
if(val2 !== BADNUM && val2 !== val) {
1373-
return axes.hoverLabelText(ax, val) + ' - ' + axes.hoverLabelText(ax, val2);
1371+
axes.hoverLabelText = function(ax, values, hoverformat) {
1372+
if(hoverformat) ax = Lib.extendFlat({}, ax, {hoverformat: hoverformat});
1373+
1374+
var val = Array.isArray(values) ? values[0] : values;
1375+
var val2 = Array.isArray(values) ? values[1] : undefined;
1376+
if(val2 !== undefined && val2 !== val) {
1377+
return (
1378+
axes.hoverLabelText(ax, val, hoverformat) + ' - ' +
1379+
axes.hoverLabelText(ax, val2, hoverformat)
1380+
);
13741381
}
13751382

13761383
var logOffScale = (ax.type === 'log' && val <= 0);

src/plots/cartesian/layout_attributes.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ var dash = require('../../components/drawing/attributes').dash;
66
var extendFlat = require('../../lib/extend').extendFlat;
77
var templatedArray = require('../../plot_api/plot_template').templatedArray;
88

9-
var FORMAT_LINK = require('../../constants/docs').FORMAT_LINK;
10-
var DATE_FORMAT_LINK = require('../../constants/docs').DATE_FORMAT_LINK;
9+
var docs = require('../../constants/docs');
10+
var FORMAT_LINK = docs.FORMAT_LINK;
11+
var DATE_FORMAT_LINK = docs.DATE_FORMAT_LINK;
12+
1113
var ONEDAY = require('../../constants/numerical').ONEDAY;
1214
var constants = require('./constants');
1315
var HOUR = constants.HOUR_PATTERN;

src/plots/gl3d/scene.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,14 @@ proto.render = function() {
322322
if(trace.setContourLevels) trace.setContourLevels();
323323
}
324324

325-
function formatter(axisName, val) {
326-
var axis = scene.fullSceneLayout[axisName];
325+
function formatter(axLetter, val, hoverformat) {
326+
var ax = scene.fullSceneLayout[axLetter + 'axis'];
327327

328-
return Axes.tickText(axis, axis.d2l(val), 'hover').text;
328+
if(ax.type !== 'log') {
329+
val = ax.d2l(val);
330+
}
331+
332+
return Axes.hoverLabelText(ax, val, hoverformat);
329333
}
330334

331335
var oldEventData;
@@ -337,9 +341,9 @@ proto.render = function() {
337341
var ptNumber = selection.index;
338342

339343
var labels = {
340-
xLabel: formatter('xaxis', selection.traceCoordinate[0]),
341-
yLabel: formatter('yaxis', selection.traceCoordinate[1]),
342-
zLabel: formatter('zaxis', selection.traceCoordinate[2])
344+
xLabel: formatter('x', selection.traceCoordinate[0], trace.xhoverformat),
345+
yLabel: formatter('y', selection.traceCoordinate[1], trace.yhoverformat),
346+
zLabel: formatter('z', selection.traceCoordinate[2], trace.zhoverformat)
343347
};
344348

345349
var hoverinfo = Fx.castHoverinfo(traceNow, scene.fullLayout, ptNumber);
@@ -358,17 +362,17 @@ proto.render = function() {
358362
var vectorTx = [];
359363

360364
if(trace.type === 'cone' || trace.type === 'streamtube') {
361-
labels.uLabel = formatter('xaxis', selection.traceCoordinate[3]);
365+
labels.uLabel = formatter('x', selection.traceCoordinate[3], trace.uhoverformat);
362366
if(isHoverinfoAll || hoverinfoParts.indexOf('u') !== -1) {
363367
vectorTx.push('u: ' + labels.uLabel);
364368
}
365369

366-
labels.vLabel = formatter('yaxis', selection.traceCoordinate[4]);
370+
labels.vLabel = formatter('y', selection.traceCoordinate[4], trace.vhoverformat);
367371
if(isHoverinfoAll || hoverinfoParts.indexOf('v') !== -1) {
368372
vectorTx.push('v: ' + labels.vLabel);
369373
}
370374

371-
labels.wLabel = formatter('zaxis', selection.traceCoordinate[5]);
375+
labels.wLabel = formatter('z', selection.traceCoordinate[5], trace.whoverformat);
372376
if(isHoverinfoAll || hoverinfoParts.indexOf('w') !== -1) {
373377
vectorTx.push('w: ' + labels.wLabel);
374378
}
@@ -388,7 +392,7 @@ proto.render = function() {
388392
}
389393
tx = vectorTx.join('<br>');
390394
} else if(trace.type === 'isosurface' || trace.type === 'volume') {
391-
labels.valueLabel = Axes.tickText(scene._mockAxis, scene._mockAxis.d2l(selection.traceCoordinate[3]), 'hover').text;
395+
labels.valueLabel = Axes.hoverLabelText(scene._mockAxis, scene._mockAxis.d2l(selection.traceCoordinate[3]), trace.valuehoverformat);
392396
vectorTx.push('value: ' + labels.valueLabel);
393397
if(selection.textLabel) {
394398
vectorTx.push(selection.textLabel);

src/plots/hoverformat_attributes.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
var docs = require('../constants/docs');
4+
var FORMAT_LINK = docs.FORMAT_LINK;
5+
var DATE_FORMAT_LINK = docs.DATE_FORMAT_LINK;
6+
7+
module.exports = function axisHoverFormat(x, noDates) {
8+
return {
9+
valType: 'string',
10+
dflt: '',
11+
editType: 'none',
12+
description: [
13+
'Sets the hover text formatting rule for `' + x + '`',
14+
' using d3 formatting mini-languages which are very similar to those in Python.',
15+
'See: ' + FORMAT_LINK + (
16+
noDates ?
17+
'' :
18+
' And for dates see: ' + DATE_FORMAT_LINK
19+
),
20+
'By default the values are formatted using ' + (
21+
noDates ?
22+
'generic number format' :
23+
('`' + x + 'axis.hoverformat`')
24+
) + '.',
25+
].join(' ')
26+
};
27+
};

src/plots/template_attributes.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

3-
var FORMAT_LINK = require('../constants/docs').FORMAT_LINK;
4-
var DATE_FORMAT_LINK = require('../constants/docs').DATE_FORMAT_LINK;
3+
var docs = require('../constants/docs');
4+
var FORMAT_LINK = docs.FORMAT_LINK;
5+
var DATE_FORMAT_LINK = docs.DATE_FORMAT_LINK;
56

67
var templateFormatStringDescription = [
78
'Variables are inserted using %{variable}, for example "y: %{y}".',

src/traces/bar/attributes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
var scatterAttrs = require('../scatter/attributes');
4+
var axisHoverFormat = require('../../plots/hoverformat_attributes');
45
var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs;
56
var texttemplateAttrs = require('../../plots/template_attributes').texttemplateAttrs;
67
var colorScaleAttrs = require('../../components/colorscale/attributes');
@@ -104,6 +105,8 @@ module.exports = {
104105
yperiod0: scatterAttrs.yperiod0,
105106
xperiodalignment: scatterAttrs.xperiodalignment,
106107
yperiodalignment: scatterAttrs.yperiodalignment,
108+
xhoverformat: axisHoverFormat('x'),
109+
yhoverformat: axisHoverFormat('y'),
107110

108111
text: scatterAttrs.text,
109112
texttemplate: texttemplateAttrs({editType: 'plot'}, {

src/traces/bar/defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
2424
}
2525

2626
handlePeriodDefaults(traceIn, traceOut, layout, coerce);
27+
coerce('xhoverformat');
28+
coerce('yhoverformat');
2729

2830
coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v');
2931
coerce('base');

src/traces/bar/hover.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,9 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
170170
var hasPeriod = di.orig_p !== undefined;
171171
pointData[posLetter + 'LabelVal'] = hasPeriod ? di.orig_p : di.p;
172172

173-
pointData.labelLabel = hoverLabelText(pa, pointData[posLetter + 'LabelVal']);
174-
pointData.valueLabel = hoverLabelText(sa, pointData[sizeLetter + 'LabelVal']);
175-
pointData.baseLabel = hoverLabelText(sa, di.b);
173+
pointData.labelLabel = hoverLabelText(pa, pointData[posLetter + 'LabelVal'], trace[posLetter + 'hoverformat']);
174+
pointData.valueLabel = hoverLabelText(sa, pointData[sizeLetter + 'LabelVal'], trace[sizeLetter + 'hoverformat']);
175+
pointData.baseLabel = hoverLabelText(sa, di.b, trace[sizeLetter + 'hoverformat']);
176176

177177
// spikelines always want "closest" distance regardless of hovermode
178178
pointData.spikeDistance = (thisBarSizeFn(di) + thisBarPositionFn(di)) / 2;

src/traces/box/attributes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var scatterAttrs = require('../scatter/attributes');
44
var barAttrs = require('../bar/attributes');
55
var colorAttrs = require('../../components/color/attributes');
6+
var axisHoverFormat = require('../../plots/hoverformat_attributes');
67
var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs;
78
var extendFlat = require('../../lib/extend').extendFlat;
89

@@ -70,6 +71,8 @@ module.exports = {
7071
yperiod0: scatterAttrs.yperiod0,
7172
xperiodalignment: scatterAttrs.xperiodalignment,
7273
yperiodalignment: scatterAttrs.yperiodalignment,
74+
xhoverformat: axisHoverFormat('x'),
75+
yhoverformat: axisHoverFormat('y'),
7376

7477
name: {
7578
valType: 'string',

0 commit comments

Comments
 (0)