Skip to content

Commit 7c95b4b

Browse files
committed
revise legend valType - pass validate test
1 parent df04d68 commit 7c95b4b

File tree

8 files changed

+249
-247
lines changed

8 files changed

+249
-247
lines changed

src/components/legend/attributes.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ var colorAttrs = require('../color/attributes');
55

66

77
module.exports = {
8+
// not really a 'subplot' attribute container,
9+
// but this is the flag we use to denote attributes that
10+
// support yaxis, yaxis2, yaxis3, ... counters
11+
_isSubplotObj: true,
12+
813
bgcolor: {
914
valType: 'color',
1015
editType: 'legend',

src/components/legend/defaults.js

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,9 @@ var attributes = require('./attributes');
99
var basePlotLayoutAttributes = require('../../plots/layout_attributes');
1010
var helpers = require('./helpers');
1111

12-
function getLegendName(id) {
13-
return 'legend' + (id > 1 ? id : '');
14-
}
15-
16-
function groupDefaults(id, layoutIn, layoutOut, fullData) {
17-
var name = getLegendName(id);
18-
var containerIn = layoutIn[name] || {};
19-
var containerOut = Template.newContainer(layoutOut, name);
12+
function groupDefaults(legendId, layoutIn, layoutOut, fullData) {
13+
var containerIn = layoutIn[legendId] || {};
14+
var containerOut = Template.newContainer(layoutOut, legendId);
2015

2116
function coerce(attr, dflt) {
2217
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
@@ -157,24 +152,22 @@ function groupDefaults(id, layoutIn, layoutOut, fullData) {
157152

158153
module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
159154
var i;
160-
var legends = [1];
155+
var legends = ['legend'];
161156

162157
for(i = 0; i < fullData.length; i++) {
163158
Lib.pushUnique(legends, fullData[i].legend);
164159
}
165160

166161
layoutOut._legends = [];
167162
for(i = 0; i < legends.length; i++) {
168-
var id = legends[i];
169-
var name = getLegendName(id);
170-
if(id > 1 && !layoutIn[name]) continue;
163+
var legendId = legends[i];
171164

172-
groupDefaults(id, layoutIn, layoutOut, fullData);
165+
groupDefaults(legendId, layoutIn, layoutOut, fullData);
173166

174-
if(layoutOut[name]) {
175-
layoutOut[name]._id = id;
167+
if(layoutOut[legendId]) {
168+
layoutOut[legendId]._id = legendId;
176169
}
177170

178-
layoutOut._legends.push(id);
171+
layoutOut._legends.push(legendId);
179172
}
180173
};

src/components/legend/draw.js

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ module.exports = function draw(gd, opts) {
3030
} else {
3131
var legends = gd._fullLayout._legends;
3232
for(var i = 0; i < legends.length; i++) {
33-
var id = legends[i];
34-
var legendObj = gd._fullLayout['legend' + (id > 1 ? id : '')];
33+
var legendId = legends[i];
34+
var legendObj = gd._fullLayout[legendId];
3535
drawOne(gd, legendObj);
3636
}
3737
}
@@ -41,7 +41,7 @@ function drawOne(gd, opts) {
4141
var legendObj = opts || {};
4242

4343
var fullLayout = gd._fullLayout;
44-
var id = getId(legendObj);
44+
var legendId = getId(legendObj);
4545

4646
var clipId, layer;
4747

@@ -51,7 +51,7 @@ function drawOne(gd, opts) {
5151
clipId = 'hover';
5252
} else {
5353
layer = fullLayout._infolayer;
54-
clipId = 'legend' + id;
54+
clipId = legendId;
5555
}
5656
if(!layer) return;
5757
clipId += fullLayout._uid;
@@ -70,12 +70,12 @@ function drawOne(gd, opts) {
7070
var hiddenSlices = fullLayout.hiddenlabels || [];
7171

7272
if(!inHover && (!fullLayout.showlegend || !legendData.length)) {
73-
layer.selectAll('.legend' + id).remove();
73+
layer.selectAll('.' + legendId).remove();
7474
fullLayout._topdefs.select('#' + clipId).remove();
75-
return Plots.autoMargin(gd, 'legend' + id);
75+
return Plots.autoMargin(gd, legendId);
7676
}
7777

78-
var legend = Lib.ensureSingle(layer, 'g', 'legend' + id, function(s) {
78+
var legend = Lib.ensureSingle(layer, 'g', legendId, function(s) {
7979
if(!inHover) s.attr('pointer-events', 'all');
8080
});
8181

@@ -96,14 +96,14 @@ function drawOne(gd, opts) {
9696
legendObj._titleWidth = 0;
9797
legendObj._titleHeight = 0;
9898
if(title.text) {
99-
var titleEl = Lib.ensureSingle(scrollBox, 'text', 'legend' + id + 'titletext');
99+
var titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext');
100100
titleEl.attr('text-anchor', 'start')
101101
.call(Drawing.font, title.font)
102102
.text(title.text);
103103

104104
textLayout(titleEl, scrollBox, gd, legendObj, MAIN_TITLE); // handle mathjax or multi-line text and compute title height
105105
} else {
106-
scrollBox.selectAll('.legend' + id + 'titletext').remove();
106+
scrollBox.selectAll('.' + legendId + 'titletext').remove();
107107
}
108108

109109
var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) {
@@ -129,7 +129,7 @@ function drawOne(gd, opts) {
129129
})
130130
.each(function() { d3.select(this).call(drawTexts, gd, legendObj); })
131131
.call(style, gd, legendObj)
132-
.each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd, id); });
132+
.each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd, legendId); });
133133

134134
Lib.syncOrAsync([
135135
Plots.previousPromises,
@@ -139,7 +139,7 @@ function drawOne(gd, opts) {
139139
var bw = legendObj.borderwidth;
140140

141141
if(!inHover) {
142-
var expMargin = expandMargin(gd, id);
142+
var expMargin = expandMargin(gd, legendId);
143143

144144
// IF expandMargin return a Promise (which is truthy),
145145
// we're under a doAutoMargin redraw, so we don't have to
@@ -157,10 +157,10 @@ function drawOne(gd, opts) {
157157
ly = Lib.constrain(ly, 0, fullLayout.height - legendObj._effHeight);
158158

159159
if(lx !== lx0) {
160-
Lib.log('Constrain legend' + id + '.x to make legend fit inside graph');
160+
Lib.log('Constrain ' + legendId + '.x to make legend fit inside graph');
161161
}
162162
if(ly !== ly0) {
163-
Lib.log('Constrain legend' + id + '.y to make legend fit inside graph');
163+
Lib.log('Constrain ' + legendId + '.y to make legend fit inside graph');
164164
}
165165
}
166166

@@ -306,7 +306,7 @@ function drawOne(gd, opts) {
306306
}
307307

308308
function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) {
309-
legendObj._scrollY = gd._fullLayout['legend' + id]._scrollY = scrollBoxY;
309+
legendObj._scrollY = gd._fullLayout[legendId]._scrollY = scrollBoxY;
310310
Drawing.setTranslate(scrollBox, 0, -scrollBoxY);
311311

312312
Drawing.setRect(
@@ -343,8 +343,8 @@ function drawOne(gd, opts) {
343343
doneFn: function() {
344344
if(xf !== undefined && yf !== undefined) {
345345
var obj = {};
346-
obj['legend' + id + '.x'] = xf;
347-
obj['legend' + id + '.y'] = yf;
346+
obj[legendId + '.x'] = xf;
347+
obj[legendId + '.y'] = yf;
348348
Registry.call('_guiRelayout', gd, obj);
349349
}
350350
},
@@ -417,7 +417,7 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) {
417417
}
418418

419419
function drawTexts(g, gd, legendObj) {
420-
var id = getId(legendObj);
420+
var legendId = getId(legendObj);
421421
var legendItem = g.data()[0][0];
422422
var trace = legendItem.trace;
423423
var isPieLike = Registry.traceIs(trace, 'pie-like');
@@ -440,7 +440,7 @@ function drawTexts(g, gd, legendObj) {
440440
}
441441
}
442442

443-
var textEl = Lib.ensureSingle(g, 'text', 'legend' + id + 'text');
443+
var textEl = Lib.ensureSingle(g, 'text', legendId + 'text');
444444

445445
textEl.attr('text-anchor', 'start')
446446
.call(Drawing.font, font)
@@ -494,12 +494,12 @@ function ensureLength(str, maxLength) {
494494
return str;
495495
}
496496

497-
function setupTraceToggle(g, gd, id) {
497+
function setupTraceToggle(g, gd, legendId) {
498498
var doubleClickDelay = gd._context.doubleClickDelay;
499499
var newMouseDownTime;
500500
var numClicks = 1;
501501

502-
var traceToggle = Lib.ensureSingle(g, 'rect', 'legend' + id + 'toggle', function(s) {
502+
var traceToggle = Lib.ensureSingle(g, 'rect', legendId + 'toggle', function(s) {
503503
if(!gd._context.staticPlot) {
504504
s.style('cursor', 'pointer').attr('pointer-events', 'all');
505505
}
@@ -521,7 +521,7 @@ function setupTraceToggle(g, gd, id) {
521521
});
522522
traceToggle.on('mouseup', function() {
523523
if(gd._dragged || gd._editing) return;
524-
var legend = gd._fullLayout['legend' + id];
524+
var legend = gd._fullLayout[legendId];
525525

526526
if((new Date()).getTime() - gd._legendMouseDownTime > doubleClickDelay) {
527527
numClicks = Math.max(numClicks - 1, 1);
@@ -548,9 +548,9 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
548548
var mathjaxGroup = g.select('g[class*=math-group]');
549549
var mathjaxNode = mathjaxGroup.node();
550550

551-
var id = getId(legendObj);
551+
var legendId = getId(legendObj);
552552
if(!legendObj) {
553-
legendObj = gd._fullLayout['legend' + id];
553+
legendObj = gd._fullLayout[legendId];
554554
}
555555
var bw = legendObj.borderwidth;
556556
var font;
@@ -576,7 +576,7 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
576576
Drawing.setTranslate(mathjaxGroup, 0, height * 0.25);
577577
}
578578
} else {
579-
var cls = '.legend' + id + (
579+
var cls = '.' + legendId + (
580580
aTitle === MAIN_TITLE ? 'title' : ''
581581
) + 'text';
582582

@@ -642,7 +642,7 @@ function getTitleSize(legendObj) {
642642
}
643643

644644
/*
645-
* Computes in fullLayout['legend' + id]:
645+
* Computes in fullLayout[legendId]:
646646
*
647647
* - _height: legend height including items past scrollbox height
648648
* - _maxHeight: maximum legend height before scrollbox is required
@@ -653,9 +653,9 @@ function getTitleSize(legendObj) {
653653
*/
654654
function computeLegendDimensions(gd, groups, traces, legendObj) {
655655
var fullLayout = gd._fullLayout;
656-
var id = getId(legendObj);
656+
var legendId = getId(legendObj);
657657
if(!legendObj) {
658-
legendObj = fullLayout['legend' + id];
658+
legendObj = fullLayout[legendId];
659659
}
660660
var gs = fullLayout._size;
661661

@@ -844,7 +844,7 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
844844
var edits = gd._context.edits;
845845
var isEditable = edits.legendText || edits.legendPosition;
846846
traces.each(function(d) {
847-
var traceToggle = d3.select(this).select('.legend' + id + 'toggle');
847+
var traceToggle = d3.select(this).select('.' + legendId + 'toggle');
848848
var h = d[0].height;
849849
var legendgroup = d[0].trace.legendgroup;
850850
var traceWidth = getTraceWidth(d, legendObj, textGap);
@@ -859,13 +859,13 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
859859
});
860860
}
861861

862-
function expandMargin(gd, id) {
862+
function expandMargin(gd, legendId) {
863863
var fullLayout = gd._fullLayout;
864-
var legendObj = fullLayout['legend' + id];
864+
var legendObj = fullLayout[legendId];
865865
var xanchor = getXanchor(legendObj);
866866
var yanchor = getYanchor(legendObj);
867867

868-
return Plots.autoMargin(gd, 'legend' + id, {
868+
return Plots.autoMargin(gd, legendId, {
869869
x: legendObj.x,
870870
y: legendObj.y,
871871
l: legendObj._width * (FROM_TL[xanchor]),
@@ -888,6 +888,5 @@ function getYanchor(legendObj) {
888888
}
889889

890890
function getId(legendObj) {
891-
var id = legendObj._id;
892-
return id > 1 ? id : '';
891+
return legendObj._id || 'legend';
893892
}

src/plots/attributes.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
var fontAttrs = require('./font_attributes');
44
var fxAttrs = require('../components/fx/attributes');
5+
var counterRegex = require('../lib/regex').counter;
56

67
module.exports = {
78
type: {
@@ -33,14 +34,15 @@ module.exports = {
3334
].join(' ')
3435
},
3536
legend: {
36-
valType: 'number',
37-
dflt: 1,
38-
min: 1,
37+
valType: 'subplotid',
38+
dflt: 'legend',
3939
editType: 'style',
40+
regex: counterRegex('legend'),
4041
description: [
41-
'Sets the legend id to show this trace in.',
42-
'If *1* (the default value), it refers to `layout.legend`.',
43-
'If *2*, it refers to `layout.legend2`, and so on.'
42+
'Sets the reference to a legend to show this trace in.',
43+
'References to these legends are *legend*, *legend2*, *legend3*, etc.',
44+
'Settings for these legends are set in the layout, under',
45+
'`layout.legend`, `layout.legend2`, etc.'
4446
].join(' ')
4547
},
4648
legendgroup: {

tasks/test_mock.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ function assert(name, v) {
6161
var condition = (
6262
e.code === 'invisible' ||
6363
e.code === 'dynamic' ||
64+
e.path[e.path.length - 1] === 'legend' ||
6465
e.path[e.path.length - 1] === 'coloraxis'
6566
);
66-
expectToBe(condition, true); // we accept invisible, dynamic and coloraxis for now
67+
expectToBe(condition, true); // we accept invisible, dynamic, legend and coloraxis for now
6768
if(!condition) {
6869
console.log('file:', name);
6970
console.log(JSON.stringify(v, null, 2));

test/image/mocks/zz-multi-legends.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
},
1212
{
1313
"y": [3],
14-
"legend": 2
14+
"legend": "legend2"
1515
},
1616
{
1717
"y": [4],
18-
"legend": 3
18+
"legend": "legend3"
1919
},
2020
{
2121
"y": [5],
22-
"legend": 3
22+
"legend": "legend3"
2323
}
2424
],
2525
"layout": {

test/jasmine/bundle_tests/plotschema_test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ describe('plot schema', function() {
138138
// not really a 'subplot' object but supports yaxis, yaxis2, yaxis3,
139139
// ... counters, so list it here
140140
'xaxis.rangeslider.yaxis',
141+
'legend',
141142
'coloraxis'
142143
];
143144

0 commit comments

Comments
 (0)