Skip to content

Commit a0021cd

Browse files
authored
Merge pull request #3963 from plotly/waterfall-hoverinfo-and-hovertemplate-flags
fixup hoverinfo & hovertemplate initial, delta and final flags for waterfalls
2 parents 0690162 + 0a58836 commit a0021cd

File tree

6 files changed

+155
-13
lines changed

6 files changed

+155
-13
lines changed

Diff for: src/traces/waterfall/attributes.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
var barAttrs = require('../bar/attributes');
1212
var lineAttrs = require('../scatter/attributes').line;
13+
var plotAttrs = require('../../plots/attributes');
14+
var hovertemplateAttrs = require('../../components/fx/hovertemplate_attributes');
15+
var constants = require('./constants');
1316
var extendFlat = require('../../lib/extend').extendFlat;
1417
var Color = require('../../components/color');
1518

@@ -74,7 +77,13 @@ module.exports = {
7477
dy: barAttrs.dy,
7578

7679
hovertext: barAttrs.hovertext,
77-
hovertemplate: barAttrs.hovertemplate,
80+
hovertemplate: hovertemplateAttrs({}, {
81+
keys: constants.eventDataKeys
82+
}),
83+
84+
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
85+
flags: ['name', 'x', 'y', 'text', 'initial', 'delta', 'final']
86+
}),
7887

7988
textinfo: {
8089
valType: 'flaglist',

Diff for: src/traces/waterfall/constants.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2012-2019, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = {
12+
eventDataKeys: [
13+
'initial',
14+
'delta',
15+
'final'
16+
]
17+
};

Diff for: src/traces/waterfall/event_data.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright 2012-2019, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = function eventData(out, pt /* , trace, cd, pointNumber */) {
12+
// standard cartesian event data
13+
out.x = 'xVal' in pt ? pt.xVal : pt.x;
14+
out.y = 'yVal' in pt ? pt.yVal : pt.y;
15+
16+
// for funnel
17+
if('initial' in pt) out.initial = pt.initial;
18+
if('delta' in pt) out.delta = pt.delta;
19+
if('final' in pt) out.final = pt.final;
20+
21+
if(pt.xa) out.xaxis = pt.xa;
22+
if(pt.ya) out.yaxis = pt.ya;
23+
24+
return out;
25+
};

Diff for: src/traces/waterfall/hover.js

+36-9
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,45 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
3838
var size = (di.isSum) ? di.b + di.s : di.rawS;
3939

4040
if(!di.isSum) {
41-
// format delta numbers:
42-
if(size > 0) {
43-
point.extraText = formatNumber(size) + ' ' + DIRSYMBOL.increasing;
44-
} else if(size < 0) {
45-
point.extraText = '(' + (formatNumber(-size)) + ') ' + DIRSYMBOL.decreasing;
46-
} else {
47-
return;
41+
point.initial = di.b + di.s - size;
42+
point.delta = size;
43+
point.final = point.initial + point.delta;
44+
45+
var v = formatNumber(Math.abs(point.delta));
46+
point.deltaLabel = size < 0 ? '(' + v + ')' : v;
47+
point.finalLabel = formatNumber(point.final);
48+
point.initialLabel = formatNumber(point.initial);
49+
}
50+
51+
var hoverinfo = di.hi || trace.hoverinfo;
52+
var text = [];
53+
if(hoverinfo && hoverinfo !== 'none' && hoverinfo !== 'skip') {
54+
var isAll = (hoverinfo === 'all');
55+
var parts = hoverinfo.split('+');
56+
57+
var hasFlag = function(flag) { return isAll || parts.indexOf(flag) !== -1; };
58+
59+
if(!di.isSum) {
60+
if(hasFlag('final') &&
61+
(isHorizontal ? !hasFlag('x') : !hasFlag('y')) // don't display redundant info.
62+
) {
63+
text.push(point.finalLabel);
64+
}
65+
if(hasFlag('delta')) {
66+
if(size < 0) {
67+
text.push(point.deltaLabel + ' ' + DIRSYMBOL.decreasing);
68+
} else {
69+
text.push(point.deltaLabel + ' ' + DIRSYMBOL.increasing);
70+
}
71+
}
72+
if(hasFlag('initial')) {
73+
text.push('Initial: ' + point.initialLabel);
74+
}
4875
}
49-
// display initial value
50-
point.extraText += '<br>Initial: ' + formatNumber(di.b + di.s - size);
5176
}
5277

78+
if(text.length) point.extraText = text.join('<br>');
79+
5380
point.color = getTraceColor(trace, di);
5481

5582
return [point];

Diff for: src/traces/waterfall/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ module.exports = {
1919
plot: require('./plot'),
2020
style: require('./style').style,
2121
hoverPoints: require('./hover'),
22+
eventData: require('./event_data'),
23+
2224
selectPoints: require('../bar/select'),
2325

2426
moduleType: 'trace',

Diff for: test/jasmine/tests/waterfall_test.js

+65-3
Original file line numberDiff line numberDiff line change
@@ -1379,13 +1379,72 @@ describe('waterfall hover', function() {
13791379
.then(done);
13801380
});
13811381

1382+
it('should turn off hoverinfo flags with hoveinfo none or skip', function(done) {
1383+
gd = createGraphDiv();
1384+
1385+
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
1386+
mock.data.forEach(function(t, i) {
1387+
t.type = 'waterfall';
1388+
if(i === 0) {
1389+
t.hoverinfo = 'none';
1390+
} else {
1391+
t.hoverinfo = 'skip';
1392+
}
1393+
});
1394+
1395+
function _hover() {
1396+
var evt = { xpx: 125, ypx: 150 };
1397+
Fx.hover('graph', evt, 'xy');
1398+
}
1399+
1400+
Plotly.plot(gd, mock)
1401+
.then(_hover)
1402+
.then(function() {
1403+
expect(d3.selectAll('g.hovertext').size()).toBe(0);
1404+
})
1405+
.catch(failTest)
1406+
.then(done);
1407+
});
1408+
1409+
it('should turn on hoverinfo flags with hoveinfo all', function(done) {
1410+
gd = createGraphDiv();
1411+
1412+
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
1413+
mock.data.forEach(function(t) {
1414+
t.type = 'waterfall';
1415+
t.base = 1000;
1416+
t.hoverinfo = 'all';
1417+
});
1418+
1419+
function _hover() {
1420+
var evt = { xpx: 125, ypx: 150 };
1421+
Fx.hover('graph', evt, 'xy');
1422+
}
1423+
1424+
Plotly.plot(gd, mock)
1425+
.then(_hover)
1426+
.then(function() {
1427+
assertHoverLabelContent({
1428+
nums: [
1429+
'1001\nHover text A\n1 ▲\nInitial: 1000',
1430+
'1002\nHover text G\n2 ▲\nInitial: 1000',
1431+
'1,001.5\na (hover)\n1.5 ▲\nInitial: 1000'
1432+
],
1433+
name: ['Lines, Marke...', 'Lines and Text', 'missing text'],
1434+
axis: '0'
1435+
});
1436+
})
1437+
.catch(failTest)
1438+
.then(done);
1439+
});
1440+
13821441
it('should use hovertemplate if specified', function(done) {
13831442
gd = createGraphDiv();
13841443

13851444
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
13861445
mock.data.forEach(function(t) {
13871446
t.type = 'waterfall';
1388-
t.hovertemplate = '%{y}<extra></extra>';
1447+
t.hovertemplate = 'Value: %{y}<br>SUM: %{final}<br>START: %{initial}<br>DIFF: %{delta}<extra></extra>';
13891448
});
13901449

13911450
function _hover() {
@@ -1397,11 +1456,14 @@ describe('waterfall hover', function() {
13971456
.then(_hover)
13981457
.then(function() {
13991458
assertHoverLabelContent({
1400-
nums: ['1', '2', '1.5'],
1459+
nums: [
1460+
'Value: 1\nSUM: 1\nSTART: 0\nDIFF: 1',
1461+
'Value: 2\nSUM: 2\nSTART: 0\nDIFF: 2',
1462+
'Value: 1.5\nSUM: 1.5\nSTART: 0\nDIFF: 1.5'
1463+
],
14011464
name: ['', '', ''],
14021465
axis: '0'
14031466
});
1404-
// return Plotly.restyle(gd, 'text', ['APPLE', 'BANANA', 'ORANGE']);
14051467
})
14061468
.catch(failTest)
14071469
.then(done);

0 commit comments

Comments
 (0)