Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/traces/sankey/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ var attrs = (module.exports = overrideAll(
dflt: 'justify',
description: 'Sets the alignment method used to position the nodes along the horizontal axis.'
},
sort: {
valType: 'enumerated',
values: ['auto', 'input'],
dflt: 'auto',
description: [
'If the value is `auto` (the default), the vertical order of nodes will be determined automatically',
'by the layout.',
'If the value is `input`, the vertical order is kept the same as the order in the input node array'
].join(' ')
},
description: 'The nodes of the Sankey plot.'
},

Expand Down
1 change: 1 addition & 0 deletions src/traces/sankey/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault);
coerceNode('hovertemplate');
coerceNode('align');
coerceNode('sort');

var colors = layout.colorway;

Expand Down
10 changes: 10 additions & 0 deletions src/traces/sankey/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function sankeyModel(layout, d, traceIndex) {
right: d3Sankey.sankeyRight,
center: d3Sankey.sankeyCenter
}[trace.node.align];
var input_sort = trace.node.sort === 'input';

var width = layout.width * (domain.x[1] - domain.x[0]);
var height = layout.height * (domain.y[1] - domain.y[0]);
Expand All @@ -48,6 +49,10 @@ function sankeyModel(layout, d, traceIndex) {
var links = calcData._links;
var circular = calcData.circular;

if(circular && input_sort) {
Lib.error('Circular Sankey diagrams do not support the "input" node.sort mode; falling back to the default sort.');
}

// Select Sankey generator
var sankey;
if(circular) {
Expand All @@ -70,6 +75,11 @@ function sankeyModel(layout, d, traceIndex) {
.nodes(nodes)
.links(links);

// d3-sankey-circular does not support the nodeSort method
if(!circular) {
sankey.nodeSort(input_sort ? null : undefined);
}

var graph = sankey();

if(sankey.nodePadding() < nodePad) {
Expand Down
Binary file added test/image/baselines/sankey_auto_sort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/sankey_input_sort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions test/image/mocks/sankey_auto_sort.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": [
{
"type": "sankey",
"node": {
"label": ["0", "1", "2", "3", "4", "5"],
"align": "center",
"sort": "auto"
},
"link": {
"source": [0, 0, 0, 0, 1, 4],
"target": [1, 2, 3, 4, 5, 5],
"value": [1, 2, 1, 1, 1, 1]
}
}
],
"layout": {
"title": { "text": "Sankey with automatic vertical node ordering" },
"width": 800,
"height": 800
}
}
22 changes: 22 additions & 0 deletions test/image/mocks/sankey_input_sort.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": [
{
"type": "sankey",
"node": {
"label": ["0", "1", "2", "3", "4", "5"],
"align": "center",
"sort": "input"
},
"link": {
"source": [0, 0, 0, 0, 1, 4],
"target": [1, 2, 3, 4, 5, 5],
"value": [1, 2, 1, 1, 1, 1]
}
}
],
"layout": {
"title": { "text": "Sankey with fixed vertical node ordering" },
"width": 800,
"height": 800
}
}
21 changes: 21 additions & 0 deletions test/jasmine/tests/sankey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,27 @@ describe('sankey tests', function () {
.then(done, done.fail);
});

it('falls back to the default sort for circular Sankey with node.sort set', function (done) {
var errors = [];
spyOn(Lib, 'error').and.callFake(function (msg) {
errors.push(msg);
});

var mockCircularCopy = Lib.extendDeep({}, mockCircular);
mockCircularCopy.data[0].node.sort = 'input';

Plotly.newPlot(gd, mockCircularCopy)
.then(function () {
// The plot renders successfully
expect(gd.calcdata[0][0].circular).toBe(true);
expect(d3SelectAll('.sankey .node-rect').size()).toBeGreaterThan(0);

// An error is logged about the fallback
expect(errors.length).toBe(1);
})
.then(done, done.fail);
});

it('can create groups, restyle groups and properly update DOM', function (done) {
var mockCircularCopy = Lib.extendDeep({}, mockCircular);
var firstGroup = [
Expand Down
10 changes: 10 additions & 0 deletions test/plot-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50746,6 +50746,16 @@
"valType": "number"
},
"role": "object",
"sort": {
"description": "If the value is `auto` (the default), the vertical order of nodes will be determined automatically by the layout. If the value is `input`, the vertical order is kept the same as the order in the input node array",
"dflt": "auto",
"editType": "calc",
"valType": "enumerated",
"values": [
"auto",
"input"
]
},
"thickness": {
"arrayOk": false,
"description": "Sets the thickness (in px) of the `nodes`.",
Expand Down
Loading