Skip to content

Commit db854f7

Browse files
authored
Merge pull request #3958 from plotly/fix3954-funnel-hoverinfo
Implement percentage flags to control funnel hoverinfo and hovertemplete
2 parents 3e3b22d + ea54842 commit db854f7

File tree

6 files changed

+148
-12
lines changed

6 files changed

+148
-12
lines changed

src/traces/funnel/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

@@ -22,7 +25,13 @@ module.exports = {
2225
dy: barAttrs.dy,
2326

2427
hovertext: barAttrs.hovertext,
25-
hovertemplate: barAttrs.hovertemplate,
28+
hovertemplate: hovertemplateAttrs({}, {
29+
keys: constants.eventDataKeys
30+
}),
31+
32+
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
33+
flags: ['name', 'x', 'y', 'text', 'percent initial', 'percent previous', 'percent total']
34+
}),
2635

2736
textinfo: {
2837
valType: 'flaglist',

src/traces/funnel/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+
'percentInitial',
14+
'percentPrevious',
15+
'percentTotal'
16+
]
17+
};

src/traces/funnel/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('percentInitial' in pt) out.percentInitial = pt.percentInitial;
18+
if('percentPrevious' in pt) out.percentPrevious = pt.percentPrevious;
19+
if('percentTotal' in pt) out.percentTotal = pt.percentTotal;
20+
21+
if(pt.xa) out.xaxis = pt.xa;
22+
if(pt.ya) out.yaxis = pt.ya;
23+
24+
return out;
25+
};

src/traces/funnel/hover.js

+28-8
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,36 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
2525
var di = cd[index];
2626

2727
var sizeLetter = isHorizontal ? 'x' : 'y';
28-
2928
point[sizeLetter + 'LabelVal'] = di.s;
3029

31-
// display ratio to initial value
32-
point.extraText = [
33-
formatPercent(di.begR, 1) + ' of initial',
34-
formatPercent(di.difR, 1) + ' of previous',
35-
formatPercent(di.sumR, 1) + ' of total'
36-
].join('<br>');
37-
// TODO: Should we use pieHelpers.formatPieValue instead ?
30+
point.percentInitial = di.begR;
31+
point.percentInitialLabel = formatPercent(di.begR, 1);
32+
33+
point.percentPrevious = di.difR;
34+
point.percentPreviousLabel = formatPercent(di.difR, 1);
35+
36+
point.percentTotal = di.sumR;
37+
point.percentTotalLabel = formatPercent(di.sumR, 1);
38+
39+
var hoverinfo = di.hi || trace.hoverinfo;
40+
var text = [];
41+
if(hoverinfo && hoverinfo !== 'none' && hoverinfo !== 'skip') {
42+
var isAll = (hoverinfo === 'all');
43+
var parts = hoverinfo.split('+');
44+
45+
var hasFlag = function(flag) { return isAll || parts.indexOf(flag) !== -1; };
46+
47+
if(hasFlag('percent initial')) {
48+
text.push(point.percentInitialLabel + ' of initial');
49+
}
50+
if(hasFlag('percent previous')) {
51+
text.push(point.percentPreviousLabel + ' of previous');
52+
}
53+
if(hasFlag('percent total')) {
54+
text.push(point.percentTotalLabel + ' of total');
55+
}
56+
}
57+
point.extraText = text.join('<br>');
3858

3959
point.color = getTraceColor(trace, di);
4060

src/traces/funnel/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',

test/jasmine/tests/funnel_test.js

+66-3
Original file line numberDiff line numberDiff line change
@@ -1326,14 +1326,74 @@ describe('funnel hover', function() {
13261326
.then(done);
13271327
});
13281328

1329+
it('should turn off percentages with hoveinfo none or skip', function(done) {
1330+
gd = createGraphDiv();
1331+
1332+
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
1333+
mock.data.forEach(function(t, i) {
1334+
t.type = 'funnel';
1335+
t.orientation = 'v';
1336+
if(i === 0) {
1337+
t.hoverinfo = 'none';
1338+
} else {
1339+
t.hoverinfo = 'skip';
1340+
}
1341+
});
1342+
1343+
function _hover() {
1344+
var evt = { xpx: 125, ypx: 150 };
1345+
Fx.hover('graph', evt, 'xy');
1346+
}
1347+
1348+
Plotly.plot(gd, mock)
1349+
.then(_hover)
1350+
.then(function() {
1351+
expect(d3.selectAll('g.hovertext').size()).toBe(0);
1352+
})
1353+
.catch(failTest)
1354+
.then(done);
1355+
});
1356+
1357+
it('should turn on percentages with hoveinfo all', function(done) {
1358+
gd = createGraphDiv();
1359+
1360+
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
1361+
mock.data.forEach(function(t) {
1362+
t.type = 'funnel';
1363+
t.orientation = 'v';
1364+
t.hoverinfo = 'all';
1365+
});
1366+
1367+
function _hover() {
1368+
var evt = { xpx: 125, ypx: 150 };
1369+
Fx.hover('graph', evt, 'xy');
1370+
}
1371+
1372+
Plotly.plot(gd, mock)
1373+
.then(_hover)
1374+
.then(function() {
1375+
assertHoverLabelContent({
1376+
nums: [
1377+
'1\nHover text A\n100% of initial\n100% of previous\n33.3% of total',
1378+
'2\nHover text G\n100% of initial\n100% of previous\n33.3% of total',
1379+
'1.5\na (hover)\n100% of initial\n100% of previous\n33.3% of total'
1380+
],
1381+
name: ['Lines, Marke...', 'Lines and Text', 'missing text'],
1382+
axis: '0'
1383+
});
1384+
})
1385+
.catch(failTest)
1386+
.then(done);
1387+
});
1388+
13291389
it('should use hovertemplate if specified', function(done) {
13301390
gd = createGraphDiv();
13311391

13321392
var mock = Lib.extendDeep({}, require('@mocks/text_chart_arrays'));
13331393
mock.data.forEach(function(t) {
13341394
t.type = 'funnel';
13351395
t.orientation = 'v';
1336-
t.hovertemplate = '%{y}<extra></extra>';
1396+
t.hovertemplate = 'Value: %{y}<br>Total percentage: %{percentTotal}<br>Initial percentage: %{percentInitial}<br>Previous percentage: %{percentPrevious}<extra></extra>';
13371397
});
13381398

13391399
function _hover() {
@@ -1345,11 +1405,14 @@ describe('funnel hover', function() {
13451405
.then(_hover)
13461406
.then(function() {
13471407
assertHoverLabelContent({
1348-
nums: ['1', '2', '1.5'],
1408+
nums: [
1409+
'Value: 1\nTotal percentage: 33.3%\nInitial percentage: 100%\nPrevious percentage: 100%',
1410+
'Value: 2\nTotal percentage: 33.3%\nInitial percentage: 100%\nPrevious percentage: 100%',
1411+
'Value: 1.5\nTotal percentage: 33.3%\nInitial percentage: 100%\nPrevious percentage: 100%'
1412+
],
13491413
name: ['', '', ''],
13501414
axis: '0'
13511415
});
1352-
// return Plotly.restyle(gd, 'text', ['APPLE', 'BANANA', 'ORANGE']);
13531416
})
13541417
.catch(failTest)
13551418
.then(done);

0 commit comments

Comments
 (0)