Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
3 changes: 2 additions & 1 deletion src/plot_api/edit_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

var Lib = require('../lib');
var extendFlat = Lib.extendFlat;
var extendDeepAll = Lib.extendDeepAll;
var isPlainObject = Lib.isPlainObject;

var traceOpts = {
Expand Down Expand Up @@ -115,7 +116,7 @@ function falseObj(keys) {
* @return {object} a new attributes object with `editType` modified as directed
*/
function overrideAll(attrs, editTypeOverride, overrideContainers) {
var out = extendFlat({}, attrs);
var out = extendDeepAll({}, attrs);
for(var key in out) {
var attr = out[key];
if(isPlainObject(attr)) {
Expand Down
13 changes: 7 additions & 6 deletions src/traces/sankey/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

module.exports = overrideAll({
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
flags: ['label', 'text', 'value', 'percent', 'name'],
}),
hoverlabel: fxAttrs.hoverlabel, // needs editType override

domain: domainAttrs({name: 'sankey', trace: true}),

orientation: {
Expand Down Expand Up @@ -127,6 +122,8 @@ module.exports = overrideAll({
role: 'style',
description: 'Sets the thickness (in px) of the `nodes`.'
},
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {flags: []}),
hoverlabel: fxAttrs.hoverlabel, // needs editType override,
description: 'The nodes of the Sankey plot.'
},

Expand Down Expand Up @@ -185,6 +182,10 @@ module.exports = overrideAll({
role: 'info',
description: 'A numeric value representing the flow volume value.'
},
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {flags: []}),
hoverlabel: fxAttrs.hoverlabel, // needs editType override,
description: 'The links of the Sankey plot.'
}
},
hoverinfo: undefined,
hoverlabel: undefined
}, 'calc', 'nested');
11 changes: 11 additions & 0 deletions src/traces/sankey/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var attributes = require('./attributes');
var Color = require('../../components/color');
var tinycolor = require('tinycolor2');
var handleDomainDefaults = require('../../plots/domain').defaults;
var Registry = require('../../registry');

module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
Expand All @@ -24,6 +25,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('node.thickness');
coerce('node.line.color');
coerce('node.line.width');
coerce('node.hoverinfo');
Registry.getComponentMethod(
'fx',
'supplyDefaults'
)(traceIn.node, traceOut.node, defaultColor, layout);

var colors = layout.colorway;

Expand All @@ -39,6 +45,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('link.value');
coerce('link.line.color');
coerce('link.line.width');
coerce('link.hoverinfo');
Registry.getComponentMethod(
'fx',
'supplyDefaults'
)(traceIn.link, traceOut.link, defaultColor, layout);

coerce('link.color', traceOut.link.value.map(function() {
return tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ?
Expand Down
68 changes: 40 additions & 28 deletions src/traces/sankey/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,13 @@ module.exports = function plot(gd, calcData) {
var linkHover = function(element, d, sankey) {
if(gd._fullLayout.hovermode === false) return;
d3.select(element).call(linkHoveredStyle.bind(0, d, sankey, true));
gd.emit('plotly_hover', {
event: d3.event,
points: [d.link]
});
if(d.link.trace.link.hoverinfo !== 'skip') {
gd.emit('plotly_hover', {
event: d3.event,
points: [d.link]
});
}

};

var sourceLabel = _(gd, 'source:') + ' ';
Expand All @@ -145,7 +148,8 @@ module.exports = function plot(gd, calcData) {

var linkHoverFollow = function(element, d) {
if(gd._fullLayout.hovermode === false) return;
var trace = d.link.trace;
var obj = d.link.trace.link;
if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return;
var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect();
var boundingBox = element.getBoundingClientRect();
var hoverCenterX = boundingBox.left + boundingBox.width / 2;
Expand All @@ -160,11 +164,11 @@ module.exports = function plot(gd, calcData) {
sourceLabel + d.link.source.label,
targetLabel + d.link.target.label
].filter(renderableValuePresent).join('<br>'),
color: castHoverOption(trace, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1),
borderColor: castHoverOption(trace, 'bordercolor'),
fontFamily: castHoverOption(trace, 'font.family'),
fontSize: castHoverOption(trace, 'font.size'),
fontColor: castHoverOption(trace, 'font.color'),
color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1),
borderColor: castHoverOption(obj, 'bordercolor'),
fontFamily: castHoverOption(obj, 'font.family'),
fontSize: castHoverOption(obj, 'font.size'),
fontColor: castHoverOption(obj, 'font.color'),
idealAlign: d3.event.x < hoverCenterX ? 'right' : 'left'
}, {
container: fullLayout._hoverlayer.node(),
Expand All @@ -179,10 +183,12 @@ module.exports = function plot(gd, calcData) {
var linkUnhover = function(element, d, sankey) {
if(gd._fullLayout.hovermode === false) return;
d3.select(element).call(linkNonHoveredStyle.bind(0, d, sankey, true));
gd.emit('plotly_unhover', {
event: d3.event,
points: [d.link]
});
if(d.link.trace.link.hoverinfo !== 'skip') {
gd.emit('plotly_unhover', {
event: d3.event,
points: [d.link]
});
}

Fx.loneUnhover(fullLayout._hoverlayer.node());
};
Expand All @@ -198,15 +204,19 @@ module.exports = function plot(gd, calcData) {
var nodeHover = function(element, d, sankey) {
if(gd._fullLayout.hovermode === false) return;
d3.select(element).call(nodeHoveredStyle, d, sankey);
gd.emit('plotly_hover', {
event: d3.event,
points: [d.node]
});
if(d.node.trace.node.hoverinfo !== 'skip') {
gd.emit('plotly_hover', {
event: d3.event,
points: [d.node]
});
}
};

var nodeHoverFollow = function(element, d) {
if(gd._fullLayout.hovermode === false) return;
var trace = d.node.trace;

var obj = d.node.trace.node;
if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return;
var nodeRect = d3.select(element).select('.' + cn.nodeRect);
var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect();
var boundingBox = nodeRect.node().getBoundingClientRect();
Expand All @@ -224,11 +234,11 @@ module.exports = function plot(gd, calcData) {
incomingLabel + d.node.targetLinks.length,
outgoingLabel + d.node.sourceLinks.length
].filter(renderableValuePresent).join('<br>'),
color: castHoverOption(trace, 'bgcolor') || d.tinyColorHue,
borderColor: castHoverOption(trace, 'bordercolor'),
fontFamily: castHoverOption(trace, 'font.family'),
fontSize: castHoverOption(trace, 'font.size'),
fontColor: castHoverOption(trace, 'font.color'),
color: castHoverOption(obj, 'bgcolor') || d.tinyColorHue,
borderColor: castHoverOption(obj, 'bordercolor'),
fontFamily: castHoverOption(obj, 'font.family'),
fontSize: castHoverOption(obj, 'font.size'),
fontColor: castHoverOption(obj, 'font.color'),
idealAlign: 'left'
}, {
container: fullLayout._hoverlayer.node(),
Expand All @@ -243,10 +253,12 @@ module.exports = function plot(gd, calcData) {
var nodeUnhover = function(element, d, sankey) {
if(gd._fullLayout.hovermode === false) return;
d3.select(element).call(nodeNonHoveredStyle, d, sankey);
gd.emit('plotly_unhover', {
event: d3.event,
points: [d.node]
});
if(d.node.trace.node.hoverinfo !== 'skip') {
gd.emit('plotly_unhover', {
event: d3.event,
points: [d.node]
});
}

Fx.loneUnhover(fullLayout._hoverlayer.node());
};
Expand Down
111 changes: 88 additions & 23 deletions test/jasmine/tests/sankey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ describe('sankey tests', function() {
Lib.clearThrottle();
}

var node = [404, 302],
link = [450, 300];

it('should show the correct hover labels', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);
Expand Down Expand Up @@ -433,10 +436,14 @@ describe('sankey tests', function() {
);

return Plotly.restyle(gd, {
'hoverlabel.bgcolor': 'red',
'hoverlabel.bordercolor': 'blue',
'hoverlabel.font.size': 20,
'hoverlabel.font.color': 'black'
'node.hoverlabel.bgcolor': 'red',
'node.hoverlabel.bordercolor': 'blue',
'node.hoverlabel.font.size': 20,
'node.hoverlabel.font.color': 'black',
'link.hoverlabel.bgcolor': 'red',
'link.hoverlabel.bordercolor': 'blue',
'link.hoverlabel.font.size': 20,
'link.hoverlabel.font.color': 'black'
});
})
.then(function() {
Expand All @@ -459,7 +466,7 @@ describe('sankey tests', function() {
.then(done);
});

it('should show correct hover labels even if there is no link.label supplied', function(done) {
it('should show the correct hover labels even if there is no link.label supplied', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);
delete mockCopy.data[0].link.label;
Expand All @@ -477,16 +484,64 @@ describe('sankey tests', function() {
.then(done);
});

it('should not show labels if hovermode is false', function(done) {
it('should not show any labels if hovermode is false', function(done) {
var gd = createGraphDiv();
var mockCopy = Lib.extendDeep({}, mock);

Plotly.plot(gd, mockCopy).then(function() {
return Plotly.relayout(gd, 'hovermode', false);
})
.then(function() {
_hover(404, 302);
_hover(node[0], node[1]);
assertNoLabel();
})
.then(function() {
_hover(link[0], link[1]);
assertNoLabel();
})
.catch(failTest)
.then(done);
});

it('should not show node labels if node.hoverinfo is none', 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);
});

it('should not show link labels if link.hoverinfo is none', 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);
});

it('should not show node labels if node.hoverinfo is skip', 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)
Expand Down Expand Up @@ -574,6 +629,7 @@ describe('sankey tests', function() {
var fig = Lib.extendDeep({}, mock);

Plotly.plot(gd, fig)
.then(function() { return Plotly.restyle(gd, 'hoverinfo', 'none'); })
.then(function() { return _hover('node'); })
.then(function(d) {
_assert(d, {
Expand Down Expand Up @@ -610,27 +666,36 @@ describe('sankey tests', function() {
.then(done);
});

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

Plotly.plot(gd, fig)
.then(function() { return Plotly.relayout(gd, 'hovermode', false); })
.then(function() { return _hover('node'); })
.then(failTest).catch(function(err) {
expect(err).toBe('plotly_hover did not get called!');
})
.then(function() { return _unhover('node'); })
.then(failTest).catch(function(err) {
expect(err).toBe('plotly_unhover did not get called!');
})
.then(function() { return _hover('link'); })
function assertNoHoverEvents(type) {
return Promise.resolve()
.then(function() { return _hover(type); })
.then(failTest).catch(function(err) {
expect(err).toBe('plotly_hover did not get called!');
})
.then(function() { return _unhover('link'); })
.then(function() { return _unhover(type); })
.then(failTest).catch(function(err) {
expect(err).toBe('plotly_unhover did not get called!');
})
});
}

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

Plotly.plot(gd, fig)
.then(function() { return Plotly.relayout(gd, 'hovermode', false); })
.then(function() { return assertNoHoverEvents('node');})
.then(function() { return assertNoHoverEvents('link');})
.catch(failTest)
.then(done);
});

it('should not output hover/unhover event data when 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 assertNoHoverEvents('link');})
.catch(failTest)
.then(done);
});
});
Expand Down