Skip to content

Commit a2f0543

Browse files
committed
Transition pie trace type to new title attr structure [882]
1 parent d600bbd commit a2f0543

File tree

7 files changed

+211
-85
lines changed

7 files changed

+211
-85
lines changed

src/plot_api/helpers.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,26 @@ function cleanTitle(titleContainer) {
245245
var oldFontAttrSet = Lib.isPlainObject(titleContainer.titlefont);
246246
var newFontAttrSet = titleContainer.title && Lib.isPlainObject(titleContainer.title.font);
247247
if(oldFontAttrSet && !newFontAttrSet) {
248-
if(!titleContainer.title) {
249-
titleContainer.title = {};
250-
}
248+
nestTitleAttr('titlefont', 'font');
249+
}
250+
251+
// titleposition -> title.position
252+
var oldPositionAttrSet = titleContainer.titleposition;
253+
var newPositionAttrSet = titleContainer.title && titleContainer.title.position;
254+
if(oldPositionAttrSet && !newPositionAttrSet) {
255+
nestTitleAttr('titleposition', 'position');
256+
}
257+
}
258+
259+
function nestTitleAttr(oldAttrName, newAttrName) {
251260

252-
titleContainer.title.font = titleContainer.titlefont;
253-
delete titleContainer.titlefont;
261+
// Ensure title object exists
262+
if(!titleContainer.title) {
263+
titleContainer.title = {};
254264
}
265+
266+
titleContainer.title[newAttrName] = titleContainer[oldAttrName];
267+
delete titleContainer[oldAttrName];
255268
}
256269
}
257270

@@ -458,6 +471,8 @@ exports.cleanData = function(data) {
458471
delete trace.autobiny;
459472
delete trace.ybins;
460473
}
474+
475+
cleanTitle(trace);
461476
}
462477
};
463478

src/plot_api/plot_api.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,8 +1405,11 @@ function _restyle(gd, aobj, traces) {
14051405
var fullLayout = gd._fullLayout,
14061406
fullData = gd._fullData,
14071407
data = gd.data,
1408+
eventData = Lib.extendDeepAll({}, aobj),
14081409
i;
14091410

1411+
cleanDeprecatedAttributeKeys(aobj);
1412+
14101413
// initialize flags
14111414
var flags = editTypes.traceFlags();
14121415

@@ -1691,49 +1694,45 @@ function _restyle(gd, aobj, traces) {
16911694
undoit: undoit,
16921695
redoit: redoit,
16931696
traces: traces,
1694-
eventData: Lib.extendDeepNoArrays([], [redoit, traces])
1697+
eventData: Lib.extendDeepNoArrays([], [eventData, traces])
16951698
};
16961699
}
16971700

16981701
/**
1699-
* Converts deprecated layout attributes and "string attributes" alike to
1702+
* Converts deprecated attribute keys to
17001703
* the current API to ensure backwards compatibility.
17011704
*
1702-
* This is needed for the relayout mechanism to determine which
1703-
* subroutines to run based on the actual layout attribute
1705+
* This is needed for the update mechanism to determine which
1706+
* subroutines to run based on the actual attribute
17041707
* definitions (that don't include the deprecated ones).
17051708
*
17061709
* E.g. Maps {'xaxis.title': 'A chart'} to {'xaxis.title.text': 'A chart'}
17071710
* and {titlefont: {...}} to {'title.font': {...}}.
17081711
*
1709-
* @param layoutObj
1712+
* @param aobj
17101713
*/
1711-
function cleanDeprecatedLayoutAttributes(layoutObj) {
1714+
function cleanDeprecatedAttributeKeys(aobj) {
17121715
var oldAxisTitleRegExp = Lib.counterRegex('axis', '\.title', false, false);
1713-
var keys, i, key, value;
1714-
1715-
if(typeof layoutObj.title === 'string') {
1716-
layoutObj.title = {text: layoutObj.title};
1717-
}
1716+
var keys = Object.keys(aobj);
1717+
var i, key, value;
17181718

1719-
keys = Object.keys(layoutObj);
17201719
for(i = 0; i < keys.length; i++) {
17211720
key = keys[i];
1722-
value = layoutObj[key];
1721+
value = aobj[key];
17231722

1724-
if(key.indexOf('titlefont') > -1) {
1725-
replace(key, key.replace('titlefont', 'title.font'));
1726-
}
1727-
1728-
if((typeof value === 'string' || typeof value === 'number') &&
1729-
oldAxisTitleRegExp.test(key)) {
1723+
if((key === 'title' || oldAxisTitleRegExp.test(key)) &&
1724+
(typeof value === 'string' || typeof value === 'number')) {
17301725
replace(key, key.replace('title', 'title.text'));
1726+
} else if(key.indexOf('titlefont') > -1) {
1727+
replace(key, key.replace('titlefont', 'title.font'));
1728+
} else if(key.indexOf('titleposition') > -1) {
1729+
replace(key, key.replace('titleposition', 'title.position'));
17311730
}
17321731
}
17331732

17341733
function replace(oldAttrStr, newAttrStr) {
1735-
layoutObj[newAttrStr] = layoutObj[oldAttrStr];
1736-
delete layoutObj[oldAttrStr];
1734+
aobj[newAttrStr] = aobj[oldAttrStr];
1735+
delete aobj[oldAttrStr];
17371736
}
17381737
}
17391738

@@ -1875,7 +1874,7 @@ function _relayout(gd, aobj) {
18751874
i,
18761875
j;
18771876

1878-
cleanDeprecatedLayoutAttributes(aobj);
1877+
cleanDeprecatedAttributeKeys(aobj);
18791878
keys = Object.keys(aobj);
18801879

18811880
// look for 'allaxes', split out into all axes

src/traces/pie/attributes.js

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -185,31 +185,44 @@ module.exports = {
185185
}),
186186

187187
title: {
188-
valType: 'string',
189-
dflt: '',
190-
role: 'info',
191-
editType: 'calc',
192-
description: [
193-
'Sets the title of the pie chart.',
194-
'If it is empty, no title is displayed.'
195-
].join(' ')
196-
},
197-
titleposition: {
198-
valType: 'enumerated',
199-
values: [
200-
'top left', 'top center', 'top right',
201-
'middle center',
202-
'bottom left', 'bottom center', 'bottom right'
203-
],
204-
role: 'info',
205-
editType: 'calc',
206-
description: [
207-
'Specifies the location of the `title`.',
208-
].join(' ')
188+
text: {
189+
valType: 'string',
190+
dflt: '',
191+
role: 'info',
192+
editType: 'calc',
193+
description: [
194+
'Sets the title of the pie chart.',
195+
'If it is empty, no title is displayed.',
196+
'Note that before the existence of `title.text`, the title\'s',
197+
'contents used to be defined as the `title` attribute itself.',
198+
'This behavior has been deprecated.'
199+
].join(' ')
200+
},
201+
font: extendFlat({}, textFontAttrs, {
202+
description: [
203+
'Sets the font used for `title`.',
204+
'Note that the title\'s font used to be set',
205+
'by the now deprecated `titlefont` attribute.'
206+
].join(' ')
207+
}),
208+
position: {
209+
valType: 'enumerated',
210+
values: [
211+
'top left', 'top center', 'top right',
212+
'middle center',
213+
'bottom left', 'bottom center', 'bottom right'
214+
],
215+
role: 'info',
216+
editType: 'calc',
217+
description: [
218+
'Specifies the location of the `title`.',
219+
'Note that the title\'s position used to be set',
220+
'by the now deprecated `titleposition` attribute.'
221+
].join(' ')
222+
},
223+
224+
editType: 'calc'
209225
},
210-
titlefont: extendFlat({}, textFontAttrs, {
211-
description: 'Sets the font used for `title`.'
212-
}),
213226

214227
// position and shape
215228
domain: domainAttrs({name: 'pie', trace: true, editType: 'calc'}),
@@ -283,5 +296,33 @@ module.exports = {
283296
'to pull all slices apart from each other equally',
284297
'or an array to highlight one or more slices.'
285298
].join(' ')
299+
},
300+
301+
_deprecated: {
302+
title: {
303+
valType: 'string',
304+
dflt: '',
305+
role: 'info',
306+
editType: 'calc',
307+
description: [
308+
'Deprecated in favor of `title.text`.',
309+
'Note that value of `title` is no longer a simple',
310+
'*string* but a set of sub-attributes.'
311+
].join(' ')
312+
},
313+
titlefont: extendFlat({}, textFontAttrs, {
314+
description: 'Deprecated in favor of `title.font`.'
315+
}),
316+
titleposition: {
317+
valType: 'enumerated',
318+
values: [
319+
'top left', 'top center', 'top right',
320+
'middle center',
321+
'bottom left', 'bottom center', 'bottom right'
322+
],
323+
role: 'info',
324+
editType: 'calc',
325+
description: 'Deprecated in favor of `title.position`.'
326+
}
286327
}
287328
};

src/traces/pie/defaults.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
7777
handleDomainDefaults(traceOut, layout, coerce);
7878

7979
var hole = coerce('hole');
80-
var title = coerce('title');
80+
var title = coerce('title.text');
8181
if(title) {
82-
var titlePosition = coerce('titleposition', hole ? 'middle center' : 'top center');
83-
if(!hole && titlePosition === 'middle center') traceOut.titleposition = 'top center';
84-
coerceFont(coerce, 'titlefont', layout.font);
82+
var titlePosition = coerce('title.position', hole ? 'middle center' : 'top center');
83+
if(!hole && titlePosition === 'middle center') traceOut.title.position = 'top center';
84+
coerceFont(coerce, 'title.font', layout.font);
8585
}
8686

8787
coerce('sort');

src/traces/pie/plot.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ module.exports = function plot(gd, cdpie) {
322322

323323
// add the title
324324
var titleTextGroup = d3.select(this).selectAll('g.titletext')
325-
.data(trace.title ? [0] : []);
325+
.data(trace.title.text ? [0] : []);
326326

327327
titleTextGroup.enter().append('g')
328328
.classed('titletext', true);
@@ -334,18 +334,18 @@ module.exports = function plot(gd, cdpie) {
334334
s.attr('data-notex', 1);
335335
});
336336

337-
titleText.text(trace.title)
337+
titleText.text(trace.title.text)
338338
.attr({
339339
'class': 'titletext',
340340
transform: '',
341341
'text-anchor': 'middle',
342342
})
343-
.call(Drawing.font, trace.titlefont)
343+
.call(Drawing.font, trace.title.font)
344344
.call(svgTextUtils.convertToTspans, gd);
345345

346346
var transform;
347347

348-
if(trace.titleposition === 'middle center') {
348+
if(trace.title.position === 'middle center') {
349349
transform = positionTitleInside(cd0);
350350
} else {
351351
transform = positionTitleOutside(cd0, fullLayout._size);
@@ -473,11 +473,11 @@ function prerenderTitles(cdpie, gd) {
473473
cd0 = cdpie[i][0];
474474
trace = cd0.trace;
475475

476-
if(trace.title) {
476+
if(trace.title.text) {
477477
var dummyTitle = Drawing.tester.append('text')
478478
.attr('data-notex', 1)
479-
.text(trace.title)
480-
.call(Drawing.font, trace.titlefont)
479+
.text(trace.title.text)
480+
.call(Drawing.font, trace.title.font)
481481
.call(svgTextUtils.convertToTspans, gd);
482482
var bBox = Drawing.bBox(dummyTitle.node(), true);
483483
cd0.titleBox = {
@@ -579,7 +579,7 @@ function positionTitleInside(cd0) {
579579
y: cd0.cy,
580580
scale: cd0.trace.hole * cd0.r * 2 / textDiameter,
581581
tx: 0,
582-
ty: - cd0.titleBox.height / 2 + cd0.trace.titlefont.size
582+
ty: - cd0.titleBox.height / 2 + cd0.trace.title.font.size
583583
};
584584
}
585585

@@ -602,25 +602,25 @@ function positionTitleOutside(cd0, plotSize) {
602602
// we reason below as if the baseline is the top middle point of the text box.
603603
// so we must add the font size to approximate the y-coord. of the top.
604604
// note that this correction must happen after scaling.
605-
translate.ty += trace.titlefont.size;
605+
translate.ty += trace.title.font.size;
606606
maxPull = getMaxPull(trace);
607607

608-
if(trace.titleposition.indexOf('top') !== -1) {
608+
if(trace.title.position.indexOf('top') !== -1) {
609609
topMiddle.y -= (1 + maxPull) * cd0.r;
610610
translate.ty -= cd0.titleBox.height;
611611
}
612-
else if(trace.titleposition.indexOf('bottom') !== -1) {
612+
else if(trace.title.position.indexOf('bottom') !== -1) {
613613
topMiddle.y += (1 + maxPull) * cd0.r;
614614
}
615615

616-
if(trace.titleposition.indexOf('left') !== -1) {
616+
if(trace.title.position.indexOf('left') !== -1) {
617617
// we start the text at the left edge of the pie
618618
maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2 + cd0.r;
619619
topMiddle.x -= (1 + maxPull) * cd0.r;
620620
translate.tx += cd0.titleBox.width / 2;
621-
} else if(trace.titleposition.indexOf('center') !== -1) {
621+
} else if(trace.title.position.indexOf('center') !== -1) {
622622
maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]);
623-
} else if(trace.titleposition.indexOf('right') !== -1) {
623+
} else if(trace.title.position.indexOf('right') !== -1) {
624624
maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2 + cd0.r;
625625
topMiddle.x += (1 + maxPull) * cd0.r;
626626
translate.tx -= cd0.titleBox.width / 2;
@@ -774,7 +774,7 @@ function scalePies(cdpie, plotSize) {
774774
pieBoxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]);
775775
pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]);
776776
// leave some space for the title, if it will be displayed outside
777-
if(trace.title && trace.titleposition !== 'middle center') {
777+
if(trace.title.text && trace.title.position !== 'middle center') {
778778
pieBoxHeight -= getTitleSpace(cd0, plotSize);
779779
}
780780

@@ -784,7 +784,7 @@ function scalePies(cdpie, plotSize) {
784784

785785
cd0.cx = plotSize.l + plotSize.w * (trace.domain.x[1] + trace.domain.x[0]) / 2;
786786
cd0.cy = plotSize.t + plotSize.h * (1 - trace.domain.y[0]) - pieBoxHeight / 2;
787-
if(trace.title && trace.titleposition.indexOf('bottom') !== -1) {
787+
if(trace.title.text && trace.title.position.indexOf('bottom') !== -1) {
788788
cd0.cy -= getTitleSpace(cd0, plotSize);
789789
}
790790

test/jasmine/tests/lib_test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,12 +2658,12 @@ describe('Queue', function() {
26582658
expect(gd.undoQueue.queue[0].undo.args[0][1]['marker.color']).toEqual([null]);
26592659
expect(gd.undoQueue.queue[0].redo.args[0][1]['marker.color']).toEqual('red');
26602660

2661-
return Plotly.relayout(gd, 'title', 'A title');
2661+
return Plotly.relayout(gd, 'title.text', 'A title');
26622662
})
26632663
.then(function() {
26642664
expect(gd.undoQueue.index).toEqual(2);
2665-
expect(gd.undoQueue.queue[1].undo.args[0][1].title).toEqual(null);
2666-
expect(gd.undoQueue.queue[1].redo.args[0][1].title.text).toEqual('A title');
2665+
expect(gd.undoQueue.queue[1].undo.args[0][1]['title.text']).toEqual(null);
2666+
expect(gd.undoQueue.queue[1].redo.args[0][1]['title.text']).toEqual('A title');
26672667

26682668
return Plotly.restyle(gd, 'mode', 'markers');
26692669
})
@@ -2674,8 +2674,8 @@ describe('Queue', function() {
26742674
expect(gd.undoQueue.queue[1].undo.args[0][1].mode).toEqual([null]);
26752675
expect(gd.undoQueue.queue[1].redo.args[0][1].mode).toEqual('markers');
26762676

2677-
expect(gd.undoQueue.queue[0].undo.args[0][1].title).toEqual(null);
2678-
expect(gd.undoQueue.queue[0].redo.args[0][1].title.text).toEqual('A title');
2677+
expect(gd.undoQueue.queue[0].undo.args[0][1]['title.text']).toEqual(null);
2678+
expect(gd.undoQueue.queue[0].redo.args[0][1]['title.text']).toEqual('A title');
26792679

26802680
return Plotly.restyle(gd, 'transforms[0]', { type: 'filter' });
26812681
})

0 commit comments

Comments
 (0)