Skip to content

Commit 576ac60

Browse files
committed
unified hover: honor hoverlabel.font, then legend.font, then layout.font
1 parent 9faea16 commit 576ac60

File tree

3 files changed

+79
-9
lines changed

3 files changed

+79
-9
lines changed

src/components/fx/hover.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,8 +989,8 @@ function createHoverText(hoverData, opts, gd) {
989989
var mockLayoutIn = {
990990
showlegend: true,
991991
legend: {
992-
title: {text: t0, font: fullLayout.font},
993-
font: fullLayout.font,
992+
title: {text: t0, font: fullLayout.hoverlabel.font},
993+
font: fullLayout.hoverlabel.font,
994994
bgcolor: fullLayout.hoverlabel.bgcolor,
995995
borderwidth: 1,
996996
tracegroupgap: 7,

src/components/fx/hoverlabel_defaults.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
1515
opts = opts || {};
1616

1717
if(contIn && isUnifiedHover(contIn.hovermode)) {
18-
opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor;
18+
if(!opts.bgcolor) opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor;
19+
// Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font
20+
opts.font = Lib.extendFlat({}, contIn.font, contIn.legend ? contIn.legend.font : {}, opts.font);
1921
}
2022

2123
coerce('hoverlabel.bgcolor', opts.bgcolor);

test/jasmine/tests/hover_label_test.js

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3988,14 +3988,18 @@ describe('hovermode: (x|y)unified', function() {
39883988
Lib.clearThrottle();
39893989
}
39903990

3991+
function getHoverLabel() {
3992+
var hoverLayer = d3.select('g.hoverlayer');
3993+
return hoverLayer.select('g.legend');
3994+
}
3995+
39913996
function assertElementCount(selector, size) {
39923997
var g = d3.selectAll(selector);
39933998
expect(g.size()).toBe(size);
39943999
}
39954000

39964001
function assertLabel(expectation) {
3997-
var hoverLayer = d3.select('g.hoverlayer');
3998-
var hover = hoverLayer.select('g.legend');
4002+
var hover = getHoverLabel();
39994003
var title = hover.select('text.legendtitletext');
40004004
var traces = hover.selectAll('g.traces');
40014005

@@ -4011,15 +4015,13 @@ describe('hovermode: (x|y)unified', function() {
40114015
}
40124016

40134017
function assertBgcolor(color) {
4014-
var hoverLayer = d3.select('g.hoverlayer');
4015-
var hover = hoverLayer.select('g.legend');
4018+
var hover = getHoverLabel();
40164019
var bg = hover.select('rect.bg');
40174020
expect(bg.node().style.fill).toBe(color);
40184021
}
40194022

40204023
function assertSymbol(exp) {
4021-
var hoverLayer = d3.select('g.hoverlayer');
4022-
var hover = hoverLayer.select('g.legend');
4024+
var hover = getHoverLabel();
40234025
var traces = hover.selectAll('g.traces');
40244026
expect(traces.size()).toBe(exp.length);
40254027

@@ -4034,6 +4036,17 @@ describe('hovermode: (x|y)unified', function() {
40344036
});
40354037
}
40364038

4039+
function assertFont(fontFamily, fontSize, fontColor) {
4040+
var hover = getHoverLabel();
4041+
var text = hover.select('text.legendtext');
4042+
var node = text.node();
4043+
4044+
var textStyle = window.getComputedStyle(node);
4045+
expect(textStyle.fontFamily.split(',')[0]).toBe(fontFamily, 'wrong font family');
4046+
expect(textStyle.fontSize).toBe(fontSize, 'wrong font size');
4047+
expect(textStyle.fill).toBe(fontColor, 'wrong font color');
4048+
}
4049+
40374050
it('set smart defaults for spikeline in x unified', function(done) {
40384051
Plotly.newPlot(gd, [{y: [4, 6, 5]}], {'hovermode': 'x unified', 'xaxis': {'color': 'red'}})
40394052
.then(function(gd) {
@@ -4371,6 +4384,61 @@ describe('hovermode: (x|y)unified', function() {
43714384
.then(done);
43724385
});
43734386

4387+
it('should use hoverlabel.font or legend.font or layout.font', function(done) {
4388+
var mockCopy = Lib.extendDeep({}, mock);
4389+
4390+
// Set layout.font
4391+
mockCopy.layout.font = {size: 20, family: 'Mono', color: 'rgb(10, 10, 10)'};
4392+
Plotly.newPlot(gd, mockCopy)
4393+
.then(function(gd) {
4394+
_hover(gd, { xval: 3});
4395+
4396+
assertFont('Mono', '20px', 'rgb(10, 10, 10)');
4397+
4398+
// Set legend.font which should win over layout font
4399+
return Plotly.relayout(gd, {
4400+
'showlegend': true,
4401+
'legend.font.size': 15,
4402+
'legend.font.family': 'Helvetica',
4403+
'legend.font.color': 'rgb(20, 20, 20)'
4404+
});
4405+
})
4406+
.then(function(gd) {
4407+
_hover(gd, { xval: 3 });
4408+
4409+
assertFont('Helvetica', '15px', 'rgb(20, 20, 20)');
4410+
4411+
// Set hoverlabel.font which should win over legend.font
4412+
return Plotly.relayout(gd, {
4413+
'hoverlabel.font.size': 22,
4414+
'hoverlabel.font.family': 'Arial',
4415+
'hoverlabel.font.color': 'rgb(30, 30, 30)'
4416+
});
4417+
})
4418+
.then(function() {
4419+
_hover(gd, { xval: 3 });
4420+
4421+
assertFont('Arial', '22px', 'rgb(30, 30, 30)');
4422+
4423+
// Finally, check that a hoverlabel.font defined in template wins
4424+
delete mockCopy.layout;
4425+
mockCopy.layout = {
4426+
hovermode: 'x unified',
4427+
template: { layout: { hoverlabel: { font: {family: 'Mono', size: 30, color: 'red'}}}},
4428+
legend: {font: {size: 20, family: 'Mono', color: 'rgb(10, 10, 10)'}}
4429+
};
4430+
4431+
return Plotly.newPlot(gd, mockCopy);
4432+
})
4433+
.then(function() {
4434+
_hover(gd, { xval: 3 });
4435+
4436+
assertFont('Mono', '30px', 'rgb(255, 0, 0)');
4437+
})
4438+
.catch(failTest)
4439+
.then(done);
4440+
});
4441+
43744442
it('should work with hovertemplate', function(done) {
43754443
var mockCopy = Lib.extendDeep({}, mock);
43764444
mockCopy.data[0].hovertemplate = 'hovertemplate: %{y:0.2f}';

0 commit comments

Comments
 (0)