Skip to content

Commit db66ff1

Browse files
authored
Merge pull request #3276 from plotly/882-chart-title-alignment
882 - Chart Title Alignment
2 parents e930009 + 2b26746 commit db66ff1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2121
-344
lines changed

src/components/colorbar/attributes.js

+50-15
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,56 @@ module.exports = overrideAll({
175175
exponentformat: axesAttrs.exponentformat,
176176
showexponent: axesAttrs.showexponent,
177177
title: {
178-
valType: 'string',
179-
role: 'info',
180-
description: 'Sets the title of the color bar.'
178+
text: {
179+
valType: 'string',
180+
role: 'info',
181+
description: [
182+
'Sets the title of the color bar.',
183+
'Note that before the existence of `title.text`, the title\'s',
184+
'contents used to be defined as the `title` attribute itself.',
185+
'This behavior has been deprecated.'
186+
].join(' ')
187+
},
188+
font: fontAttrs({
189+
description: [
190+
'Sets this color bar\'s title font.',
191+
'Note that the title\'s font used to be set',
192+
'by the now deprecated `titlefont` attribute.'
193+
].join(' ')
194+
}),
195+
side: {
196+
valType: 'enumerated',
197+
values: ['right', 'top', 'bottom'],
198+
role: 'style',
199+
dflt: 'top',
200+
description: [
201+
'Determines the location of color bar\'s title',
202+
'with respect to the color bar.',
203+
'Note that the title\'s location used to be set',
204+
'by the now deprecated `titleside` attribute.'
205+
].join(' ')
206+
}
181207
},
182-
titlefont: fontAttrs({
183-
description: 'Sets this color bar\'s title font.'
184-
}),
185-
titleside: {
186-
valType: 'enumerated',
187-
values: ['right', 'top', 'bottom'],
188-
role: 'style',
189-
dflt: 'top',
190-
description: [
191-
'Determines the location of the colorbar title',
192-
'with respect to the color bar.'
193-
].join(' ')
208+
209+
_deprecated: {
210+
title: {
211+
valType: 'string',
212+
role: 'info',
213+
description: [
214+
'Deprecated in favor of color bar\'s `title.text`.',
215+
'Note that value of color bar\'s `title` is no longer a simple',
216+
'*string* but a set of sub-attributes.'
217+
].join(' ')
218+
},
219+
titlefont: fontAttrs({
220+
description: 'Deprecated in favor of color bar\'s `title.font`.'
221+
}),
222+
titleside: {
223+
valType: 'enumerated',
224+
values: ['right', 'top', 'bottom'],
225+
role: 'style',
226+
dflt: 'top',
227+
description: 'Deprecated in favor of color bar\'s `title.side`.'
228+
}
194229
}
195230
}, 'colorbars', 'from-root');

src/components/colorbar/defaults.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
5959
handleTickLabelDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts);
6060
handleTickMarkDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts);
6161

62-
coerce('title', layout._dfltTitle.colorbar);
63-
Lib.coerceFont(coerce, 'titlefont', layout.font);
64-
coerce('titleside');
62+
coerce('title.text', layout._dfltTitle.colorbar);
63+
Lib.coerceFont(coerce, 'title.font', layout.font);
64+
coerce('title.side');
6565
};

src/components/colorbar/draw.js

+14-15
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ module.exports = function draw(gd, id) {
184184
showticksuffix: opts.showticksuffix,
185185
ticksuffix: opts.ticksuffix,
186186
title: opts.title,
187-
titlefont: opts.titlefont,
188187
showline: true,
189188
anchor: 'free',
190189
side: 'right',
@@ -219,11 +218,11 @@ module.exports = function draw(gd, id) {
219218
// save for other callers to access this axis
220219
component.axis = cbAxisOut;
221220

222-
if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
223-
cbAxisOut.titleside = opts.titleside;
221+
if(['top', 'bottom'].indexOf(opts.title.side) !== -1) {
222+
cbAxisOut.title.side = opts.title.side;
224223
cbAxisOut.titlex = opts.x + xpadFrac;
225224
cbAxisOut.titley = yBottomFrac +
226-
(opts.titleside === 'top' ? lenFrac - ypadFrac : ypadFrac);
225+
(opts.title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
227226
}
228227

229228
if(opts.line.color && opts.tickmode === 'auto') {
@@ -286,15 +285,15 @@ module.exports = function draw(gd, id) {
286285
var axisLayer = container.select('.cbaxis');
287286

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

297-
if(opts.titleside === 'top') {
296+
if(opts.title.side === 'top') {
298297
y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h +
299298
gs.t + 3 + fontSize * 0.75;
300299
}
@@ -308,7 +307,7 @@ module.exports = function draw(gd, id) {
308307
}
309308

310309
function drawAxis() {
311-
if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
310+
if(['top', 'bottom'].indexOf(opts.title.side) !== -1) {
312311
// squish the axis top to make room for the title
313312
var titleGroup = container.select('.cbtitle'),
314313
titleText = titleGroup.select('text'),
@@ -339,7 +338,7 @@ module.exports = function draw(gd, id) {
339338
// TODO: configurable
340339
titleHeight += 5;
341340

342-
if(opts.titleside === 'top') {
341+
if(opts.title.side === 'top') {
343342
cbAxisOut.domain[1] -= titleHeight / gs.h;
344343
titleTrans[1] *= -1;
345344
}
@@ -460,8 +459,8 @@ module.exports = function draw(gd, id) {
460459
});
461460
},
462461
function() {
463-
if(['top', 'bottom'].indexOf(opts.titleside) === -1) {
464-
var fontSize = cbAxisOut.titlefont.size,
462+
if(['top', 'bottom'].indexOf(opts.title.side) === -1) {
463+
var fontSize = cbAxisOut.title.font.size,
465464
y = cbAxisOut._offset + cbAxisOut._length / 2,
466465
x = gs.l + (cbAxisOut.position || 0) * gs.w + ((cbAxisOut.side === 'right') ?
467466
10 + fontSize * ((cbAxisOut.showticklabels ? 1 : 0.5)) :
@@ -473,7 +472,7 @@ module.exports = function draw(gd, id) {
473472
drawTitle('h' + cbAxisOut._id + 'title', {
474473
avoid: {
475474
selection: d3.select(gd).selectAll('g.' + cbAxisOut._id + 'tick'),
476-
side: opts.titleside,
475+
side: opts.title.side,
477476
offsetLeft: gs.l,
478477
offsetTop: 0,
479478
maxShift: fullLayout.width
@@ -526,11 +525,11 @@ module.exports = function draw(gd, id) {
526525
.node(),
527526
titleWidth;
528527
if(mathJaxNode &&
529-
['top', 'bottom'].indexOf(opts.titleside) !== -1) {
528+
['top', 'bottom'].indexOf(opts.title.side) !== -1) {
530529
titleWidth = Drawing.bBox(mathJaxNode).width;
531530
}
532531
else {
533-
// note: the formula below works for all titlesides,
532+
// note: the formula below works for all title sides,
534533
// (except for top/bottom mathjax, above)
535534
// but the weird gs.l is because the titleunshift
536535
// transform gets removed by Drawing.bBox
@@ -559,7 +558,7 @@ module.exports = function draw(gd, id) {
559558
container.selectAll('.cboutline').attr({
560559
x: xLeft,
561560
y: yTopPx + opts.ypad +
562-
(opts.titleside === 'top' ? titleHeight : 0),
561+
(opts.title.side === 'top' ? titleHeight : 0),
563562
width: Math.max(thickPx, 2),
564563
height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2)
565564
})

src/components/legend/draw.js

+10-11
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ var FROM_BR = alignmentConstants.FROM_BR;
3030
var getLegendData = require('./get_legend_data');
3131
var style = require('./style');
3232
var helpers = require('./helpers');
33-
var anchorUtils = require('./anchor_utils');
3433

3534
var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY;
3635

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

157-
if(anchorUtils.isRightAnchor(opts)) {
156+
if(Lib.isRightAnchor(opts)) {
158157
lx -= opts._width;
159158
}
160-
else if(anchorUtils.isCenterAnchor(opts)) {
159+
else if(Lib.isCenterAnchor(opts)) {
161160
lx -= opts._width / 2;
162161
}
163162

164-
if(anchorUtils.isBottomAnchor(opts)) {
163+
if(Lib.isBottomAnchor(opts)) {
165164
ly -= opts._height;
166165
}
167-
else if(anchorUtils.isMiddleAnchor(opts)) {
166+
else if(Lib.isMiddleAnchor(opts)) {
168167
ly -= opts._height / 2;
169168
}
170169

@@ -700,18 +699,18 @@ function expandMargin(gd) {
700699
opts = fullLayout.legend;
701700

702701
var xanchor = 'left';
703-
if(anchorUtils.isRightAnchor(opts)) {
702+
if(Lib.isRightAnchor(opts)) {
704703
xanchor = 'right';
705704
}
706-
else if(anchorUtils.isCenterAnchor(opts)) {
705+
else if(Lib.isCenterAnchor(opts)) {
707706
xanchor = 'center';
708707
}
709708

710709
var yanchor = 'top';
711-
if(anchorUtils.isBottomAnchor(opts)) {
710+
if(Lib.isBottomAnchor(opts)) {
712711
yanchor = 'bottom';
713712
}
714-
else if(anchorUtils.isMiddleAnchor(opts)) {
713+
else if(Lib.isMiddleAnchor(opts)) {
715714
yanchor = 'middle';
716715
}
717716

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

733732
var xanchor = 'left';
734-
if(anchorUtils.isRightAnchor(opts)) {
733+
if(Lib.isRightAnchor(opts)) {
735734
xanchor = 'right';
736735
}
737-
else if(anchorUtils.isCenterAnchor(opts)) {
736+
else if(Lib.isCenterAnchor(opts)) {
738737
xanchor = 'center';
739738
}
740739

src/components/rangeselector/draw.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ var Drawing = require('../drawing');
1717
var Lib = require('../../lib');
1818
var svgTextUtils = require('../../lib/svg_text_utils');
1919
var axisIds = require('../../plots/cartesian/axis_ids');
20-
var anchorUtils = require('../legend/anchor_utils');
2120

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

220219
var xanchor = 'left';
221-
if(anchorUtils.isRightAnchor(opts)) {
220+
if(Lib.isRightAnchor(opts)) {
222221
lx -= width;
223222
xanchor = 'right';
224223
}
225-
if(anchorUtils.isCenterAnchor(opts)) {
224+
if(Lib.isCenterAnchor(opts)) {
226225
lx -= width / 2;
227226
xanchor = 'center';
228227
}
229228

230229
var yanchor = 'top';
231-
if(anchorUtils.isBottomAnchor(opts)) {
230+
if(Lib.isBottomAnchor(opts)) {
232231
ly -= height;
233232
yanchor = 'bottom';
234233
}
235-
if(anchorUtils.isMiddleAnchor(opts)) {
234+
if(Lib.isMiddleAnchor(opts)) {
236235
ly -= height / 2;
237236
yanchor = 'middle';
238237
}

src/components/rangeslider/draw.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ module.exports = function(gd) {
172172
placeholder: fullLayout._dfltTitle.x,
173173
attributes: {
174174
x: axisOpts._offset + axisOpts._length / 2,
175-
y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.titlefont.size,
175+
y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.title.font.size,
176176
'text-anchor': 'middle'
177177
}
178178
});

src/components/sliders/attributes.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ module.exports = overrideAll(templatedArray('slider', {
133133
role: 'style',
134134
description: 'Sets the x position (in normalized coordinates) of the slider.'
135135
},
136-
pad: extendDeepAll({}, padAttrs, {
136+
pad: extendDeepAll(padAttrs({editType: 'arraydraw'}), {
137137
description: 'Set the padding of the slider component along each side.'
138138
}, {t: {dflt: 20}}),
139139
xanchor: {

src/components/sliders/draw.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ var Color = require('../color');
1515
var Drawing = require('../drawing');
1616
var Lib = require('../../lib');
1717
var svgTextUtils = require('../../lib/svg_text_utils');
18-
var anchorUtils = require('../legend/anchor_utils');
1918
var arrayEditor = require('../../plot_api/plot_template').arrayEditor;
2019

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

209208
var xanchor = 'left';
210-
if(anchorUtils.isRightAnchor(sliderOpts)) {
209+
if(Lib.isRightAnchor(sliderOpts)) {
211210
dims.lx -= dims.outerLength;
212211
xanchor = 'right';
213212
}
214-
if(anchorUtils.isCenterAnchor(sliderOpts)) {
213+
if(Lib.isCenterAnchor(sliderOpts)) {
215214
dims.lx -= dims.outerLength / 2;
216215
xanchor = 'center';
217216
}
218217

219218
var yanchor = 'top';
220-
if(anchorUtils.isBottomAnchor(sliderOpts)) {
219+
if(Lib.isBottomAnchor(sliderOpts)) {
221220
dims.ly -= dims.height;
222221
yanchor = 'bottom';
223222
}
224-
if(anchorUtils.isMiddleAnchor(sliderOpts)) {
223+
if(Lib.isMiddleAnchor(sliderOpts)) {
225224
dims.ly -= dims.height / 2;
226225
yanchor = 'middle';
227226
}

src/components/titles/index.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,21 @@ function draw(gd, titleClass, options) {
6767
var group = options.containerGroup;
6868

6969
var fullLayout = gd._fullLayout;
70-
var titlefont = cont.titlefont || {};
71-
var font = titlefont.family;
72-
var fontSize = titlefont.size;
73-
var fontColor = titlefont.color;
7470

7571
var opacity = 1;
7672
var isplaceholder = false;
77-
var txt = (cont.title || '').trim();
73+
var title = cont.title;
74+
var txt = (title && title.text ? title.text : '').trim();
75+
76+
var font = title && title.font ? title.font : {};
77+
var fontFamily = font.family;
78+
var fontSize = font.size;
79+
var fontColor = font.color;
7880

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

139141
titleEl.style({
140-
'font-family': font,
142+
'font-family': fontFamily,
141143
'font-size': d3.round(fontSize, 2) + 'px',
142144
fill: Color.rgb(fontColor),
143145
opacity: opacity * Color.opacity(fontColor),

src/components/updatemenus/attributes.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ module.exports = overrideAll(templatedArray('updatemenu', {
162162
].join(' ')
163163
},
164164

165-
pad: extendFlat({}, padAttrs, {
165+
pad: extendFlat(padAttrs({editType: 'arraydraw'}), {
166166
description: 'Sets the padding around the buttons or dropdown menu.'
167167
}),
168168

0 commit comments

Comments
 (0)