diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js index 37653f9c3a8..f7dd1e6cccc 100644 --- a/src/traces/bar/plot.js +++ b/src/traces/bar/plot.js @@ -1101,56 +1101,60 @@ function calcTextinfo(cd, index, xa, ya) { var textinfo = trace.textinfo; var cdi = cd[index]; - var parts = textinfo.split('+'); + var parts = textinfo.split('+').map(function(p) { + return p.trim(); + }); + var text = []; var tx; - var hasFlag = function (flag) { + var hasFlag = function(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 delta, final, initial; + if(isWaterfall) { + delta = +cdi.rawS || cdi.s; + final = cdi.v; + initial = final - delta; } - 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)); + var nPercent = 0; + var hasMultiplePercents = false; + if(isFunnel) { + if(hasFlag('percent initial')) nPercent++; + if(hasFlag('percent previous')) nPercent++; + if(hasFlag('percent total')) nPercent++; + hasMultiplePercents = nPercent > 1; } - 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')) { + for(var i in parts) { + var part = parts[i]; + + if(part === 'label' && hasFlag('label')) { + text.push(formatLabel(cdi.p)); + } else if(part === 'text' && hasFlag('text')) { + tx = Lib.castOption(trace, cdi.i, 'text'); + if(tx === 0 || tx) text.push(tx); + } else if(isWaterfall && part === 'initial' && hasFlag('initial')) { + text.push(formatNumber(initial)); + } else if(isWaterfall && part === 'delta' && hasFlag('delta')) { + text.push(formatNumber(delta)); + } else if(isWaterfall && part === 'final' && hasFlag('final')) { + text.push(formatNumber(final)); + } else if(isFunnel && part === 'value' && hasFlag('value')) { + text.push(formatNumber(cdi.s)); + } else if(isFunnel && part === 'percent initial' && hasFlag('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' && hasFlag('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' && hasFlag('percent total')) { tx = Lib.formatPercent(cdi.sumR); - if (hasMultiplePercents) tx += ' of total'; + if(hasMultiplePercents) tx += ' of total'; text.push(tx); } } diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index 0506aba9da3..f4b770ea853 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -1757,4 +1757,41 @@ describe('funnel uniformtext', function() { })) .then(done, done.fail); }); + + it('should respect textinfo token order', function() { + var gd = createGraphDiv(); + + return 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'); + + expect(textEls.length).toBeGreaterThan(0); + + for(var i = 0; i < textEls.length; i++) { + var txt = textEls[i].textContent; + if(!txt || txt.length === 0) continue; + + var percentIndex = txt.indexOf('%'); + expect(percentIndex).toBeGreaterThan(-1); + + var firstNumberIndex = txt.search(/\d/); + expect(firstNumberIndex).toBeGreaterThan(-1); + + // percent sign must appear AFTER first digit (e.g. "70%") + // but BEFORE the value number that follows + expect(percentIndex).toBeGreaterThan(firstNumberIndex); + + // value number must exist AFTER percent + var afterPercent = txt.slice(percentIndex + 1); + expect(afterPercent.match(/\d+/)).not.toBeNull(); + } + }) + .then(destroyGraphDiv); + }); + });