Skip to content

Commit 95bfea1

Browse files
authored
Merge pull request #7959 from CAOShurong/codex/fix-parcats-numeric-bundle-sort
Fix numeric color sorting in parcats bundles
2 parents 38a48b7 + 49b904a commit 95bfea1

3 files changed

Lines changed: 79 additions & 9 deletions

File tree

draftlogs/7959_fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix numeric color sorting for bundled parallel-categories (parcats) paths [[#7959](https://github.com/plotly/plotly.js/pull/7959)], with thanks to @CAOShurong for the contribution!

src/traces/parcats/parcats.js

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,33 @@ function compareRawColor(a, b) {
370370
}
371371
}
372372

373+
/**
374+
* Compare two sort arrays element by element in ascending order.
375+
* Values that do not order against each other, for example NaN, sort last.
376+
* The shorter array sorts first when one array is a prefix of the other.
377+
*
378+
* @param {Array} a
379+
* @param {Array} b
380+
*/
381+
function compareArrays(a, b) {
382+
for(var i = 0; i < Math.min(a.length, b.length); i++) {
383+
var valA = a[i];
384+
var valB = b[i];
385+
386+
if(valA < valB) return -1;
387+
if(valA > valB) return 1;
388+
// Handle values that do not order against each other (NaN, undefined, etc.)
389+
if(valA !== valB) {
390+
// Sort these after every orderable value.
391+
var badA = isNaN(valA);
392+
var badB = isNaN(valB);
393+
if(badA !== badB) return badA ? 1 : -1;
394+
}
395+
}
396+
397+
return a.length - b.length;
398+
}
399+
373400
/**
374401
* Handle path mouseover
375402
* @param {PathViewModel} d
@@ -1734,15 +1761,8 @@ function updatePathViewModels(parcatsViewModel) {
17341761
sortArray2.unshift(v2.rawColor);
17351762
}
17361763

1737-
// colors equal, sort by display categories
1738-
if(sortArray1 < sortArray2) {
1739-
return -1;
1740-
}
1741-
if(sortArray1 > sortArray2) {
1742-
return 1;
1743-
}
1744-
1745-
return 0;
1764+
// Sort by color, then display categories
1765+
return compareArrays(sortArray1, sortArray2);
17461766
});
17471767

17481768
// Create path models

test/jasmine/tests/parcats_test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,55 @@ describe('Basic parcats trace', function() {
284284
.then(done, done.fail);
285285
});
286286

287+
it('should sort bundled paths by numeric color values', function(done) {
288+
var trace = {
289+
type: 'parcats',
290+
dimensions: [
291+
{values: ['a', 'a', 'a', 'a']},
292+
{values: ['b', 'b', 'b', 'b']}
293+
],
294+
line: {color: [1, 10, 2, 20]},
295+
bundlecolors: true
296+
};
297+
298+
Plotly.newPlot(gd, [trace])
299+
.then(function() {
300+
var parcatsViewModel = d3Select('g.trace.parcats').datum();
301+
var pathColors = parcatsViewModel.paths.map(function(path) {
302+
return path.model.rawColor;
303+
});
304+
305+
expect(pathColors).toEqual([1, 2, 10, 20]);
306+
})
307+
.then(done, done.fail);
308+
});
309+
310+
it('should sort NaN color values after orderable values', function(done) {
311+
var trace = {
312+
type: 'parcats',
313+
dimensions: [
314+
{values: ['a', 'a', 'a', 'a']},
315+
{values: ['b', 'b', 'b', 'b']}
316+
],
317+
line: {color: [10, NaN, 2, NaN]},
318+
bundlecolors: true
319+
};
320+
321+
Plotly.newPlot(gd, [trace])
322+
.then(function() {
323+
var parcatsViewModel = d3Select('g.trace.parcats').datum();
324+
var pathColors = parcatsViewModel.paths.map(function(path) {
325+
return path.model.rawColor;
326+
});
327+
328+
// Orderable values sort first, NaN values sort last
329+
expect(pathColors.length).toBe(3)
330+
expect(pathColors.slice(0, 2)).toEqual([2, 10]);
331+
expect(isNaN(pathColors[2])).toBe(true);
332+
})
333+
.then(done, done.fail);
334+
});
335+
287336
it('should compute initial model views properly', function(done) {
288337
Plotly.newPlot(gd, basicMock)
289338
.then(function() {

0 commit comments

Comments
 (0)