Skip to content

Commit

Permalink
Merge pull request #6040 from plotly/grouptitlesfont
Browse files Browse the repository at this point in the history
Implement `legend.grouptitlefont` and `hoverlabel.grouptitlefont`
  • Loading branch information
archmoj committed Dec 10, 2021
2 parents fc10a31 + 775b9fc commit 1206902
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 31 deletions.
1 change: 1 addition & 0 deletions draftlogs/6040_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Implement legend.grouptitlefont and hoverlabel.grouptitlefont [[#6040](https://github.com/plotly/plotly.js/pull/6040)]
7 changes: 5 additions & 2 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,9 @@ function createHoverText(hoverData, opts) {
orientation: 'v'
}
};
var mockLayoutOut = {};
var mockLayoutOut = {
font: font
};
legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
var mockLegend = mockLayoutOut.legend;

Expand Down Expand Up @@ -1144,7 +1146,8 @@ function createHoverText(hoverData, opts) {

// Draw unified hover label
mockLegend._inHover = true;
mockLegend._groupTitleFont = font;
mockLegend._groupTitleFont = hoverlabel.grouptitlefont;

legendDraw(gd, mockLegend);

// Position the hover
Expand Down
6 changes: 4 additions & 2 deletions src/components/fx/hoverlabel_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ var isUnifiedHover = require('./helpers').isUnifiedHover;
module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
opts = opts || {};

var hasLegend = contOut.legend;

function inheritFontAttr(attr) {
if(!opts.font[attr]) {
opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
}
}

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

if(contOut.legend) {
if(hasLegend) {
if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
} else {
Expand Down
18 changes: 14 additions & 4 deletions src/components/fx/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

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

var fontAttrs = require('../../plots/font_attributes')({
var fontAttrs = require('../../plots/font_attributes');

var font = fontAttrs({
editType: 'none',
description: 'Sets the default hover label font used by all traces on the graph.'
});
fontAttrs.family.dflt = constants.HOVERFONT;
fontAttrs.size.dflt = constants.HOVERFONTSIZE;
font.family.dflt = constants.HOVERFONT;
font.size.dflt = constants.HOVERFONTSIZE;

module.exports = {
clickmode: {
Expand Down Expand Up @@ -118,7 +120,14 @@ module.exports = {
'Sets the border color of all hover labels on graph.'
].join(' ')
},
font: fontAttrs,
font: font,
grouptitlefont: fontAttrs({
editType: 'none',
description: [
'Sets the font for group titles in hover (unified modes).',
'Defaults to `hoverlabel.font`.'
].join(' ')
}),
align: {
valType: 'enumerated',
values: ['left', 'right', 'auto'],
Expand All @@ -143,6 +152,7 @@ module.exports = {
'`namelength - 3` characters and add an ellipsis.'
].join(' ')
},

editType: 'none'
},
selectdirection: {
Expand Down
2 changes: 2 additions & 0 deletions src/components/fx/layout_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
}

handleHoverLabelDefaults(layoutIn, layoutOut, coerce);

Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
};
7 changes: 7 additions & 0 deletions src/components/legend/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ module.exports = {
editType: 'legend',
description: 'Sets the font used to text the legend items.'
}),
grouptitlefont: fontAttrs({
editType: 'legend',
description: [
'Sets the font for group titles in legend.',
'Defaults to `legend.font` with its size increased about 10%.'
].join(' ')
}),
orientation: {
valType: 'enumerated',
values: ['v', 'h'],
Expand Down
31 changes: 24 additions & 7 deletions src/components/legend/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,38 @@ var Registry = require('../../registry');
var Lib = require('../../lib');
var Template = require('../../plot_api/plot_template');

var plotsAttrs = require('../../plots/attributes');
var attributes = require('./attributes');
var basePlotLayoutAttributes = require('../../plots/layout_attributes');
var helpers = require('./helpers');


module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
var containerIn = layoutIn.legend || {};
var containerOut = Template.newContainer(layoutOut, 'legend');

function coerce(attr, dflt) {
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
}

var trace;
var traceCoerce = function(attr, dflt) {
var traceIn = trace._input;
var traceOut = trace;
return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
};

var globalFont = layoutOut.font || {};
var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
size: Math.round(globalFont.size * 1.1)
}));

var legendTraceCount = 0;
var legendReallyHasATrace = false;
var defaultOrder = 'normal';

for(var i = 0; i < fullData.length; i++) {
var trace = fullData[i];
trace = fullData[i];

if(!trace.visible) continue;

Expand All @@ -44,6 +62,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
legendTraceCount++;
}
}

Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
}

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

if(showLegend === false && !containerIn.uirevision) return;

var containerOut = Template.newContainer(layoutOut, 'legend');
// delete legend
if(showLegend === false) layoutOut.legend = undefined;

function coerce(attr, dflt) {
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
}
if(showLegend === false && !containerIn.uirevision) return;

coerce('uirevision', layoutOut.uirevision);

Expand Down
2 changes: 1 addition & 1 deletion src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
(typeof value === 'string' || typeof value === 'number')) {
replace(key, key.replace('title', 'title.text'));
} else if(key.indexOf('titlefont') > -1) {
} else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
replace(key, key.replace('titlefont', 'title.font'));
} else if(key.indexOf('titleposition') > -1) {
replace(key, key.replace('titleposition', 'title.position'));
Expand Down
1 change: 1 addition & 0 deletions src/plots/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ module.exports = {
'c) One trace is explicitly given with `showlegend: true`.'
].join(' ')
},

colorway: {
valType: 'colorlist',
dflt: colorAttrs.defaults,
Expand Down
22 changes: 7 additions & 15 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -1321,13 +1321,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
);

coerce('legendgroup');
var titleText = coerce('legendgrouptitle.text');
if(titleText) {
Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
size: Math.round(layout.font.size * 1.1) // default to larger font size
}));
}

coerce('legendgrouptitle.text');
coerce('legendrank');

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

coerce('autotypenumbers');

var globalFont = Lib.coerceFont(coerce, 'font');

coerce('title.text', layoutOut._dfltTitle.plot);
var font = Lib.coerceFont(coerce, 'font');
var fontSize = font.size;

Lib.coerceFont(coerce, 'title.font', {
family: globalFont.family,
size: Math.round(globalFont.size * 1.4),
color: globalFont.color
});
Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
size: Math.round(fontSize * 1.4)
}));

coerce('title.text', layoutOut._dfltTitle.plot);
coerce('title.xref');
coerce('title.yref');
coerce('title.x');
Expand Down
Binary file modified test/image/baselines/legendrank.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions test/image/mocks/legendrank.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
"text": "legendrank"
},
"hovermode": "x unified",
"hoverlabel": {
"grouptitlefont": {
"family": "Raleway",
"color": "red",
"size": 16
}
},
"legend": {
"grouptitlefont": {
"family": "Times New Roman",
"color": "orange",
"size": 14
}
},
"margin": {
"t": 50,
"b": 25
Expand Down
34 changes: 34 additions & 0 deletions test/jasmine/tests/hover_label_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6144,6 +6144,40 @@ describe('hovermode: (x|y)unified', function() {
.then(done, done.fail);
});

it('should use hoverlabel.grouptitlefont for group titles', function(done) {
function assertFont(fontFamily, fontSize, fontColor) {
var hover = getHoverLabel();
var traces = hover.selectAll('g.traces');

traces.each(function() {
var e = d3Select(this);
var text = e.select('text.legendtext');
var node = text.node();
var label = node.innerHTML;
if(label.indexOf('group') !== -1) {
var textStyle = window.getComputedStyle(node);
expect(textStyle.fontFamily.split(',')[0]).toBe(fontFamily, 'wrong font family');
expect(textStyle.fontSize).toBe(fontSize, 'wrong font size');
expect(textStyle.fill).toBe(fontColor, 'wrong font color');
}
});
}

var mockCopy = Lib.extendDeep({}, groupTitlesMock);

mockCopy.layout.hoverlabel = {
grouptitlefont: {size: 20, family: 'Mono', color: 'rgb(255, 127, 0)'}
};

Plotly.newPlot(gd, mockCopy)
.then(function(gd) {
_hover(gd, { xval: 0});

assertFont('Mono', '20px', 'rgb(255, 127, 0)');
})
.then(done, done.fail);
});

it('should work with hovertemplate', function(done) {
var mockCopy = Lib.extendDeep({}, mock);
mockCopy.data[0].hovertemplate = 'hovertemplate: %{y:0.2f}';
Expand Down
42 changes: 42 additions & 0 deletions test/plot-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2494,6 +2494,27 @@
"valType": "number"
}
},
"grouptitlefont": {
"color": {
"editType": "none",
"valType": "color"
},
"description": "Sets the font for group titles in hover (unified modes). Defaults to `hoverlabel.font`.",
"editType": "none",
"family": {
"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*.",
"editType": "none",
"noBlank": true,
"strict": true,
"valType": "string"
},
"role": "object",
"size": {
"editType": "none",
"min": 1,
"valType": "number"
}
},
"namelength": {
"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.",
"dflt": 15,
Expand Down Expand Up @@ -2693,6 +2714,27 @@
"togglegroup"
]
},
"grouptitlefont": {
"color": {
"editType": "legend",
"valType": "color"
},
"description": "Sets the font for group titles in legend. Defaults to `legend.font` with its size increased about 10%.",
"editType": "legend",
"family": {
"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*.",
"editType": "legend",
"noBlank": true,
"strict": true,
"valType": "string"
},
"role": "object",
"size": {
"editType": "legend",
"min": 1,
"valType": "number"
}
},
"itemclick": {
"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.",
"dflt": "toggle",
Expand Down

0 comments on commit 1206902

Please sign in to comment.