Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

882 - Chart Title Alignment #3276

Merged
merged 50 commits into from
Nov 29, 2018
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6687034
Add test of current plot title alignment [882]
rmoestl Oct 30, 2018
a7e3a9d
Transition layout titles from being strings to be objects [882]
rmoestl Oct 30, 2018
50a1e9b
Support updating titles through `relayout` and `update` [882]
rmoestl Oct 31, 2018
4d21886
Deprecate `*.titlefont` attributes in favor of `*.title.font` [882]
rmoestl Nov 5, 2018
66a8154
Implement basic chart title alignment options [882]
rmoestl Nov 7, 2018
6f583a4
Add test to ensure current chart title position is still supported [882]
rmoestl Nov 8, 2018
185772b
Implement 'auto' values for title's `xanchor` and `yanchor` [882]
rmoestl Nov 12, 2018
ac3649b
Support deprecated axes titles syntax for multiple axes [882]
rmoestl Nov 13, 2018
493b6ec
Adapt axes tests to new `title` structure [882]
rmoestl Nov 14, 2018
4d7c4b3
Adapt axes auto-margin code to new `title` structure [882]
rmoestl Nov 14, 2018
96df782
Adapt `axes.swap` to new `title` attr structure [882]
rmoestl Nov 14, 2018
43da557
Adapt colorbar to new title attr structure [882]
rmoestl Nov 13, 2018
9e2cbfe
Adapt rangeslider to new title attr structure [882]
rmoestl Nov 14, 2018
f632a7d
Transition polar plot type to new title attr structure [882]
rmoestl Nov 15, 2018
b3367f1
Adapt legacy polar chart to new title attr structure [882]
rmoestl Nov 15, 2018
cf7f493
Transition ternary plot type to new title attr structure [882]
rmoestl Nov 15, 2018
573c90d
Deduplicate transitioning to new title structure in `cleanLayout` [882]
rmoestl Nov 15, 2018
ddf9c0b
Transition gl3d plot type to new title attr structure [882]
rmoestl Nov 15, 2018
0e144b6
Transition gl2d plot type to new title attr structure [882]
rmoestl Nov 15, 2018
984aa46
Expect new title syntax in legend, lib and further tests [882]
rmoestl Nov 15, 2018
58f402a
Reactivating editing plot title [882]
rmoestl Nov 15, 2018
5e16b02
Also call cleanLayout on `layout.template.layout` [882]
rmoestl Nov 16, 2018
7a81f27
Adjust hover template test to new title structure [882]
rmoestl Nov 20, 2018
e53e546
Adapt clonePlot function to new title attr structure [882]
rmoestl Nov 20, 2018
ca920ab
Implement padding for chart title alignment [882]
rmoestl Nov 20, 2018
37bb68c
Restrict title.y (and x) to a number between 0 and 1 [882]
rmoestl Nov 20, 2018
e438a3f
Edit attribute descriptions for new title attr structure [882]
rmoestl Nov 21, 2018
b37950d
Minor clean up in subroutines.js [882]
rmoestl Nov 21, 2018
0c2bfd7
Fix cleaning deprecated title structure on relayout/update [882]
rmoestl Nov 21, 2018
eda4f72
Fix `cleanLayout` bug [882]
rmoestl Nov 21, 2018
53ea94d
Remove small piece of obsolete code in gl3d's convert module [882]
rmoestl Nov 21, 2018
f896273
Still accept numbers as titles when defined in deprecated notation [882]
rmoestl Nov 22, 2018
f7b652b
Improve and simplify title compatibility code for relayout [882]
rmoestl Nov 22, 2018
1288121
Clear TODOs in gl3d axis_defaults.js and cloneplot.js [882]
rmoestl Nov 22, 2018
ee613bb
Streamline variable names in subroutines.js [882]
rmoestl Nov 23, 2018
678c2d9
Deprecate old title structure properly [882]
rmoestl Nov 23, 2018
598fc5f
Fix plotschema_test.js to embrace deprecated attribute containers [882]
rmoestl Nov 23, 2018
4efb546
Make explanatory comment in polar.js more clear [882]
rmoestl Nov 23, 2018
014548c
Skip overriding deprecated title attributes in polar [882]
rmoestl Nov 26, 2018
1117113
Reuse Lib.counterRegex to match deprecated title string attributes [882]
rmoestl Nov 26, 2018
c2b4c10
Pass back update data unmodified to plotly_relayout event handlers [882]
rmoestl Nov 26, 2018
86a88e2
Move legend's anchor_utils to Lib and use them in title alignment [882]
rmoestl Nov 23, 2018
5fb7b8f
Redeclare valType of title.y to be a 'number' [882]
rmoestl Nov 26, 2018
d600bbd
Merge branch 'master' into 882-chart-title-alignment
rmoestl Nov 27, 2018
a2f0543
Transition pie trace type to new title attr structure [882]
rmoestl Nov 27, 2018
a4e43a6
Transition color bar to new title attr structure [882]
rmoestl Nov 27, 2018
e4dbc5d
Transition carpet to new title attr structure [882]
rmoestl Nov 28, 2018
ef9e078
Refactor code to clean up deprecated title attr structure [882]
rmoestl Nov 28, 2018
e3bcf7c
Let '' be the default carpet axes title [882]
rmoestl Nov 28, 2018
2b26746
Reverse coerce logic for carpet axes titles [882]
rmoestl Nov 29, 2018
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
65 changes: 50 additions & 15 deletions src/components/colorbar/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,56 @@ module.exports = overrideAll({
exponentformat: axesAttrs.exponentformat,
showexponent: axesAttrs.showexponent,
title: {
valType: 'string',
role: 'info',
description: 'Sets the title of the color bar.'
text: {
valType: 'string',
role: 'info',
description: [
'Sets the title of the color bar.',
'Note that before the existence of `title.text`, the title\'s',
'contents used to be defined as the `title` attribute itself.',
'This behavior has been deprecated.'
].join(' ')
},
font: fontAttrs({
description: [
'Sets this color bar\'s title font.',
'Note that the title\'s font used to be set',
'by the now deprecated `titlefont` attribute.'
].join(' ')
}),
side: {
valType: 'enumerated',
values: ['right', 'top', 'bottom'],
role: 'style',
dflt: 'top',
description: [
'Determines the location of color bar\'s title',
'with respect to the color bar.',
'Note that the title\'s location used to be set',
'by the now deprecated `titleside` attribute.'
].join(' ')
}
},
titlefont: fontAttrs({
description: 'Sets this color bar\'s title font.'
}),
titleside: {
valType: 'enumerated',
values: ['right', 'top', 'bottom'],
role: 'style',
dflt: 'top',
description: [
'Determines the location of the colorbar title',
'with respect to the color bar.'
].join(' ')

_deprecated: {
title: {
valType: 'string',
role: 'info',
description: [
'Deprecated in favor of color bar\'s `title.text`.',
'Note that value of color bar\'s `title` is no longer a simple',
'*string* but a set of sub-attributes.'
].join(' ')
},
titlefont: fontAttrs({
description: 'Deprecated in favor of color bar\'s `title.font`.'
}),
titleside: {
valType: 'enumerated',
values: ['right', 'top', 'bottom'],
role: 'style',
dflt: 'top',
description: 'Deprecated in favor of color bar\'s `title.side`.'
}
}
}, 'colorbars', 'from-root');
6 changes: 3 additions & 3 deletions src/components/colorbar/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
handleTickLabelDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts);
handleTickMarkDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts);

coerce('title', layout._dfltTitle.colorbar);
Lib.coerceFont(coerce, 'titlefont', layout.font);
coerce('titleside');
coerce('title.text', layout._dfltTitle.colorbar);
Lib.coerceFont(coerce, 'title.font', layout.font);
coerce('title.side');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh hmm, I was going to say we should not coerce title.font and title.side here but because of _dfltTitle you'd have to explicitly set title.text = '' to make these irrelevant, and even then in principle in editable: true mode we would need these attributes. So I guess here - and everywhere else the titles are editable within the plot - it's correct as is. And the only places that doesn't apply are carpet (discussed elsewhere) and pie (already handled correctly) 🎉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. That was my concern as well (plus my guess that we might need font to calculate things like automargin even if we don't have a title set). But I resisted to raise that because I haven't done the research in the code to underpin my claim.

};
29 changes: 14 additions & 15 deletions src/components/colorbar/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ module.exports = function draw(gd, id) {
showticksuffix: opts.showticksuffix,
ticksuffix: opts.ticksuffix,
title: opts.title,
titlefont: opts.titlefont,
showline: true,
anchor: 'free',
side: 'right',
Expand Down Expand Up @@ -218,11 +217,11 @@ module.exports = function draw(gd, id) {
// save for other callers to access this axis
component.axis = cbAxisOut;

if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
cbAxisOut.titleside = opts.titleside;
if(['top', 'bottom'].indexOf(opts.title.side) !== -1) {
cbAxisOut.title.side = opts.title.side;
cbAxisOut.titlex = opts.x + xpadFrac;
cbAxisOut.titley = yBottomFrac +
(opts.titleside === 'top' ? lenFrac - ypadFrac : ypadFrac);
(opts.title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
}

if(opts.line.color && opts.tickmode === 'auto') {
Expand Down Expand Up @@ -285,15 +284,15 @@ module.exports = function draw(gd, id) {
var axisLayer = container.select('.cbaxis');

var titleHeight = 0;
if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
if(['top', 'bottom'].indexOf(opts.title.side) !== -1) {
// draw the title so we know how much room it needs
// when we squish the axis. This one only applies to
// top or bottom titles, not right side.
var x = gs.l + (opts.x + xpadFrac) * gs.w,
fontSize = cbAxisOut.titlefont.size,
fontSize = cbAxisOut.title.font.size,
y;

if(opts.titleside === 'top') {
if(opts.title.side === 'top') {
y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h +
gs.t + 3 + fontSize * 0.75;
}
Expand All @@ -307,7 +306,7 @@ module.exports = function draw(gd, id) {
}

function drawAxis() {
if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
if(['top', 'bottom'].indexOf(opts.title.side) !== -1) {
// squish the axis top to make room for the title
var titleGroup = container.select('.cbtitle'),
titleText = titleGroup.select('text'),
Expand Down Expand Up @@ -338,7 +337,7 @@ module.exports = function draw(gd, id) {
// TODO: configurable
titleHeight += 5;

if(opts.titleside === 'top') {
if(opts.title.side === 'top') {
cbAxisOut.domain[1] -= titleHeight / gs.h;
titleTrans[1] *= -1;
}
Expand Down Expand Up @@ -459,8 +458,8 @@ module.exports = function draw(gd, id) {
});
},
function() {
if(['top', 'bottom'].indexOf(opts.titleside) === -1) {
var fontSize = cbAxisOut.titlefont.size,
if(['top', 'bottom'].indexOf(opts.title.side) === -1) {
var fontSize = cbAxisOut.title.font.size,
y = cbAxisOut._offset + cbAxisOut._length / 2,
x = gs.l + (cbAxisOut.position || 0) * gs.w + ((cbAxisOut.side === 'right') ?
10 + fontSize * ((cbAxisOut.showticklabels ? 1 : 0.5)) :
Expand All @@ -472,7 +471,7 @@ module.exports = function draw(gd, id) {
drawTitle('h' + cbAxisOut._id + 'title', {
avoid: {
selection: d3.select(gd).selectAll('g.' + cbAxisOut._id + 'tick'),
side: opts.titleside,
side: opts.title.side,
offsetLeft: gs.l,
offsetTop: 0,
maxShift: fullLayout.width
Expand Down Expand Up @@ -525,11 +524,11 @@ module.exports = function draw(gd, id) {
.node(),
titleWidth;
if(mathJaxNode &&
['top', 'bottom'].indexOf(opts.titleside) !== -1) {
['top', 'bottom'].indexOf(opts.title.side) !== -1) {
titleWidth = Drawing.bBox(mathJaxNode).width;
}
else {
// note: the formula below works for all titlesides,
// note: the formula below works for all title sides,
// (except for top/bottom mathjax, above)
// but the weird gs.l is because the titleunshift
// transform gets removed by Drawing.bBox
Expand Down Expand Up @@ -558,7 +557,7 @@ module.exports = function draw(gd, id) {
container.selectAll('.cboutline').attr({
x: xLeft,
y: yTopPx + opts.ypad +
(opts.titleside === 'top' ? titleHeight : 0),
(opts.title.side === 'top' ? titleHeight : 0),
width: Math.max(thickPx, 2),
height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2)
})
Expand Down
21 changes: 10 additions & 11 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ var FROM_BR = alignmentConstants.FROM_BR;
var getLegendData = require('./get_legend_data');
var style = require('./style');
var helpers = require('./helpers');
var anchorUtils = require('./anchor_utils');

var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY;

Expand Down Expand Up @@ -154,17 +153,17 @@ module.exports = function draw(gd) {
lx = gs.l + gs.w * opts.x,
ly = gs.t + gs.h * (1 - opts.y);

if(anchorUtils.isRightAnchor(opts)) {
if(Lib.isRightAnchor(opts)) {
lx -= opts._width;
}
else if(anchorUtils.isCenterAnchor(opts)) {
else if(Lib.isCenterAnchor(opts)) {
lx -= opts._width / 2;
}

if(anchorUtils.isBottomAnchor(opts)) {
if(Lib.isBottomAnchor(opts)) {
ly -= opts._height;
}
else if(anchorUtils.isMiddleAnchor(opts)) {
else if(Lib.isMiddleAnchor(opts)) {
ly -= opts._height / 2;
}

Expand Down Expand Up @@ -700,18 +699,18 @@ function expandMargin(gd) {
opts = fullLayout.legend;

var xanchor = 'left';
if(anchorUtils.isRightAnchor(opts)) {
if(Lib.isRightAnchor(opts)) {
xanchor = 'right';
}
else if(anchorUtils.isCenterAnchor(opts)) {
else if(Lib.isCenterAnchor(opts)) {
xanchor = 'center';
}

var yanchor = 'top';
if(anchorUtils.isBottomAnchor(opts)) {
if(Lib.isBottomAnchor(opts)) {
yanchor = 'bottom';
}
else if(anchorUtils.isMiddleAnchor(opts)) {
else if(Lib.isMiddleAnchor(opts)) {
yanchor = 'middle';
}

Expand All @@ -731,10 +730,10 @@ function expandHorizontalMargin(gd) {
opts = fullLayout.legend;

var xanchor = 'left';
if(anchorUtils.isRightAnchor(opts)) {
if(Lib.isRightAnchor(opts)) {
xanchor = 'right';
}
else if(anchorUtils.isCenterAnchor(opts)) {
else if(Lib.isCenterAnchor(opts)) {
xanchor = 'center';
}

Expand Down
9 changes: 4 additions & 5 deletions src/components/rangeselector/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ var Drawing = require('../drawing');
var Lib = require('../../lib');
var svgTextUtils = require('../../lib/svg_text_utils');
var axisIds = require('../../plots/cartesian/axis_ids');
var anchorUtils = require('../legend/anchor_utils');

var alignmentConstants = require('../../constants/alignment');
var LINE_SPACING = alignmentConstants.LINE_SPACING;
Expand Down Expand Up @@ -218,21 +217,21 @@ function reposition(gd, buttons, opts, axName, selector) {
var ly = graphSize.t + graphSize.h * (1 - opts.y);

var xanchor = 'left';
if(anchorUtils.isRightAnchor(opts)) {
if(Lib.isRightAnchor(opts)) {
lx -= width;
xanchor = 'right';
}
if(anchorUtils.isCenterAnchor(opts)) {
if(Lib.isCenterAnchor(opts)) {
lx -= width / 2;
xanchor = 'center';
}

var yanchor = 'top';
if(anchorUtils.isBottomAnchor(opts)) {
if(Lib.isBottomAnchor(opts)) {
ly -= height;
yanchor = 'bottom';
}
if(anchorUtils.isMiddleAnchor(opts)) {
if(Lib.isMiddleAnchor(opts)) {
ly -= height / 2;
yanchor = 'middle';
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/rangeslider/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ module.exports = function(gd) {
placeholder: fullLayout._dfltTitle.x,
attributes: {
x: axisOpts._offset + axisOpts._length / 2,
y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.titlefont.size,
y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.title.font.size,
'text-anchor': 'middle'
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/sliders/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ module.exports = overrideAll(templatedArray('slider', {
role: 'style',
description: 'Sets the x position (in normalized coordinates) of the slider.'
},
pad: extendDeepAll({}, padAttrs, {
pad: extendDeepAll(padAttrs({editType: 'arraydraw'}), {
description: 'Set the padding of the slider component along each side.'
}, {t: {dflt: 20}}),
xanchor: {
Expand Down
9 changes: 4 additions & 5 deletions src/components/sliders/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ var Color = require('../color');
var Drawing = require('../drawing');
var Lib = require('../../lib');
var svgTextUtils = require('../../lib/svg_text_utils');
var anchorUtils = require('../legend/anchor_utils');
var arrayEditor = require('../../plot_api/plot_template').arrayEditor;

var constants = require('./constants');
Expand Down Expand Up @@ -207,21 +206,21 @@ function findDimensions(gd, sliderOpts) {
dims.height = dims.currentValueTotalHeight + constants.tickOffset + sliderOpts.ticklen + constants.labelOffset + dims.labelHeight + sliderOpts.pad.t + sliderOpts.pad.b;

var xanchor = 'left';
if(anchorUtils.isRightAnchor(sliderOpts)) {
if(Lib.isRightAnchor(sliderOpts)) {
dims.lx -= dims.outerLength;
xanchor = 'right';
}
if(anchorUtils.isCenterAnchor(sliderOpts)) {
if(Lib.isCenterAnchor(sliderOpts)) {
dims.lx -= dims.outerLength / 2;
xanchor = 'center';
}

var yanchor = 'top';
if(anchorUtils.isBottomAnchor(sliderOpts)) {
if(Lib.isBottomAnchor(sliderOpts)) {
dims.ly -= dims.height;
yanchor = 'bottom';
}
if(anchorUtils.isMiddleAnchor(sliderOpts)) {
if(Lib.isMiddleAnchor(sliderOpts)) {
dims.ly -= dims.height / 2;
yanchor = 'middle';
}
Expand Down
16 changes: 9 additions & 7 deletions src/components/titles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,21 @@ function draw(gd, titleClass, options) {
var group = options.containerGroup;

var fullLayout = gd._fullLayout;
var titlefont = cont.titlefont || {};
var font = titlefont.family;
var fontSize = titlefont.size;
var fontColor = titlefont.color;

var opacity = 1;
var isplaceholder = false;
var txt = (cont.title || '').trim();
var title = cont.title;
var txt = (title && title.text ? title.text : '').trim();

var font = title && title.font ? title.font : {};
var fontFamily = font.family;
var fontSize = font.size;
var fontColor = font.color;

// only make this title editable if we positively identify its property
// as one that has editing enabled.
var editAttr;
if(prop === 'title') editAttr = 'titleText';
if(prop === 'title.text') editAttr = 'titleText';
else if(prop.indexOf('axis') !== -1) editAttr = 'axisTitleText';
else if(prop.indexOf('colorbar' !== -1)) editAttr = 'colorbarTitleText';
var editable = gd._context.edits[editAttr];
Expand Down Expand Up @@ -137,7 +139,7 @@ function draw(gd, titleClass, options) {
titleEl.attr('transform', transformVal);

titleEl.style({
'font-family': font,
'font-family': fontFamily,
'font-size': d3.round(fontSize, 2) + 'px',
fill: Color.rgb(fontColor),
opacity: opacity * Color.opacity(fontColor),
Expand Down
2 changes: 1 addition & 1 deletion src/components/updatemenus/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ module.exports = overrideAll(templatedArray('updatemenu', {
].join(' ')
},

pad: extendFlat({}, padAttrs, {
pad: extendFlat(padAttrs({editType: 'arraydraw'}), {
description: 'Sets the padding around the buttons or dropdown menu.'
}),

Expand Down
Loading