Skip to content

Commit

Permalink
Merge pull request #3150 from plotly/sankey-trace-hover
Browse files Browse the repository at this point in the history
sankey hover improvements
  • Loading branch information
antoinerg authored Oct 25, 2018
2 parents d5ebb50 + 6ab718d commit c3a0118
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 53 deletions.
19 changes: 15 additions & 4 deletions src/traces/sankey/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,27 @@
'use strict';

var fontAttrs = require('../../plots/font_attributes');
var plotAttrs = require('../../plots/attributes');
var colorAttrs = require('../../components/color/attributes');
var fxAttrs = require('../../components/fx/attributes');
var domainAttrs = require('../../plots/domain').attributes;

var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

var attrs = module.exports = overrideAll({
module.exports = overrideAll({
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
flags: [],
arrayOk: false,
description: [
'Determines which trace information appear on hover.',
'If `none` or `skip` are set, no information is displayed upon hovering.',
'But, if `none` is set, click and hover events are still fired.',
'Note that this attribute is superseded by `node.hoverinfo` and `node.hoverinfo`',
'for nodes and links respectively.'
].join(' ')
}),
hoverlabel: fxAttrs.hoverlabel,
domain: domainAttrs({name: 'sankey', trace: true}),

orientation: {
Expand Down Expand Up @@ -205,6 +219,3 @@ var attrs = module.exports = overrideAll({
description: 'The links of the Sankey plot.'
}
}, 'calc', 'nested');
// hide unsupported top-level properties from plot-schema
attrs.hoverinfo = undefined;
attrs.hoverlabel = undefined;
14 changes: 7 additions & 7 deletions src/traces/sankey/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
}

var hoverlabelDefault = Lib.extendDeep(layout.hoverlabel, traceIn.hoverlabel);

// node attributes
var nodeIn = traceIn.node, nodeOut = Template.newContainer(traceOut, 'node');
function coerceNode(attr, dflt) {
Expand All @@ -31,8 +33,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerceNode('thickness');
coerceNode('line.color');
coerceNode('line.width');
coerceNode('hoverinfo');
handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, layout.hoverlabel);
coerceNode('hoverinfo', traceIn.hoverinfo);
handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault);

var colors = layout.colorway;

Expand All @@ -53,16 +55,14 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerceLink('value');
coerceLink('line.color');
coerceLink('line.width');
coerceLink('hoverinfo');
handleHoverLabelDefaults(linkIn, linkOut, coerceLink, layout.hoverlabel);
coerceLink('hoverinfo', traceIn.hoverinfo);
handleHoverLabelDefaults(linkIn, linkOut, coerceLink, hoverlabelDefault);

var defaultLinkColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ?
'rgba(255, 255, 255, 0.6)' :
'rgba(0, 0, 0, 0.2)';

coerceLink('color', linkOut.value.map(function() {
return defaultLinkColor;
}));
coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length));

handleDomainDefaults(traceOut, layout, coerce);

Expand Down
136 changes: 94 additions & 42 deletions test/jasmine/tests/sankey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,9 @@ describe('sankey tests', function() {
['source: Solid', 'target: Industry', '46TWh'],
['rgb(0, 0, 96)', 'rgb(255, 255, 255)', 13, 'Arial', 'rgb(255, 255, 255)']
);

})
// Test layout.hoverlabel
.then(function() {
return Plotly.relayout(gd, 'hoverlabel.font.family', 'Roboto');
})
.then(function() {
Expand All @@ -434,16 +436,45 @@ describe('sankey tests', function() {
['source: Solid', 'target: Industry', '46TWh'],
['rgb(0, 0, 96)', 'rgb(255, 255, 255)', 13, 'Roboto', 'rgb(255, 255, 255)']
);
})
// Test trace-level hoverlabel
.then(function() {
return Plotly.restyle(gd, {
'hoverlabel.bgcolor': 'blue',
'hoverlabel.bordercolor': 'red',
'hoverlabel.font.size': 22,
'hoverlabel.font.color': 'magenta'
});
})
.then(function() {
_hover(404, 302);

assertLabel(
['Solid', 'incoming flow count: 4', 'outgoing flow count: 3', '447TWh'],
['rgb(0, 0, 255)', 'rgb(255, 0, 0)', 22, 'Roboto', 'rgb(255, 0, 255)']
);
})
.then(function() {
_hover(450, 300);

assertLabel(
['source: Solid', 'target: Industry', '46TWh'],
['rgb(0, 0, 255)', 'rgb(255, 0, 0)', 22, 'Roboto', 'rgb(255, 0, 255)']
);
})
// Test (node|link).hoverlabel
.then(function() {
return Plotly.restyle(gd, {
'node.hoverlabel.bgcolor': 'red',
'node.hoverlabel.bordercolor': 'blue',
'node.hoverlabel.font.size': 20,
'node.hoverlabel.font.color': 'black',
'node.hoverlabel.font.family': 'Roboto',
'link.hoverlabel.bgcolor': 'yellow',
'link.hoverlabel.bordercolor': 'magenta',
'link.hoverlabel.font.size': 18,
'link.hoverlabel.font.color': 'green'
'link.hoverlabel.font.color': 'green',
'link.hoverlabel.font.family': 'Roboto'
});
})
.then(function() {
Expand Down Expand Up @@ -556,49 +587,59 @@ describe('sankey tests', function() {
.then(done);
});

it('should not show node labels if node.hoverinfo is none', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);
['skip', 'none'].forEach(function(hoverinfoFlag) {
it('should not show node labels if node.hoverinfo is ' + hoverinfoFlag, function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);

Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'node.hoverinfo', 'none');
})
.then(function() {
_hover(node[0], node[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'node.hoverinfo', hoverinfoFlag);
})
.then(function() {
_hover(node[0], node[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
});
});

it('should not show link labels if link.hoverinfo is none', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);
['skip', 'none'].forEach(function(hoverinfoFlag) {
it('should not show link labels if link.hoverinfo is ' + hoverinfoFlag, function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);

Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'link.hoverinfo', 'none');
})
.then(function() {
_hover(link[0], link[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'link.hoverinfo', hoverinfoFlag);
})
.then(function() {
_hover(link[0], link[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
});
});

it('should not show node labels if node.hoverinfo is skip', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);
['skip', 'none'].forEach(function(hoverinfoFlag) {
it('should not show labels if trace hoverinfo is ' + hoverinfoFlag + ' and (node|link).hoverinfo is undefined', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);

Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'node.hoverinfo', 'skip');
})
.then(function() {
_hover(node[0], node[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
Plotly.plot(gd, mockCopy).then(function() {
return Plotly.restyle(gd, 'hoverinfo', hoverinfoFlag);
})
.then(function() {
_hover(node[0], node[1]);
assertNoLabel();
})
.then(function() {
_hover(link[0], link[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
});
});

it('should not show link labels if link.hoverinfo is skip', function(done) {
Expand Down Expand Up @@ -748,7 +789,7 @@ describe('sankey tests', function() {
};
}

it('should not output hover/unhover event data when hovermoder is false', function(done) {
it('should not output hover/unhover event data when hovermode is false', function(done) {
var fig = Lib.extendDeep({}, mock);

Plotly.plot(gd, fig)
Expand All @@ -759,17 +800,28 @@ describe('sankey tests', function() {
.then(done);
});

it('should not output hover/unhover event data when hoverinfo is skip', function(done) {
it('should not output hover/unhover event data when trace hoverinfo is skip', function(done) {
var fig = Lib.extendDeep({}, mock);

Plotly.plot(gd, fig)
.then(function() { return Plotly.restyle(gd, 'link.hoverinfo', 'skip'); })
.then(function() { return Plotly.restyle(gd, 'hoverinfo', 'skip'); })
.then(assertNoHoverEvents('link'))
.then(function() { return Plotly.restyle(gd, 'node.hoverinfo', 'skip'); })
.then(assertNoHoverEvents('node'))
.catch(failTest)
.then(done);
});

['node', 'link'].forEach(function(obj) {
it('should not output hover/unhover event data when ' + obj + '.hoverinfo is skip', function(done) {
var fig = Lib.extendDeep({}, mock);

Plotly.plot(gd, fig)
.then(function() { return Plotly.restyle(gd, obj + '.hoverinfo', 'skip'); })
.then(assertNoHoverEvents(obj))
.catch(failTest)
.then(done);
});
});
});

it('emits a warning if node.pad is too large', function(done) {
Expand Down

0 comments on commit c3a0118

Please sign in to comment.