Skip to content

Commit 880973a

Browse files
committed
sankey node and link each have their own hover attributes
1 parent 69c11fe commit 880973a

File tree

4 files changed

+78
-52
lines changed

4 files changed

+78
-52
lines changed

Diff for: src/traces/sankey/attributes.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ var extendFlat = require('../../lib/extend').extendFlat;
1818
var overrideAll = require('../../plot_api/edit_types').overrideAll;
1919

2020
module.exports = overrideAll({
21-
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
22-
flags: ['label', 'text', 'value', 'percent', 'name'],
23-
}),
24-
hoverlabel: fxAttrs.hoverlabel, // needs editType override
25-
2621
domain: domainAttrs({name: 'sankey', trace: true}),
2722

2823
orientation: {
@@ -127,6 +122,8 @@ module.exports = overrideAll({
127122
role: 'style',
128123
description: 'Sets the thickness (in px) of the `nodes`.'
129124
},
125+
hoverinfo: Object.assign(plotAttrs.hoverinfo, {flags: []}),
126+
hoverlabel: fxAttrs.hoverlabel, // needs editType override,
130127
description: 'The nodes of the Sankey plot.'
131128
},
132129

@@ -185,6 +182,8 @@ module.exports = overrideAll({
185182
role: 'info',
186183
description: 'A numeric value representing the flow volume value.'
187184
},
185+
hoverinfo: Object.assign(plotAttrs.hoverinfo, {flags: []}),
186+
hoverlabel: fxAttrs.hoverlabel, // needs editType override,
188187
description: 'The links of the Sankey plot.'
189188
}
190189
}, 'calc', 'nested');

Diff for: src/traces/sankey/defaults.js

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var attributes = require('./attributes');
1313
var Color = require('../../components/color');
1414
var tinycolor = require('tinycolor2');
1515
var handleDomainDefaults = require('../../plots/domain').defaults;
16+
var Registry = require('../../registry');
1617

1718
module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
1819
function coerce(attr, dflt) {
@@ -24,6 +25,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
2425
coerce('node.thickness');
2526
coerce('node.line.color');
2627
coerce('node.line.width');
28+
coerce('node.hoverinfo');
29+
Registry.getComponentMethod(
30+
'fx',
31+
'supplyDefaults'
32+
)(traceIn.node, traceOut.node, defaultColor, layout);
2733

2834
var colors = layout.colorway;
2935

@@ -39,6 +45,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3945
coerce('link.value');
4046
coerce('link.line.color');
4147
coerce('link.line.width');
48+
coerce('link.hoverinfo');
49+
Registry.getComponentMethod(
50+
'fx',
51+
'supplyDefaults'
52+
)(traceIn.link, traceOut.link, defaultColor, layout);
4253

4354
coerce('link.color', traceOut.link.value.map(function() {
4455
return tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ?

Diff for: src/traces/sankey/plot.js

+18-18
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ module.exports = function plot(gd, calcData) {
132132
var linkHover = function(element, d, sankey) {
133133
if(gd._fullLayout.hovermode === false) return;
134134
d3.select(element).call(linkHoveredStyle.bind(0, d, sankey, true));
135-
if(d.link.trace.hoverinfo !== 'skip') {
135+
if(d.link.trace.link.hoverinfo !== 'skip') {
136136
gd.emit('plotly_hover', {
137137
event: d3.event,
138138
points: [d.link]
@@ -148,8 +148,8 @@ module.exports = function plot(gd, calcData) {
148148

149149
var linkHoverFollow = function(element, d) {
150150
if(gd._fullLayout.hovermode === false) return;
151-
var trace = d.link.trace;
152-
if(trace.hoverinfo === 'none' || trace.hoverinfo === 'skip') return;
151+
var obj = d.link.trace.link;
152+
if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return;
153153
var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect();
154154
var boundingBox = element.getBoundingClientRect();
155155
var hoverCenterX = boundingBox.left + boundingBox.width / 2;
@@ -164,11 +164,11 @@ module.exports = function plot(gd, calcData) {
164164
sourceLabel + d.link.source.label,
165165
targetLabel + d.link.target.label
166166
].filter(renderableValuePresent).join('<br>'),
167-
color: castHoverOption(trace, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1),
168-
borderColor: castHoverOption(trace, 'bordercolor'),
169-
fontFamily: castHoverOption(trace, 'font.family'),
170-
fontSize: castHoverOption(trace, 'font.size'),
171-
fontColor: castHoverOption(trace, 'font.color'),
167+
color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1),
168+
borderColor: castHoverOption(obj, 'bordercolor'),
169+
fontFamily: castHoverOption(obj, 'font.family'),
170+
fontSize: castHoverOption(obj, 'font.size'),
171+
fontColor: castHoverOption(obj, 'font.color'),
172172
idealAlign: d3.event.x < hoverCenterX ? 'right' : 'left'
173173
}, {
174174
container: fullLayout._hoverlayer.node(),
@@ -183,7 +183,7 @@ module.exports = function plot(gd, calcData) {
183183
var linkUnhover = function(element, d, sankey) {
184184
if(gd._fullLayout.hovermode === false) return;
185185
d3.select(element).call(linkNonHoveredStyle.bind(0, d, sankey, true));
186-
if(d.link.trace.hoverinfo !== 'skip') {
186+
if(d.link.trace.link.hoverinfo !== 'skip') {
187187
gd.emit('plotly_unhover', {
188188
event: d3.event,
189189
points: [d.link]
@@ -204,7 +204,7 @@ module.exports = function plot(gd, calcData) {
204204
var nodeHover = function(element, d, sankey) {
205205
if(gd._fullLayout.hovermode === false) return;
206206
d3.select(element).call(nodeHoveredStyle, d, sankey);
207-
if(d.node.trace.hoverinfo !== 'skip') {
207+
if(d.node.trace.node.hoverinfo !== 'skip') {
208208
gd.emit('plotly_hover', {
209209
event: d3.event,
210210
points: [d.node]
@@ -215,8 +215,8 @@ module.exports = function plot(gd, calcData) {
215215
var nodeHoverFollow = function(element, d) {
216216
if(gd._fullLayout.hovermode === false) return;
217217

218-
var trace = d.node.trace;
219-
if(trace.hoverinfo === 'none' || trace.hoverinfo === 'skip') return;
218+
var obj = d.node.trace.node;
219+
if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return;
220220
var nodeRect = d3.select(element).select('.' + cn.nodeRect);
221221
var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect();
222222
var boundingBox = nodeRect.node().getBoundingClientRect();
@@ -234,11 +234,11 @@ module.exports = function plot(gd, calcData) {
234234
incomingLabel + d.node.targetLinks.length,
235235
outgoingLabel + d.node.sourceLinks.length
236236
].filter(renderableValuePresent).join('<br>'),
237-
color: castHoverOption(trace, 'bgcolor') || d.tinyColorHue,
238-
borderColor: castHoverOption(trace, 'bordercolor'),
239-
fontFamily: castHoverOption(trace, 'font.family'),
240-
fontSize: castHoverOption(trace, 'font.size'),
241-
fontColor: castHoverOption(trace, 'font.color'),
237+
color: castHoverOption(obj, 'bgcolor') || d.tinyColorHue,
238+
borderColor: castHoverOption(obj, 'bordercolor'),
239+
fontFamily: castHoverOption(obj, 'font.family'),
240+
fontSize: castHoverOption(obj, 'font.size'),
241+
fontColor: castHoverOption(obj, 'font.color'),
242242
idealAlign: 'left'
243243
}, {
244244
container: fullLayout._hoverlayer.node(),
@@ -253,7 +253,7 @@ module.exports = function plot(gd, calcData) {
253253
var nodeUnhover = function(element, d, sankey) {
254254
if(gd._fullLayout.hovermode === false) return;
255255
d3.select(element).call(nodeNonHoveredStyle, d, sankey);
256-
if(d.node.trace.hoverinfo !== 'skip') {
256+
if(d.node.trace.node.hoverinfo !== 'skip') {
257257
gd.emit('plotly_unhover', {
258258
event: d3.event,
259259
points: [d.node]

Diff for: test/jasmine/tests/sankey_test.js

+45-29
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ describe('sankey tests', function() {
394394
Lib.clearThrottle();
395395
}
396396

397+
var node = [404, 302],
398+
link = [450, 300];
399+
397400
it('should show the correct hover labels', function(done) {
398401
var gd = createGraphDiv();
399402
var mockCopy = Lib.extendDeep({}, mock);
@@ -433,10 +436,14 @@ describe('sankey tests', function() {
433436
);
434437

435438
return Plotly.restyle(gd, {
436-
'hoverlabel.bgcolor': 'red',
437-
'hoverlabel.bordercolor': 'blue',
438-
'hoverlabel.font.size': 20,
439-
'hoverlabel.font.color': 'black'
439+
'node.hoverlabel.bgcolor': 'red',
440+
'node.hoverlabel.bordercolor': 'blue',
441+
'node.hoverlabel.font.size': 20,
442+
'node.hoverlabel.font.color': 'black',
443+
'link.hoverlabel.bgcolor': 'red',
444+
'link.hoverlabel.bordercolor': 'blue',
445+
'link.hoverlabel.font.size': 20,
446+
'link.hoverlabel.font.color': 'black'
440447
});
441448
})
442449
.then(function() {
@@ -459,7 +466,7 @@ describe('sankey tests', function() {
459466
.then(done);
460467
});
461468

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

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

484491
Plotly.plot(gd, mockCopy).then(function() {
485492
return Plotly.relayout(gd, 'hovermode', false);
486493
})
487494
.then(function() {
488-
_hover(404, 302);
489-
495+
_hover(node[0], node[1]);
496+
assertNoLabel();
497+
})
498+
.then(function() {
499+
_hover(link[0], link[1]);
490500
assertNoLabel();
491501
})
492502
.catch(failTest)
493503
.then(done);
494504
});
495505

496-
it('should not show labels if hoverinfo is none', function(done) {
506+
it('should not show node labels if node.hoverinfo is none', function(done) {
497507
var gd = createGraphDiv();
498508
var mockCopy = Lib.extendDeep({}, mock);
499509

500510
Plotly.plot(gd, mockCopy).then(function() {
501-
return Plotly.restyle(gd, 'hoverinfo', 'none');
511+
return Plotly.restyle(gd, 'node.hoverinfo', 'none');
502512
})
503513
.then(function() {
504-
_hover(404, 302);
505-
514+
_hover(node[0], node[1]);
506515
assertNoLabel();
507516
})
508517
.catch(failTest)
509518
.then(done);
510519
});
511520

512-
it('should not show labels if hoverinfo is skip', function(done) {
521+
it('should not show link labels if link.hoverinfo is none', function(done) {
513522
var gd = createGraphDiv();
514523
var mockCopy = Lib.extendDeep({}, mock);
515524

516525
Plotly.plot(gd, mockCopy).then(function() {
517-
return Plotly.restyle(gd, 'hoverinfo', 'skip');
526+
return Plotly.restyle(gd, 'link.hoverinfo', 'none');
518527
})
519528
.then(function() {
520-
_hover(404, 302);
529+
_hover(link[0], link[1]);
530+
assertNoLabel();
531+
})
532+
.catch(failTest)
533+
.then(done);
534+
});
535+
536+
it('should not show node labels if node.hoverinfo is skip', function(done) {
537+
var gd = createGraphDiv();
538+
var mockCopy = Lib.extendDeep({}, mock);
521539

540+
Plotly.plot(gd, mockCopy).then(function() {
541+
return Plotly.restyle(gd, 'node.hoverinfo', 'skip');
542+
})
543+
.then(function() {
544+
_hover(node[0], node[1]);
522545
assertNoLabel();
523546
})
524547
.catch(failTest)
@@ -643,21 +666,13 @@ describe('sankey tests', function() {
643666
.then(done);
644667
});
645668

646-
function assertNoHoverEvents() {
669+
function assertNoHoverEvents(type) {
647670
return Promise.resolve()
648-
.then(function() { return _hover('node'); })
671+
.then(function() { return _hover(type); })
649672
.then(failTest).catch(function(err) {
650673
expect(err).toBe('plotly_hover did not get called!');
651674
})
652-
.then(function() { return _unhover('node'); })
653-
.then(failTest).catch(function(err) {
654-
expect(err).toBe('plotly_unhover did not get called!');
655-
})
656-
.then(function() { return _hover('link'); })
657-
.then(failTest).catch(function(err) {
658-
expect(err).toBe('plotly_hover did not get called!');
659-
})
660-
.then(function() { return _unhover('link'); })
675+
.then(function() { return _unhover(type); })
661676
.then(failTest).catch(function(err) {
662677
expect(err).toBe('plotly_unhover did not get called!');
663678
});
@@ -668,7 +683,8 @@ describe('sankey tests', function() {
668683

669684
Plotly.plot(gd, fig)
670685
.then(function() { return Plotly.relayout(gd, 'hovermode', false); })
671-
.then(assertNoHoverEvents)
686+
.then(function() { return assertNoHoverEvents('node');})
687+
.then(function() { return assertNoHoverEvents('link');})
672688
.catch(failTest)
673689
.then(done);
674690
});
@@ -677,8 +693,8 @@ describe('sankey tests', function() {
677693
var fig = Lib.extendDeep({}, mock);
678694

679695
Plotly.plot(gd, fig)
680-
.then(function() { return Plotly.restyle(gd, 'hoverinfo', 'skip'); })
681-
.then(assertNoHoverEvents)
696+
.then(function() { return Plotly.restyle(gd, 'link.hoverinfo', 'skip'); })
697+
.then(function() { return assertNoHoverEvents('link');})
682698
.catch(failTest)
683699
.then(done);
684700
});

0 commit comments

Comments
 (0)