-
-
Notifications
You must be signed in to change notification settings - Fork 2k
fix(funnel/waterfall): respect textinfo token order #7752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
4c418a0
c05bb22
4696313
4f5d538
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
|
Comment on lines
+1116
to
+1119
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see any reason to calculate these separately at the top; might as well just put each calculation inside its corresponding if/else case, I think that's clearer. |
||
| } | ||
|
|
||
| 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')) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need the |
||
| 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); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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(); | ||
| } | ||
|
Comment on lines
+1773
to
+1792
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Abineshabee Instead of this approach, let's just assert the exact text content we expect, I think that will be much clearer. i.e. something like var textContent = Array.from(textEls).map((el) => el.textContent);
expect(textContent).toBe([
"100%1000",
"70%700",
"40%400"
]); |
||
| }) | ||
| .then(destroyGraphDiv); | ||
| }); | ||
|
|
||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I double-checked, and we already validate flaglist items during the coerce step, so this
trim()is not needed.