diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js
index 37653f9c3a8..ee16cc099e4 100644
--- a/src/traces/bar/plot.js
+++ b/src/traces/bar/plot.js
@@ -1105,52 +1105,43 @@ function calcTextinfo(cd, index, xa, ya) {
var text = [];
var tx;
- var hasFlag = function (flag) {
+ function hasFlag(flag) {
return parts.indexOf(flag) !== -1;
- };
-
- if (hasFlag('label')) {
- text.push(formatLabel(cd[index].p));
}
- if (hasFlag('text')) {
- tx = Lib.castOption(trace, cdi.i, 'text');
- if (tx === 0 || tx) text.push(tx);
+ var nPercent = 0;
+ if(isFunnel) {
+ if(hasFlag('percent initial')) nPercent++;
+ if(hasFlag('percent previous')) nPercent++;
+ if(hasFlag('percent total')) nPercent++;
}
-
- if (isWaterfall) {
- var delta = +cdi.rawS || cdi.s;
- var final = cdi.v;
- var initial = final - delta;
-
- if (hasFlag('initial')) text.push(formatNumber(initial));
- if (hasFlag('delta')) text.push(formatNumber(delta));
- if (hasFlag('final')) text.push(formatNumber(final));
- }
-
- if (isFunnel) {
- if (hasFlag('value')) text.push(formatNumber(cdi.s));
-
- var nPercent = 0;
- if (hasFlag('percent initial')) nPercent++;
- if (hasFlag('percent previous')) nPercent++;
- if (hasFlag('percent total')) nPercent++;
-
- var hasMultiplePercents = nPercent > 1;
-
- if (hasFlag('percent initial')) {
+ var hasMultiplePercents = nPercent > 1;
+ for(var i in parts) {
+ var part = parts[i];
+ if(part === 'label') {
+ text.push(formatLabel(cdi.p));
+ } else if(part === 'text') {
+ tx = Lib.castOption(trace, cdi.i, 'text');
+ if(tx === 0 || tx) text.push(tx);
+ } else if(isWaterfall && part === 'initial') {
+ text.push(formatNumber(cdi.v - (+cdi.rawS || cdi.s)));
+ } else if(isWaterfall && part === 'delta') {
+ text.push(formatNumber(+cdi.rawS || cdi.s));
+ } else if(isWaterfall && part === 'final') {
+ text.push(formatNumber(cdi.v));
+ } else if(isFunnel && part === 'value') {
+ text.push(formatNumber(cdi.s));
+ } else if(isFunnel && part === 'percent initial') {
tx = Lib.formatPercent(cdi.begR);
- if (hasMultiplePercents) tx += ' of initial';
+ if(hasMultiplePercents) tx += ' of initial';
text.push(tx);
- }
- if (hasFlag('percent previous')) {
+ } else if(isFunnel && part === 'percent previous') {
tx = Lib.formatPercent(cdi.difR);
- if (hasMultiplePercents) tx += ' of previous';
+ if(hasMultiplePercents) tx += ' of previous';
text.push(tx);
- }
- if (hasFlag('percent total')) {
+ } else if(isFunnel && part === 'percent total') {
tx = Lib.formatPercent(cdi.sumR);
- if (hasMultiplePercents) tx += ' of total';
+ if(hasMultiplePercents) tx += ' of total';
text.push(tx);
}
}
diff --git a/src/traces/pie/plot.js b/src/traces/pie/plot.js
index d31ad0a7c32..97800b4604d 100644
--- a/src/traces/pie/plot.js
+++ b/src/traces/pie/plot.js
@@ -1229,24 +1229,22 @@ function formatSliceLabel(gd, pt, cd0) {
var textinfo = trace.textinfo;
if (!texttemplate && textinfo && textinfo !== 'none') {
var parts = textinfo.split('+');
- var hasFlag = function (flag) {
- return parts.indexOf(flag) !== -1;
- };
- var hasLabel = hasFlag('label');
- var hasText = hasFlag('text');
- var hasValue = hasFlag('value');
- var hasPercent = hasFlag('percent');
-
var separators = fullLayout.separators;
- var text;
-
- text = hasLabel ? [pt.label] : [];
- if (hasText) {
- var tx = helpers.getFirstFilled(trace.text, pt.pts);
- if (isValidTextValue(tx)) text.push(tx);
+ var text = [];
+ var tx;
+ for(var i in parts) {
+ var part = parts[i];
+ if(part === 'label') {
+ text.push(pt.label);
+ } else if(part === 'text') {
+ tx = helpers.getFirstFilled(trace.text, pt.pts);
+ if(isValidTextValue(tx)) text.push(tx);
+ } else if(part === 'value') {
+ text.push(helpers.formatPieValue(pt.v, separators));
+ } else if(part === 'percent') {
+ text.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators));
+ }
}
- if (hasValue) text.push(helpers.formatPieValue(pt.v, separators));
- if (hasPercent) text.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators));
pt.text = text.join('
');
}
diff --git a/src/traces/sunburst/plot.js b/src/traces/sunburst/plot.js
index 3708e2b8136..377bd4c02e2 100644
--- a/src/traces/sunburst/plot.js
+++ b/src/traces/sunburst/plot.js
@@ -544,58 +544,39 @@ exports.formatSliceLabel = function (pt, entry, trace, cd, fullLayout) {
if (!texttemplate) {
var parts = textinfo.split('+');
- var hasFlag = function (flag) {
- return parts.indexOf(flag) !== -1;
- };
var thisText = [];
var tx;
- if (hasFlag('label') && cdi.label) {
- thisText.push(cdi.label);
- }
-
- if (cdi.hasOwnProperty('v') && hasFlag('value')) {
- thisText.push(helpers.formatValue(cdi.v, separators));
+ var nPercent = 0;
+ for(var p = 0; p < parts.length; p++) {
+ var f = parts[p];
+ if(f === 'percent parent' || f === 'percent entry' || f === 'percent root') nPercent++;
}
-
- if (!isRoot) {
- if (hasFlag('current path')) {
+ var hasMultiplePercents = nPercent > 1;
+ for(var i in parts) {
+ var part = parts[i];
+ if(part === 'label' && cdi.label) {
+ thisText.push(cdi.label);
+ } else if(part === 'value' && cdi.hasOwnProperty('v')) {
+ thisText.push(helpers.formatValue(cdi.v, separators));
+ } else if(part === 'text') {
+ tx = Lib.castOption(trace, cdi.i, 'text');
+ if(Lib.isValidTextValue(tx)) thisText.push(tx);
+ } else if(!isRoot && part === 'current path') {
thisText.push(helpers.getPath(pt.data));
+ } else if(!isRoot && part === 'percent parent') {
+ tx = helpers.formatPercent(val / helpers.getValue(parent), separators);
+ if(hasMultiplePercents) tx += ' of parent';
+ thisText.push(tx);
+ } else if(!isRoot && part === 'percent entry') {
+ tx = helpers.formatPercent(val / helpers.getValue(entry), separators);
+ if(hasMultiplePercents) tx += ' of entry';
+ thisText.push(tx);
+ } else if(!isRoot && part === 'percent root') {
+ tx = helpers.formatPercent(val / helpers.getValue(hierarchy), separators);
+ if(hasMultiplePercents) tx += ' of root';
+ thisText.push(tx);
}
-
- var nPercent = 0;
- if (hasFlag('percent parent')) nPercent++;
- if (hasFlag('percent entry')) nPercent++;
- if (hasFlag('percent root')) nPercent++;
- var hasMultiplePercents = nPercent > 1;
-
- if (nPercent) {
- var percent;
- var addPercent = function (key) {
- tx = helpers.formatPercent(percent, separators);
-
- if (hasMultiplePercents) tx += ' of ' + key;
- thisText.push(tx);
- };
-
- if (hasFlag('percent parent') && !isRoot) {
- percent = val / helpers.getValue(parent);
- addPercent('parent');
- }
- if (hasFlag('percent entry')) {
- percent = val / helpers.getValue(entry);
- addPercent('entry');
- }
- if (hasFlag('percent root')) {
- percent = val / helpers.getValue(hierarchy);
- addPercent('root');
- }
- }
- }
-
- if (hasFlag('text')) {
- tx = Lib.castOption(trace, cdi.i, 'text');
- if (Lib.isValidTextValue(tx)) thisText.push(tx);
}
return thisText.join('
');
diff --git a/test/image/baselines/display-text_zero-number.png b/test/image/baselines/display-text_zero-number.png
index 508ca937acd..98a6c0e4b54 100644
Binary files a/test/image/baselines/display-text_zero-number.png and b/test/image/baselines/display-text_zero-number.png differ
diff --git a/test/image/baselines/funnelarea_with_other_traces.png b/test/image/baselines/funnelarea_with_other_traces.png
index 5dd61a8c47e..5c80f49151d 100644
Binary files a/test/image/baselines/funnelarea_with_other_traces.png and b/test/image/baselines/funnelarea_with_other_traces.png differ
diff --git a/test/image/baselines/icicle_textposition.png b/test/image/baselines/icicle_textposition.png
index 1c1fbfc12a8..5adf6f61194 100644
Binary files a/test/image/baselines/icicle_textposition.png and b/test/image/baselines/icicle_textposition.png differ
diff --git a/test/image/baselines/icicle_with-without_values.png b/test/image/baselines/icicle_with-without_values.png
index 1dca4bcfad0..65d621f79e4 100644
Binary files a/test/image/baselines/icicle_with-without_values.png and b/test/image/baselines/icicle_with-without_values.png differ
diff --git a/test/image/baselines/sunburst_with-without_values.png b/test/image/baselines/sunburst_with-without_values.png
index 6cfc8dd3e45..d6dca921c36 100644
Binary files a/test/image/baselines/sunburst_with-without_values.png and b/test/image/baselines/sunburst_with-without_values.png differ
diff --git a/test/image/baselines/treemap_sunburst_marker_colors.png b/test/image/baselines/treemap_sunburst_marker_colors.png
index 209427c1b2a..d57b8e15f6e 100644
Binary files a/test/image/baselines/treemap_sunburst_marker_colors.png and b/test/image/baselines/treemap_sunburst_marker_colors.png differ
diff --git a/test/image/baselines/treemap_textposition.png b/test/image/baselines/treemap_textposition.png
index 6959e66b90e..f571dcaec2a 100644
Binary files a/test/image/baselines/treemap_textposition.png and b/test/image/baselines/treemap_textposition.png differ
diff --git a/test/image/baselines/treemap_with-without_values.png b/test/image/baselines/treemap_with-without_values.png
index ad8a8f1e8d7..63e9c304855 100644
Binary files a/test/image/baselines/treemap_with-without_values.png and b/test/image/baselines/treemap_with-without_values.png differ
diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js
index 0506aba9da3..19f169651e5 100644
--- a/test/jasmine/tests/funnel_test.js
+++ b/test/jasmine/tests/funnel_test.js
@@ -1757,4 +1757,25 @@ describe('funnel uniformtext', function() {
}))
.then(done, done.fail);
});
+
+ it('should respect textinfo token order', function(done) {
+ Plotly.newPlot(gd, [{
+ type: 'funnel',
+ y: ['Awareness', 'Interest', 'Action'],
+ x: [1000, 700, 400],
+ textinfo: 'percent initial+value'
+ }], {})
+ .then(function() {
+ var textEls = gd.querySelectorAll('text.bartext');
+ var textContent = Array.from(textEls).map(function(el) {
+ return el.textContent;
+ });
+ expect(textContent.length).toBe(3);
+ expect(textContent[0]).toBe('100%1000');
+ expect(textContent[1]).toBe('70%700');
+ expect(textContent[2]).toBe('40%400');
+ })
+ .then(done, done.fail);
+ });
+
});
diff --git a/test/jasmine/tests/pie_test.js b/test/jasmine/tests/pie_test.js
index 5aad071dc2e..f316f9dff76 100644
--- a/test/jasmine/tests/pie_test.js
+++ b/test/jasmine/tests/pie_test.js
@@ -909,6 +909,27 @@ describe('Pie traces', function() {
}))
.then(done, done.fail);
});
+
+ it('should respect textinfo token order', function(done) {
+ Plotly.newPlot(gd, [{
+ type: 'pie',
+ labels: ['A', 'B', 'C'],
+ values: [10, 20, 70],
+ textinfo: 'percent+label',
+ sort: false
+ }], {})
+ .then(function() {
+ var textEls = gd.querySelectorAll('text.slicetext');
+ var textContent = Array.from(textEls).map(function(el) {
+ return el.textContent;
+ });
+ expect(textContent.length).toBe(3);
+ expect(textContent[0]).toBe('10%A');
+ expect(textContent[1]).toBe('20%B');
+ expect(textContent[2]).toBe('70%C');
+ })
+ .then(done, done.fail);
+ });
});
describe('Pie texttemplate:', function() {
diff --git a/test/jasmine/tests/sunburst_test.js b/test/jasmine/tests/sunburst_test.js
index 09ae8bf4ad6..b0e6067aa63 100644
--- a/test/jasmine/tests/sunburst_test.js
+++ b/test/jasmine/tests/sunburst_test.js
@@ -1199,6 +1199,28 @@ describe('Test sunburst restyle:', function () {
.then(_assert('back to dflt', ['Root\nnode0', 'B\nnode2', 'A\nnode1', 'b\nnode3']))
.then(done, done.fail);
});
+
+ it('should respect textinfo token order', function(done) {
+ Plotly.newPlot(gd, [{
+ type: 'sunburst',
+ labels: ['Root', 'A', 'B'],
+ parents: ['', 'Root', 'Root'],
+ values: [0, 10, 20],
+ textinfo: 'percent root+value+label'
+ }], {})
+ .then(function() {
+ var layer = d3Select(gd).select('.sunburstlayer');
+ var textContent = [];
+ layer.selectAll('text.slicetext').each(function() {
+ textContent.push(this.textContent);
+ });
+ expect(textContent.length).toBe(3);
+ expect(textContent[0]).toBe('0Root');
+ expect(textContent[1]).toBe('33%20B');
+ expect(textContent[2]).toBe('17%10A');
+ })
+ .then(done, done.fail);
+ });
});
describe('Test sunburst tweening:', function () {
diff --git a/test/jasmine/tests/treemap_test.js b/test/jasmine/tests/treemap_test.js
index bf427dc4eae..96578d60ec5 100644
--- a/test/jasmine/tests/treemap_test.js
+++ b/test/jasmine/tests/treemap_test.js
@@ -1431,7 +1431,7 @@ describe('Test treemap restyle:', function () {
}
Plotly.newPlot(gd, mock)
- .then(_assert('base', ['Root', 'B', 'A\nnode1', 'b\nnode3']))
+ .then(_assert('base', ['Root', 'B', 'node1\nA', 'node3\nb']))
.then(function () {
spyOn(Plots, 'doCalcdata').and.callThrough();
})
@@ -1442,9 +1442,9 @@ describe('Test treemap restyle:', function () {
.then(_restyle({ textinfo: 'none' }))
.then(_assert('no textinfo', ['Root', 'B', ' ', ' '])) // use one space character instead of a blank string to avoid jumps during transition
.then(_restyle({ textinfo: 'label+text+value' }))
- .then(_assert('show everything', ['Root', 'B', 'A\n1\nnode1', 'b\n3\nnode3']))
+ .then(_assert('show everything', ['Root', 'B', 'A\nnode1\n1', 'b\nnode3\n3']))
.then(_restyle({ textinfo: null }))
- .then(_assert('back to dflt', ['Root', 'B', 'A\nnode1', 'b\nnode3']))
+ .then(_assert('back to dflt', ['Root', 'B', 'node1\nA', 'node3\nb']))
.then(done, done.fail);
});