Skip to content

Commit 1206902

Browse files
authored
Merge pull request #6040 from plotly/grouptitlesfont
Implement `legend.grouptitlefont` and `hoverlabel.grouptitlefont`
2 parents fc10a31 + 775b9fc commit 1206902

File tree

14 files changed

+156
-31
lines changed

14 files changed

+156
-31
lines changed

draftlogs/6040_add.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Implement legend.grouptitlefont and hoverlabel.grouptitlefont [[#6040](https://github.com/plotly/plotly.js/pull/6040)]

src/components/fx/hover.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,9 @@ function createHoverText(hoverData, opts) {
11031103
orientation: 'v'
11041104
}
11051105
};
1106-
var mockLayoutOut = {};
1106+
var mockLayoutOut = {
1107+
font: font
1108+
};
11071109
legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
11081110
var mockLegend = mockLayoutOut.legend;
11091111

@@ -1144,7 +1146,8 @@ function createHoverText(hoverData, opts) {
11441146

11451147
// Draw unified hover label
11461148
mockLegend._inHover = true;
1147-
mockLegend._groupTitleFont = font;
1149+
mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
1150+
11481151
legendDraw(gd, mockLegend);
11491152

11501153
// Position the hover

src/components/fx/hoverlabel_defaults.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ var isUnifiedHover = require('./helpers').isUnifiedHover;
77
module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
88
opts = opts || {};
99

10+
var hasLegend = contOut.legend;
11+
1012
function inheritFontAttr(attr) {
1113
if(!opts.font[attr]) {
12-
opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
14+
opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
1315
}
1416
}
1517

@@ -20,7 +22,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
2022
inheritFontAttr('family');
2123
inheritFontAttr('color');
2224

23-
if(contOut.legend) {
25+
if(hasLegend) {
2426
if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
2527
if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
2628
} else {

src/components/fx/layout_attributes.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
var constants = require('./constants');
44

5-
var fontAttrs = require('../../plots/font_attributes')({
5+
var fontAttrs = require('../../plots/font_attributes');
6+
7+
var font = fontAttrs({
68
editType: 'none',
79
description: 'Sets the default hover label font used by all traces on the graph.'
810
});
9-
fontAttrs.family.dflt = constants.HOVERFONT;
10-
fontAttrs.size.dflt = constants.HOVERFONTSIZE;
11+
font.family.dflt = constants.HOVERFONT;
12+
font.size.dflt = constants.HOVERFONTSIZE;
1113

1214
module.exports = {
1315
clickmode: {
@@ -118,7 +120,14 @@ module.exports = {
118120
'Sets the border color of all hover labels on graph.'
119121
].join(' ')
120122
},
121-
font: fontAttrs,
123+
font: font,
124+
grouptitlefont: fontAttrs({
125+
editType: 'none',
126+
description: [
127+
'Sets the font for group titles in hover (unified modes).',
128+
'Defaults to `hoverlabel.font`.'
129+
].join(' ')
130+
}),
122131
align: {
123132
valType: 'enumerated',
124133
values: ['left', 'right', 'auto'],
@@ -143,6 +152,7 @@ module.exports = {
143152
'`namelength - 3` characters and add an ellipsis.'
144153
].join(' ')
145154
},
155+
146156
editType: 'none'
147157
},
148158
selectdirection: {

src/components/fx/layout_defaults.js

+2
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
3434
}
3535

3636
handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
37+
38+
Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
3739
};

src/components/legend/attributes.js

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ module.exports = {
3030
editType: 'legend',
3131
description: 'Sets the font used to text the legend items.'
3232
}),
33+
grouptitlefont: fontAttrs({
34+
editType: 'legend',
35+
description: [
36+
'Sets the font for group titles in legend.',
37+
'Defaults to `legend.font` with its size increased about 10%.'
38+
].join(' ')
39+
}),
3340
orientation: {
3441
valType: 'enumerated',
3542
values: ['v', 'h'],

src/components/legend/defaults.js

+24-7
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,38 @@ var Registry = require('../../registry');
44
var Lib = require('../../lib');
55
var Template = require('../../plot_api/plot_template');
66

7+
var plotsAttrs = require('../../plots/attributes');
78
var attributes = require('./attributes');
89
var basePlotLayoutAttributes = require('../../plots/layout_attributes');
910
var helpers = require('./helpers');
1011

1112

1213
module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
1314
var containerIn = layoutIn.legend || {};
15+
var containerOut = Template.newContainer(layoutOut, 'legend');
16+
17+
function coerce(attr, dflt) {
18+
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
19+
}
20+
21+
var trace;
22+
var traceCoerce = function(attr, dflt) {
23+
var traceIn = trace._input;
24+
var traceOut = trace;
25+
return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
26+
};
27+
28+
var globalFont = layoutOut.font || {};
29+
var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
30+
size: Math.round(globalFont.size * 1.1)
31+
}));
1432

1533
var legendTraceCount = 0;
1634
var legendReallyHasATrace = false;
1735
var defaultOrder = 'normal';
1836

1937
for(var i = 0; i < fullData.length; i++) {
20-
var trace = fullData[i];
38+
trace = fullData[i];
2139

2240
if(!trace.visible) continue;
2341

@@ -44,6 +62,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
4462
legendTraceCount++;
4563
}
4664
}
65+
66+
Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
4767
}
4868

4969
if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -62,13 +82,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
6282
basePlotLayoutAttributes, 'showlegend',
6383
legendReallyHasATrace && legendTraceCount > 1);
6484

65-
if(showLegend === false && !containerIn.uirevision) return;
66-
67-
var containerOut = Template.newContainer(layoutOut, 'legend');
85+
// delete legend
86+
if(showLegend === false) layoutOut.legend = undefined;
6887

69-
function coerce(attr, dflt) {
70-
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
71-
}
88+
if(showLegend === false && !containerIn.uirevision) return;
7289

7390
coerce('uirevision', layoutOut.uirevision);
7491

src/plot_api/plot_api.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
17191719
if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
17201720
(typeof value === 'string' || typeof value === 'number')) {
17211721
replace(key, key.replace('title', 'title.text'));
1722-
} else if(key.indexOf('titlefont') > -1) {
1722+
} else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
17231723
replace(key, key.replace('titlefont', 'title.font'));
17241724
} else if(key.indexOf('titleposition') > -1) {
17251725
replace(key, key.replace('titleposition', 'title.position'));

src/plots/layout_attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ module.exports = {
309309
'c) One trace is explicitly given with `showlegend: true`.'
310310
].join(' ')
311311
},
312+
312313
colorway: {
313314
valType: 'colorlist',
314315
dflt: colorAttrs.defaults,

src/plots/plots.js

+7-15
Original file line numberDiff line numberDiff line change
@@ -1321,13 +1321,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
13211321
);
13221322

13231323
coerce('legendgroup');
1324-
var titleText = coerce('legendgrouptitle.text');
1325-
if(titleText) {
1326-
Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
1327-
size: Math.round(layout.font.size * 1.1) // default to larger font size
1328-
}));
1329-
}
1330-
1324+
coerce('legendgrouptitle.text');
13311325
coerce('legendrank');
13321326

13331327
traceOut._dfltShowLegend = true;
@@ -1475,16 +1469,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
14751469

14761470
coerce('autotypenumbers');
14771471

1478-
var globalFont = Lib.coerceFont(coerce, 'font');
1479-
1480-
coerce('title.text', layoutOut._dfltTitle.plot);
1472+
var font = Lib.coerceFont(coerce, 'font');
1473+
var fontSize = font.size;
14811474

1482-
Lib.coerceFont(coerce, 'title.font', {
1483-
family: globalFont.family,
1484-
size: Math.round(globalFont.size * 1.4),
1485-
color: globalFont.color
1486-
});
1475+
Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
1476+
size: Math.round(fontSize * 1.4)
1477+
}));
14871478

1479+
coerce('title.text', layoutOut._dfltTitle.plot);
14881480
coerce('title.xref');
14891481
coerce('title.yref');
14901482
coerce('title.x');

test/image/baselines/legendrank.png

-275 Bytes
Loading

test/image/mocks/legendrank.json

+14
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@
3737
"text": "legendrank"
3838
},
3939
"hovermode": "x unified",
40+
"hoverlabel": {
41+
"grouptitlefont": {
42+
"family": "Raleway",
43+
"color": "red",
44+
"size": 16
45+
}
46+
},
47+
"legend": {
48+
"grouptitlefont": {
49+
"family": "Times New Roman",
50+
"color": "orange",
51+
"size": 14
52+
}
53+
},
4054
"margin": {
4155
"t": 50,
4256
"b": 25

test/jasmine/tests/hover_label_test.js

+34
Original file line numberDiff line numberDiff line change
@@ -6144,6 +6144,40 @@ describe('hovermode: (x|y)unified', function() {
61446144
.then(done, done.fail);
61456145
});
61466146

6147+
it('should use hoverlabel.grouptitlefont for group titles', function(done) {
6148+
function assertFont(fontFamily, fontSize, fontColor) {
6149+
var hover = getHoverLabel();
6150+
var traces = hover.selectAll('g.traces');
6151+
6152+
traces.each(function() {
6153+
var e = d3Select(this);
6154+
var text = e.select('text.legendtext');
6155+
var node = text.node();
6156+
var label = node.innerHTML;
6157+
if(label.indexOf('group') !== -1) {
6158+
var textStyle = window.getComputedStyle(node);
6159+
expect(textStyle.fontFamily.split(',')[0]).toBe(fontFamily, 'wrong font family');
6160+
expect(textStyle.fontSize).toBe(fontSize, 'wrong font size');
6161+
expect(textStyle.fill).toBe(fontColor, 'wrong font color');
6162+
}
6163+
});
6164+
}
6165+
6166+
var mockCopy = Lib.extendDeep({}, groupTitlesMock);
6167+
6168+
mockCopy.layout.hoverlabel = {
6169+
grouptitlefont: {size: 20, family: 'Mono', color: 'rgb(255, 127, 0)'}
6170+
};
6171+
6172+
Plotly.newPlot(gd, mockCopy)
6173+
.then(function(gd) {
6174+
_hover(gd, { xval: 0});
6175+
6176+
assertFont('Mono', '20px', 'rgb(255, 127, 0)');
6177+
})
6178+
.then(done, done.fail);
6179+
});
6180+
61476181
it('should work with hovertemplate', function(done) {
61486182
var mockCopy = Lib.extendDeep({}, mock);
61496183
mockCopy.data[0].hovertemplate = 'hovertemplate: %{y:0.2f}';

test/plot-schema.json

+42
Original file line numberDiff line numberDiff line change
@@ -2494,6 +2494,27 @@
24942494
"valType": "number"
24952495
}
24962496
},
2497+
"grouptitlefont": {
2498+
"color": {
2499+
"editType": "none",
2500+
"valType": "color"
2501+
},
2502+
"description": "Sets the font for group titles in hover (unified modes). Defaults to `hoverlabel.font`.",
2503+
"editType": "none",
2504+
"family": {
2505+
"description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.",
2506+
"editType": "none",
2507+
"noBlank": true,
2508+
"strict": true,
2509+
"valType": "string"
2510+
},
2511+
"role": "object",
2512+
"size": {
2513+
"editType": "none",
2514+
"min": 1,
2515+
"valType": "number"
2516+
}
2517+
},
24972518
"namelength": {
24982519
"description": "Sets the default length (in number of characters) of the trace name in the hover labels for all traces. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis.",
24992520
"dflt": 15,
@@ -2693,6 +2714,27 @@
26932714
"togglegroup"
26942715
]
26952716
},
2717+
"grouptitlefont": {
2718+
"color": {
2719+
"editType": "legend",
2720+
"valType": "color"
2721+
},
2722+
"description": "Sets the font for group titles in legend. Defaults to `legend.font` with its size increased about 10%.",
2723+
"editType": "legend",
2724+
"family": {
2725+
"description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.",
2726+
"editType": "legend",
2727+
"noBlank": true,
2728+
"strict": true,
2729+
"valType": "string"
2730+
},
2731+
"role": "object",
2732+
"size": {
2733+
"editType": "legend",
2734+
"min": 1,
2735+
"valType": "number"
2736+
}
2737+
},
26962738
"itemclick": {
26972739
"description": "Determines the behavior on legend item click. *toggle* toggles the visibility of the item clicked on the graph. *toggleothers* makes the clicked item the sole visible item on the graph. *false* disables legend item click interactions.",
26982740
"dflt": "toggle",

0 commit comments

Comments
 (0)