From d8629ceed3460e884d0f8908cf686d4787879839 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 11:05:58 -0400 Subject: [PATCH 01/15] add multiple legends to layout based on legendgroup --- src/components/legend/defaults.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index a2bfc776848..348cc9d444c 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -9,10 +9,10 @@ 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 groupDefaults(legendGroup, layoutIn, layoutOut, fullData) { + var name = 'legend' + legendGroup; + var containerIn = layoutIn[name] || {}; + var containerOut = Template.newContainer(layoutOut, name); function coerce(attr, dflt) { return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); @@ -147,4 +147,20 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { Lib.coerceFont(coerce, 'title.font', dfltTitleFont); } +} + +module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { + var i; + var groups = ['']; + + for(i = 0; i < fullData.length; i++) { + Lib.pushUnique(groups, fullData[i].legendgroup); + } + + for(i = 0; i < groups.length; i++) { + var groupName = groups[i]; + groupDefaults(groupName, layoutIn, layoutOut, fullData); + + layoutOut['legend' + groupName]._id = groupName; + } }; From d6573f33e80a4a334bc5258d04a807fa9e1e838a Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 11:14:59 -0400 Subject: [PATCH 02/15] revisit legend and unified hover draw --- src/components/legend/draw.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 9f000a6c26c..c8afa831ed5 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -31,18 +31,18 @@ module.exports = function draw(gd, opts) { function _draw(gd, legendObj) { var fullLayout = gd._fullLayout; - var clipId = 'legend' + fullLayout._uid; - var layer; + var clipId, layer; var inHover = legendObj._inHover; if(inHover) { layer = legendObj.layer; - clipId += '-hover'; + clipId = 'hover'; } else { layer = fullLayout._infolayer; + clipId = 'legend'; } - if(!layer) return; + clipId += fullLayout._uid; if(!gd._legendMouseDownTime) gd._legendMouseDownTime = 0; From 3aeeceddc9380a69861a29990ff7f454a1c4edc1 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 11:37:30 -0400 Subject: [PATCH 03/15] simplify legend draw - no need to return --- src/components/legend/draw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index c8afa831ed5..135626e934d 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -26,7 +26,7 @@ var MAIN_TITLE = 1; module.exports = function draw(gd, opts) { if(!opts) opts = gd._fullLayout.legend || {}; - return _draw(gd, opts); + _draw(gd, opts); }; function _draw(gd, legendObj) { From 9101d7a9a73f3659af0e06812bfa3f4c1518f5af Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 11:38:57 -0400 Subject: [PATCH 04/15] rename _draw to drawOne --- src/components/legend/draw.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 135626e934d..40de85e20cd 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -26,10 +26,10 @@ var MAIN_TITLE = 1; module.exports = function draw(gd, opts) { if(!opts) opts = gd._fullLayout.legend || {}; - _draw(gd, opts); + drawOne(gd, opts); }; -function _draw(gd, legendObj) { +function drawOne(gd, legendObj) { var fullLayout = gd._fullLayout; var clipId, layer; From afbcb18394666bd456724581b7ffbcc4b4e7d08a Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 11:42:33 -0400 Subject: [PATCH 05/15] revisit drawOne arguments --- src/components/legend/draw.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 40de85e20cd..b65db34eead 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -25,11 +25,12 @@ var helpers = require('./helpers'); var MAIN_TITLE = 1; module.exports = function draw(gd, opts) { - if(!opts) opts = gd._fullLayout.legend || {}; - drawOne(gd, opts); + drawOne(gd, opts || gd._fullLayout.legend); }; -function drawOne(gd, legendObj) { +function drawOne(gd, opts) { + var legendObj = opts || {}; + var fullLayout = gd._fullLayout; var clipId, layer; From 8630ad7055db38f1c0592ea79ad7d972633af26a Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 21 Mar 2023 12:10:59 -0400 Subject: [PATCH 06/15] draw multiple legends --- src/components/legend/defaults.js | 24 ++++-- src/components/legend/draw.js | 85 ++++++++++++++-------- src/components/legend/get_legend_data.js | 4 +- test/image/baselines/zz-multi-legends.png | Bin 0 -> 23979 bytes test/image/mocks/zz-multi-legends.json | 63 ++++++++++++++++ 5 files changed, 141 insertions(+), 35 deletions(-) create mode 100644 test/image/baselines/zz-multi-legends.png create mode 100644 test/image/mocks/zz-multi-legends.json diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 348cc9d444c..c45ca0afb62 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -9,8 +9,12 @@ var attributes = require('./attributes'); var basePlotLayoutAttributes = require('../../plots/layout_attributes'); var helpers = require('./helpers'); -function groupDefaults(legendGroup, layoutIn, layoutOut, fullData) { - var name = 'legend' + legendGroup; +function getLegendName(id) { + return 'legend' + id; +} + +function groupDefaults(id, layoutIn, layoutOut, fullData) { + var name = getLegendName(id); var containerIn = layoutIn[name] || {}; var containerOut = Template.newContainer(layoutOut, name); @@ -147,6 +151,8 @@ function groupDefaults(legendGroup, layoutIn, layoutOut, fullData) { Lib.coerceFont(coerce, 'title.font', dfltTitleFont); } + + return true; } module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { @@ -157,10 +163,18 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { Lib.pushUnique(groups, fullData[i].legendgroup); } + layoutOut._legends = []; for(i = 0; i < groups.length; i++) { - var groupName = groups[i]; - groupDefaults(groupName, layoutIn, layoutOut, fullData); + var id = groups[i]; + var name = getLegendName(id); + if(id && !layoutIn[name]) continue; + + groupDefaults(id, layoutIn, layoutOut, fullData); + + if(layoutOut[name]) { + layoutOut[name]._id = id; + } - layoutOut['legend' + groupName]._id = groupName; + layoutOut._legends.push(id); } }; diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index b65db34eead..f8050467e20 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -25,13 +25,22 @@ var helpers = require('./helpers'); var MAIN_TITLE = 1; module.exports = function draw(gd, opts) { - drawOne(gd, opts || gd._fullLayout.legend); + if(opts) { + drawOne(gd, opts); + } else { + var legendGroups = gd._fullLayout._legends; + for(var i = 0; i < legendGroups.length; i++) { + drawOne(gd, gd._fullLayout['legend' + legendGroups[i]]); + } + } }; function drawOne(gd, opts) { var legendObj = opts || {}; var fullLayout = gd._fullLayout; + var id = getId(legendObj); + var clipId, layer; var inHover = legendObj._inHover; @@ -40,7 +49,7 @@ function drawOne(gd, opts) { clipId = 'hover'; } else { layer = fullLayout._infolayer; - clipId = 'legend'; + clipId = 'legend' + id; } if(!layer) return; clipId += fullLayout._uid; @@ -50,7 +59,7 @@ function drawOne(gd, opts) { var legendData; if(!inHover) { if(!gd.calcdata) return; - legendData = fullLayout.showlegend && getLegendData(gd.calcdata, legendObj); + legendData = fullLayout.showlegend && getLegendData(gd.calcdata, legendObj, fullLayout._legends.length > 1); } else { if(!legendObj.entries) return; legendData = getLegendData(legendObj.entries, legendObj); @@ -59,12 +68,12 @@ function drawOne(gd, opts) { var hiddenSlices = fullLayout.hiddenlabels || []; if(!inHover && (!fullLayout.showlegend || !legendData.length)) { - layer.selectAll('.legend').remove(); + layer.selectAll('.legend' + id).remove(); fullLayout._topdefs.select('#' + clipId).remove(); - return Plots.autoMargin(gd, 'legend'); + return Plots.autoMargin(gd, 'legend' + id); } - var legend = Lib.ensureSingle(layer, 'g', 'legend', function(s) { + var legend = Lib.ensureSingle(layer, 'g', 'legend' + id, function(s) { if(!inHover) s.attr('pointer-events', 'all'); }); @@ -85,14 +94,14 @@ function drawOne(gd, opts) { legendObj._titleWidth = 0; legendObj._titleHeight = 0; if(title.text) { - var titleEl = Lib.ensureSingle(scrollBox, 'text', 'legendtitletext'); + var titleEl = Lib.ensureSingle(scrollBox, 'text', 'legend' + id + 'titletext'); titleEl.attr('text-anchor', 'start') .call(Drawing.font, title.font) .text(title.text); textLayout(titleEl, scrollBox, gd, legendObj, MAIN_TITLE); // handle mathjax or multi-line text and compute title height } else { - scrollBox.selectAll('.legendtitletext').remove(); + scrollBox.selectAll('.legend' + id + 'titletext').remove(); } var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) { @@ -118,7 +127,7 @@ function drawOne(gd, opts) { }) .each(function() { d3.select(this).call(drawTexts, gd, legendObj); }) .call(style, gd, legendObj) - .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd); }); + .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd, id); }); Lib.syncOrAsync([ Plots.previousPromises, @@ -128,7 +137,7 @@ function drawOne(gd, opts) { var bw = legendObj.borderwidth; if(!inHover) { - var expMargin = expandMargin(gd); + var expMargin = expandMargin(gd, id); // IF expandMargin return a Promise (which is truthy), // we're under a doAutoMargin redraw, so we don't have to @@ -146,10 +155,10 @@ function drawOne(gd, opts) { ly = Lib.constrain(ly, 0, fullLayout.height - legendObj._effHeight); if(lx !== lx0) { - Lib.log('Constrain legend.x to make legend fit inside graph'); + Lib.log('Constrain legend' + id + '.x to make legend fit inside graph'); } if(ly !== ly0) { - Lib.log('Constrain legend.y to make legend fit inside graph'); + Lib.log('Constrain legend' + id + '.y to make legend fit inside graph'); } } @@ -295,7 +304,7 @@ function drawOne(gd, opts) { } function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) { - legendObj._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY; + legendObj._scrollY = gd._fullLayout['legend' + id]._scrollY = scrollBoxY; Drawing.setTranslate(scrollBox, 0, -scrollBoxY); Drawing.setRect( @@ -331,11 +340,14 @@ function drawOne(gd, opts) { }, doneFn: function() { if(xf !== undefined && yf !== undefined) { - Registry.call('_guiRelayout', gd, {'legend.x': xf, 'legend.y': yf}); + var obj = {}; + obj['legend' + id + '.x'] = xf; + obj['legend' + id + '.y'] = yf; + Registry.call('_guiRelayout', gd, obj); } }, clickFn: function(numClicks, e) { - var clickedTrace = layer.selectAll('g.traces').filter(function() { + var clickedTrace = groups.selectAll('g.traces').filter(function() { var bbox = this.getBoundingClientRect(); return ( e.clientX >= bbox.left && e.clientX <= bbox.right && @@ -403,6 +415,7 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) { } function drawTexts(g, gd, legendObj) { + var id = getId(legendObj); var legendItem = g.data()[0][0]; var trace = legendItem.trace; var isPieLike = Registry.traceIs(trace, 'pie-like'); @@ -425,7 +438,7 @@ function drawTexts(g, gd, legendObj) { } } - var textEl = Lib.ensureSingle(g, 'text', 'legendtext'); + var textEl = Lib.ensureSingle(g, 'text', 'legend' + id + 'text'); textEl.attr('text-anchor', 'start') .call(Drawing.font, font) @@ -479,12 +492,12 @@ function ensureLength(str, maxLength) { return str; } -function setupTraceToggle(g, gd) { +function setupTraceToggle(g, gd, id) { var doubleClickDelay = gd._context.doubleClickDelay; var newMouseDownTime; var numClicks = 1; - var traceToggle = Lib.ensureSingle(g, 'rect', 'legendtoggle', function(s) { + var traceToggle = Lib.ensureSingle(g, 'rect', 'legend' + id + 'toggle', function(s) { if(!gd._context.staticPlot) { s.style('cursor', 'pointer').attr('pointer-events', 'all'); } @@ -506,7 +519,7 @@ function setupTraceToggle(g, gd) { }); traceToggle.on('mouseup', function() { if(gd._dragged || gd._editing) return; - var legend = gd._fullLayout.legend; + var legend = gd._fullLayout['legend' + id]; if((new Date()).getTime() - gd._legendMouseDownTime > doubleClickDelay) { numClicks = Math.max(numClicks - 1, 1); @@ -532,7 +545,11 @@ function computeTextDimensions(g, gd, legendObj, aTitle) { var mathjaxGroup = g.select('g[class*=math-group]'); var mathjaxNode = mathjaxGroup.node(); - if(!legendObj) legendObj = gd._fullLayout.legend; + + var id = getId(legendObj); + if(!legendObj) { + legendObj = gd._fullLayout['legend' + id]; + } var bw = legendObj.borderwidth; var font; if(aTitle === MAIN_TITLE) { @@ -557,9 +574,12 @@ function computeTextDimensions(g, gd, legendObj, aTitle) { Drawing.setTranslate(mathjaxGroup, 0, height * 0.25); } } else { - var textEl = g.select(aTitle === MAIN_TITLE ? - '.legendtitletext' : '.legendtext' - ); + var cls = '.legend' + id + ( + aTitle === MAIN_TITLE ? 'title' : '' + ) + 'text'; + + var textEl = g.select(cls); + var textLines = svgTextUtils.lineCount(textEl); var textNode = textEl.node(); @@ -620,7 +640,7 @@ function getTitleSize(legendObj) { } /* - * Computes in fullLayout.legend: + * Computes in fullLayout['legend' + id]: * * - _height: legend height including items past scrollbox height * - _maxHeight: maximum legend height before scrollbox is required @@ -631,7 +651,10 @@ function getTitleSize(legendObj) { */ function computeLegendDimensions(gd, groups, traces, legendObj) { var fullLayout = gd._fullLayout; - if(!legendObj) legendObj = fullLayout.legend; + var id = getId(legendObj); + if(!legendObj) { + legendObj = fullLayout['legend' + id]; + } var gs = fullLayout._size; var isVertical = helpers.isVertical(legendObj); @@ -819,7 +842,7 @@ function computeLegendDimensions(gd, groups, traces, legendObj) { var edits = gd._context.edits; var isEditable = edits.legendText || edits.legendPosition; traces.each(function(d) { - var traceToggle = d3.select(this).select('.legendtoggle'); + var traceToggle = d3.select(this).select('.legend' + id + 'toggle'); var h = d[0].height; var legendgroup = d[0].trace.legendgroup; var traceWidth = getTraceWidth(d, legendObj, textGap); @@ -834,13 +857,13 @@ function computeLegendDimensions(gd, groups, traces, legendObj) { }); } -function expandMargin(gd) { +function expandMargin(gd, id) { var fullLayout = gd._fullLayout; - var legendObj = fullLayout.legend; + var legendObj = fullLayout['legend' + id]; var xanchor = getXanchor(legendObj); var yanchor = getYanchor(legendObj); - return Plots.autoMargin(gd, 'legend', { + return Plots.autoMargin(gd, 'legend' + id, { x: legendObj.x, y: legendObj.y, l: legendObj._width * (FROM_TL[xanchor]), @@ -861,3 +884,7 @@ function getYanchor(legendObj) { Lib.isMiddleAnchor(legendObj) ? 'middle' : 'top'; } + +function getId(legendObj) { + return legendObj._id || ''; +} diff --git a/src/components/legend/get_legend_data.js b/src/components/legend/get_legend_data.js index a19d582b536..070bea64d4d 100644 --- a/src/components/legend/get_legend_data.js +++ b/src/components/legend/get_legend_data.js @@ -3,7 +3,7 @@ var Registry = require('../../registry'); var helpers = require('./helpers'); -module.exports = function getLegendData(calcdata, opts) { +module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { var inHover = opts._inHover; var grouped = helpers.isGrouped(opts); var reversed = helpers.isReversed(opts); @@ -17,6 +17,8 @@ module.exports = function getLegendData(calcdata, opts) { var i, j; function addOneItem(legendGroup, legendItem) { + if(hasMultipleLegends && legendGroup !== opts._id) return; + // each '' legend group is treated as a separate group if(legendGroup === '' || !helpers.isGrouped(opts)) { // TODO: check this against fullData legendgroups? diff --git a/test/image/baselines/zz-multi-legends.png b/test/image/baselines/zz-multi-legends.png new file mode 100644 index 0000000000000000000000000000000000000000..e7078b921dd670952d611181b42ad27e50a7c0c6 GIT binary patch literal 23979 zcmeFZcTiN@w=Rl^0Ra&(5CkMkmMj@1jSvwMZ=|gm6P_ix`|qh09U(7S#0Gat0V@o1FZj^U9w+KeXq}4 z{YKBcnW3S?#-sTS-}(J?JL&m$I#yOzVY743NXV{`96LSpkksoM?($@SI1B0FZ}(5% z$DBTP^#A9`$gbh8U~W18`TJRB*0Iw{B;cabxpSY8FW=JDo;doOBsk(EaX4`Ch7t*c z`i1t)#Xo=3%P{_V7TK|5l=7!#qD}w&eIN6XI2M@5zaI48v~;c~o=Z(Vg(whkdiEn9 zGQ;Ub*t>lqA|v4?(7KLBzujz=NEX)tEh(E&Ef}m~Z#Cc`cAv1TQD{&s+O@k>-rKP= zpCPibz09Ml%` z*>qi+I}mhJK+|B6vED@iqbp*zT~YO38{E0F{(ChO-q>PM-`|fJuHAn&;kP{*8m#bW zH`@NPc*Pxs1RP8)zJznM1zW#93(CkT2_GM z0b4N*o;6^PZ7hL`Nis1cgJ+x-&u0_2<`6>sduSCd;*% zN-8nKW;mD3oI@od&ZUW9;E!M6k@mw^B-LX2bHdF0cVve-}PZdP55=+2YFV9PR1% znT2W!YhUSXW&D19|J+|;KX6OQZLUj1Z(1)`Ga6gkG?n=93nQX5*ne@5x9@I~Il{IC z&RDLXnr(yGnCljs%gQyXdSpCW^CauxBw__!YS9Fvg0fyU4 zHBZ(zdKFV-Dkt$*zGrKZ2eZ)7ux(FzW{i5CyLge?ZN4WyUoS5?B*$T>AZe~QU4ERt zGIt;(JTQmO?^!;y&f{HX6RuyQ%n>EDaZb0$NW^L%5$D>O>qi10eI)3V`CRujYf~3<};$1`&C6q$vJ;yAgw@L8+j}X=lFg+LL402Qq zmqxhpLULWiHN76v_nC|9&lqbJia5>Cz8h~aZHArv_X_lrZ>o--bSh+=`5H<`XD1AM z`PTWo?_82y_z#ELEaf+%95xcp4dUHU&q*6f!WRl*aqd;{lH2_VcSk+{{zCA2?+zwh zI|b)H-`t%|b}SL$SPs-snKsdRd6J42Eb>>O#^07!7_)P2P5|I1hNo+B{&dP12Mjvk zpn+j$@w|KAyW8EWMxNf-1MK@Ae#pUkr|@i6q=Nb|#KDAF26ioF)1>NAQU}ugb-iJ! z`J6walyhpLp~?b6M~U@hOwTP&LAjhv^wa4#{f&M;Vx&6W`St}1i;&13%X-4r_`6Oj za*d0p&R)KzHzT9*Hp?c@N&OnkscFipU*nCb9rs|O=hDanTTR@JcjgV=?fsi8ljCx! zTuZJf|3o;tapE>BC8MBarR|rYhAt>$4hFJW8F&&4+$>`V1HP5iyJi(Z1bb ziS0P-ip*?@;|^XXJ)*^Z%v7bz0Vl(VTKEl?Xfk}sy<@^YMRe?YUT_J=YP!5nGVg|h zA3o9e4Aer$+djjdDWZJ4;v7fZ3Wx&iC(XIbdEZ zq3jHcO>C6iWQq$pz6VA>Qiq`4xSpbB(X8av&MS96Zt9)#vm(7nv({1C;g*{4BwHyp z^THdXyT=XGL}hxxy~5l@Xxj5v;o)6_NQvi+0j&|t-5AN)9PEUQPbR9&rn9R#a$oZR z9QO!@AuPVuTzhkpjYs@jXBpVg0qhLQ4HSB}w(6)mr?Ekjvt8|C@%)d~& zMm*)Up0(AtNO`H`KXZ;%IXRl^r6~A$|2!>~lZkElFxv_5tXpkN34fnlG}qmRbk|Fb z*tY-}W9>Cy3PCL_1-`kTd?T-_a(SUR6WeCOstPNRD>hscjZx~5#I!WT^5`TpgvoiW zXQ$j7Nb{WXTL1o%Iyb4sJ|&eA(Q^(Xzu2tY?=x7nXj_eN$J+jWz~D!Z45^IMAm8&+ zx-tT|%ID#%37upzT}A}A_wOGeHUL{}2~zoYv&C_NycW>XAy zlZuBAa(}p6rD|_ul@*|!+BK;a?fIFGN%&7W2k)gFcX9FJX>5H9n_)tTt9{7L&noEi zcl;5sw|;q)?k71K8p!tAm97{OU$H-SLM522UliA?crc+kt(_t%_yl1@p=OW4i!ldb z2aBCa^z;l~4xs8_Wa)jUq1_gWLgkj<&Pe-g72%f0QHc*sIA9X2P!wuwX`)t4V>J_t zuWKC3$t~iT0eIBG1vj(IogQFv%G+c?G$L}TuQ;MgBvw7KJ`1@WVxixH!$smm(&W^HW&FFy#o;9ZxvA?Wr4h&gfrj21W{-)`bG6g zcruULZHD>oN#D4_L;O-LOZ(>Da=gv*gQjRp7qhBL6|j2t8J{7vg){noX|=`q?S2cp zl#=faO;>dkRE%1ASp}AX94y0F`GjEv``h3WbTW!}TB(87TxWm=q3y`iKs$9CHF_F4 zF!zFltSo~hIGxayPeYo2dWH;~L8r;UT)kg-HiopV;Wzepa-+1x;f1GuK39Ic6oZM8 zU5RP{AhsLAJ=Dl%gPWhArqtJXVT-9H9;5^gXC9q3&PH-<8_Z=z zEcfIQ^L>UTy9Pti=p8$x(@LNGNa+!~;rV|U^LLqJl#}jX^^d6WxyN8`D+*Q)e+Y1m zHVMR&S>(bYr6wVp;CYr=*PF=rhd7sjuMeuCdEyUM|JP&xwaCPC^Z)5cl_h;z7|7#N zP%!_}++1EemwI;+FgD5zK>O#yPujWh_eHLLLKU0N``EhXvflwTR^aYuWO-oNSLx>@ z$E2stzaYitUi$kU@V6rU?BE94l#@+zyn?4_uUxUhNS57JY#e9?7eX?3;mkQF$d8eV z20L@u;HG8eDJMNW=n(;~{Qu9*4XKYXRxRPtxmqd70i?5*aG$q0vgKdl zB*z#a)ikX5wKQ{GNWj{+OF4iKx&8>cgg3u0IrkM=P9u5m#wT9l6j${5?QRHj;^V>-X6;n zIpK-+dpCeIt#*#Db(=r*sPyx7T?w10lniX8Kf&7=0n67fHo51&zhl>jP>;LHRz2li z7$;!dpDpda7}u37p&|KbpvO z^Ju3=!7coaooi<=<{OviK0-G_xpmS7BIUOd|4gKRhKwv!(_pgTNi1vkOgx>;gm(n@R#IX1H4+J%b1*|g18c>G<-Yc}4n z3nTp*nIhrHeaXW2WBtMY?m95($}L;`K~hZv@lNF(@{%H>h%(*JhCQC=&Sv zOmL?=3d%E|5zwf%J7j3l-tvZNcCD3lyB*n^Ds9zeK5ZX#=7J`J%oh~zHj{JB(E=vX z9P@iIYI!BkA#f+iK$>IOFF@g#Q;F#B?Qp>i5Tf`}g;rZ>;*Iq~4S=gen-s?K@SQH&Z5fE4}CoL5`!nTx} z_U_%gwkWya6`zAxF=kS{dXP5n!pW#W4Nv<;Tx_Gs=b%ixd&f}?jkhHC{p5_R3LW9m zq0rtpuWNdMYv5=2LQ#Q$a2Vn7w-L$n8 z2+3}EzUG92XYN`c5-_EvDdjXKUOt?46Xhvd+t2+r9H)+;xM;x68dRlD2gw^*{S+HW zf^RoFi+^ow0#~GjTBZ978RQMbn&S(`fqUnWJLJ|GlzB=`hgHGX$a{0qCU=5PXmY{0 z{^=93N*wU3PPC`t4v zaPr#h$cs#*sG)CU}9XxK5h9y)ArlReE61znLjQM!6x`PMBmGt=Yw zH^^piKGSJA=2b?$xL{J)6 zrR<~iq-3z3Gn=uMh(6;cUfp7oN|=VVUh0WQWhYM^8s;o(qG1kT!0*2=cl~~=$X>NU z)SmU@q6Ysa(+d81$y9^SZp@@iq<=@T&fWO%4ZS=FLGoyv^6k&n5BI*RNmO0?FyDcej@3&Rvp^sPx<2 znwzQeSRQK!Q9}U*8D#%KP7Y(vsB&7(@qm#rGiv1x{97U ze)PIl;B_0~f>|!m2?r3|TAn=5v-&yn?b|86oTdubnu@wlJNeI|A9&?>uleS8NI(7c zR{90P1>G3hG*CXeY33o1Q&*HIg!_9N^je~_%oTT+#H^+q`iX%`0VrZHl|IjYGf*;3 z#!$>Kc6eiOdll_sd#qxDY{f1WN?g%E$Jggk4Fg1?fZ< z>F=8d??(op15DC)Y@4P@r*F?pf3fMsnd(8O$n`m;ygXx-2m~!?M>NM^6#)r?( zIBRvy)NqU3R>pqg#eNrwD9`VI}45~7Vmv&~(Hw51E$46<- zhOydsrMDd3X|Hv>Uv&cuW`o1@i9STW{aO#0n1ssLDiFHt_Gv~kdrFhPj6dXSeUd~| zrZ|k;^=r@>W>!_uI_Mv=$@WhoZIoI%aAT2ywS~vTYS&^<`+a>y0|JKPTj??xM`Y5zJ6;x%NeEtb0*&o<5y?A&OE2MhG z^-SBsp&fk_49G8T?*Yd9YpHX%Y29iZCb(uUo`YaHN1n9|!pYoXXb|RO`Z-)=Y(;4% z^=-k?7SO`EgH2Cs>O1*=fKVR1Wl{D zK8Py_SdphJNoO3M!@DBHbJ#>Fk8W?`5^%_{SJlrC^L4rNIu$Rtxi;OZu{za2Ft9Z^ zg9q{D+385d1lQS)b`XaT$+SDcV(-RtggCy$wF;p3{>V&`{iPr?^v$b?tNZ~_`P)6g z7uFjdu+Lq)AYTFln5YXv;L- zyk3LoEO?VG0#bLoR|6&18_Ux3j;F+a6!;2rUAV=e!aRpn5S?_=HW=88j*g~B+>4Bn zHav2=ZvOeo*+h7lyvkRC$if@v*)}*?-S{~FnxFvlfsV?q=nb)h4$E)=Qr}cx^JYK%bY>kdossIGD>uW z4;Jd@#~4+mXG{USv8E=IdAB<9F-!a*65#2yIR_hA|CK{f-@gV}0B-MNu(|sa;ZV5> zZexzBN?*u3bqTQZ2N@g4Oo(mVWc6ym0AA)MtBB<-%TXrDM^VC!zi)bPE!pP|p-L@; zK~hI7SmDXfTlT|6NrQ!k!p5esK;X7~g5{0qNv6^u+zoY=oY@W^SP=oN$UHTKI#gQd zn};tO&29kA&ZZ#4t!+9XyX81cY)s^ zalun!7dVNk#Hc@`H%OitL#U~!F8Do0W?%#I+#g^X9m7*=k38#WxkIETQlqrlK`m!Q zZ80$Bwj5?4aLtPYK5&@x+kyNo{*sz6*@lqFu&~(DM!Y(3Ol-Oo7KFCFHs**<$eSH- zzD+<#w1>@t_i@kfEpTmT$spT=l`=&h)`WKdxk38-M>x$%#AyJNqdD<( zkZoZd_0H!<7asj};Q?mfM#cWd&BL)&8GtKF4cSg(4qmbFh`Y#nbaUMQK{va;$i(tG zfEepGfm_hE1f(p9^jP}I&&`I84vuXgih{x%k!@IK+k>TL0{3zy_O>&6(-`mM*Il%cpo?20F* z-nN#NT0bhclnJle7d z;+E+$;@fLt%j6yErb%_arNu;>D(9-BvmescR^ciEa-0s0+F)NvxWvn2kYIv&2*rqAQ~g>r8S^@`*u>ko5aT6&PK|# z-X8{MMlkk<=MvFI1cws>5C)IEW^@#QamoUxG)Ejq)hgBYUGe0u`Td(cPifkx>k~~* zIJSSHI4L6vlUJzJ$xzTO(9aj=AF1~$-}}`}Jx7THIS!TNLj+TpRrUEd=qk5OwgGu0 zgDG#Upqsd3gZJh&*gQ0)TyF(rK~GZB-_H$nMl9r}`iYGWdLKsDB#1UVF1T@HP&*0X zSTIeRHT}*;V=zH~AuRA>^qC(QF2nVt>&qsf3(l><`yKqHoTjbA|6py0sl-jbdj*^c z#q)XFfZmTDe;$F6^;o(}#VD>ibW&c=4zv7TF(5{@JI?Be5q9>!E15o$SVVK&;cV1c zki+iOhl5@(43bT(V`aSB#nSi)27ey7jC{D!`1>ct!f1J3l7U5&e}e$9(DZna1 z+HEfJz+Gnib>?o#w`bkbUhCH7H=6TLlWr-Osfhh$%u4|h+(H`LSd6T_5AWBO< zR;&Q{p4+j9zULo+)v}X!Kf+hon_9$k?YuGfG}D2?Oe|~%geAECB7?g?vtT{l@}^}E zSY^RUgu8~MrQ+l7&qnWNNV!Z|Q#I`4u{l~PlJ=6oL=NXk^W8HEF2Tx}+0!AZc)S?(0ObSi@bKA+=`A_WT#w()e7@*8y&spsjvzvF_?CNT+_*j$Q|3UW+rdC5JH z0i?dAc6!FA6491q)t)pXEYR0*@Pg=`^SDW8Z&!n8M~@Ic?=@TzvV+Y&$+g!+MZ_lg zY-ufZ=w5=Qcf;ppcIJcKS1QA*r|cYX(>_g>n8tDqejWhY>BsIe2B%j#U%8UkjK$GJ zXS8(gUtmolvq|=#wV#4yEA6Ol6W%8cci~(sQF26;O zprhdSMf}H16?0*bhcfTab2dD>^+D#pZvEE^{A&gNvlZygURiD2)wb0*p@G+ct~V}xTS&CPWH=;)4OuJUUhV%UyfC4gzKmc zJgFsB&Z~c1`NZR85Vpv52g^0064){AUUDN>=76z#;Ps=%=RI@IAYZhm6+!c_yz@VVncXd5`2Bmwy)un0N z*p0uucyPjItvgJtH#JQ6ZAO=@Ebs{beaza8GedF8kt~8ge*EaqQlXw_aPv~n)f~9^ zsazu?UgrQWJ}T@|(yr5q zxXl_1H*6FLJCKoLZz{vb_ix8EK67YuWZo1XBrlx&5RhhZ$igaydnZ2WX)fp*K zbzyZ2FI;Pxo>6$}5My`NLH>_0(I^d&?uX-U1BWHx)L*%|e@AS}$qV?y5RVb2HJHV# zf%93Wj~Xk)Gf3euN%?miZ$&~g4+jqX`@kYFLkt};<@XPC{}01PIa126EE#+4e)P%d zq$pMYL7P)=onGYZQM=p3e|Vq^kVgmllO06SFl&jbb=OI zmpLj;D-v9X9NHFQ@2)S$t?4$l1i9L`j+-sBQcfN`B`1DV|278+h~kqOR%21Of~Bc? z?JpD;62{<_G0ILZQQ(70+?}jk^E8(9%uS7uVdIJ1cl5tV%g7B4X%sraPSJr5a7xHw zZ4f@#Z!mlv$HxJm7*Q)2cC_vnOxbuIIM>M|qw&E7n?cLUYS*>>+H_U>@?F-ca*f6e z>D%DVxKD&#fagkiNOJqNexixUosbf=U}y3-6Oh{UpBmc#j3h+DiD}IDX9y!mj#4<8 znHWx*!y>Mu606o=fNE>EQkm%_FV%QyfKp$+SUfYhW+giPO~JLf*)IncU+`|O)^-1K z?M9Fxmy7DFRGBAcwr3Z345yxC=-0n3Swe5+`AR4 zn~W@bQlooY8U^lQrDDQLoO!%w-p`f#K9INf^;6kEet6mAoM98Yxjn2n6MGkO+3B@xG4**! zMzkZ#Q~i#6r3(%R_c8me8pN+g|F6ScLXXhCC!8d0ydE6LJ(ZHaqW}JuTJ7|X;Y@Ev zKn(g)0Ed*kyR(e!XXGlQoC$l_c`?0dQ-e~V%Z0?uM8;AiS4Hu!)}ZMT5eQTC=Jx<< z%CM#cW^6#LM?-poyP`mxqJdCsiZ`|DUPEriM73RRa7h-S7k!y6UZ{xYlEwJcW+QR4 z6aTr{AlE#or6?G!?PspKF$MD@yu7qazaeNyAT@4+ML*hm@)5SU`%bMi3;W`mdUhR~ z7M1*5m%Y8$Zi77|9?yC)IVAY3n({A)!B}s_#LP^`aR?*~ojWo;HkTjgKwr8Vk{W>Y5Xsw~nU+)~c-LJeNS1zmC{#27QN zvh#?A5^n$?m}DkS{2;IK-sd`7C;4LP&Qxi4T?JMt-PiGg!j~$Y;6;k;VHe#tp)fGb zb)J8mVMmD0=rE*+_}f~ys0{O}His$$ zHBddJORi1&B~bL?C!+tHEc z_Un#ss0#Ryg&&`k!j@(Mbj37a_jY6QZ|`Kn+Xeo?8f2xy7jQ}v{&7ltC1EMb0o(hW z?Uz`D;1yWT2Rj>`qa*aAzXxb{oPJzt_h=a(jMiJX#O$x~5?%EyKHL$x|MeA#_QJE3 zE0`B)?tJx8toMZbZnbo}_I~(izTUQl5P=-jK_)!=W{85*>O3v4?q%fXm+0Q1pCi?QrKCWUT}SgI_tK&!@)kYr>xZ-ToFk9 z`6)Stl_+e%hZ*7i{fn_C3f1%N#zsOdu3k+p%pM=H}=$h*@iH!C;O}1|6JHEB*mj~ zcCV~=oI;|y+J^FI7s{$qQw~|FqIiDig~e*ow2Rs3QuNwxsqS=)M)z|e?{^a=RF2&u zAL$W#ueTNsZRG2}Y$P2-Sj;~4{K3-n*WHMM@jD)8nQgjnD6;NuW=qZB+OP8J7X=Qw z_@$laHC7)MCTO3z$S;IV@a69wL-SP%*Xbtoq;ty-A8tsT740AU+=45y)+qarTVJfP0J3Q3IjIIb}EfLh}F@LNk4>`G$Fb z+F~_AxxfMz3PNEz>$}_NjstHw-kmQTGq6GOc2*kR@(_8RZkY*(+;ypaT*F?aw@om| zsvb{7Cw2K$?9W+#^=Zd(z!rRl71$0*G0mS7W5nd$C#)FjI;|qx7$UdEzUHON6B&7_ zJ+`HHfd4nzajd;DT}MU~S31SO?@7fX=+&Qp|65);SAg{m`;j@BouA8nt~Ulcb4;3B zLTy+9*5LwcdI%>|G8WcK=`wupusn6YSyuji)3fy~Yh0uXWy}Ci1QEg1uqBgR@9sRH zocwrmiH?@Yr7ryStyE@SGTDhepCUEBCLfr3o$W-Gi(0$_Lf<%)H+FySV;sXfA$y^a zaZe9xjAHlh9T~a(N0wuWpymKBJm3BqI?kz+Uhj(g?w{}G<>(f%t5QlC*XgprXVW7q z<&AP|MM$i7&pdf&SH)u{QykDK2H`4G?Gs;>m*h67+AA|N2#~jM_VF%#J?yhkg`M$rrw%4wYfM$Le$E%h?s31ozIb479PIoge3IJ~G>CxIEFo zF&ekKu4AXR+luG8xHd46MC&(KVK%iRWL42Q=X(X996iM1*YMT+q52$s$Hz}B@h|JD zI%AUbX6EuvNjoW9BDT~0G@ZS@-<}sRk?XDp6ffE~`8hxcJH8l7+P6nXO{t0rF;$f8 z{n3k6Z3cnnEO0(9-B%xk_CUB0mM(c&3X9QT0-Bt0VxU*3Qbp#uKr}K@$|#vGn73_L}>0w@jULs;ukxRqOd$ zN9e%{nt$g^AWy_hb;*vgf2tUC#rJ_eVu0`;?PxkZB1NhQ=$g5&rzto6PTtae=le}R zxTNk!Q<|Ll&z_cKX6yx__fC|CRPsVX+WzL(3?)m=`0T7Kvz4dkTt~a1nqG+ZEesc@n7Oudu~c9G zRe1O=e7BEC=yL%k1pH06mV04lZ;F(TNu>kV?XZjSiu=DI_^oAr;H4%Yk;sWa_Rei} zzzxddcTi7_ALxM zth<%uA5;DKhgl{?o>ZuRY79H{Es#d#Z=#6%U^G%y-rk_iNYbEU`SNw z*6T+=+ifSiUS#+lyFg6$0YzhbI1=aw9!hpR$#KEpnYI`?=gSH2lyU!W>8E+<2~CEf4pMod7l8O z>loo}%1@6?ZzJsz6C2uF;`Z$EEpKe}%+8o$c&_b7*xw!oPPnmMf}k`}@+!lQu5^SO zQwZs1znXZ`%G?jaD39_Lc?@qV_0((wy`t?FJ#2YQg2%Jm(Md(IBs1qe9Q=EsnYIyv;jp}y1MHMm6Jm_QwNv!-kK#Yf@j6{7~+F^_wIFYoU;~wze+1 zX!dacvZE0b#z91d2dIuERzkM}L&eYdkeKJC&!$6?m(|3`+w83rE3kpSvhFW0Px*b}yn6TJ zTQhf0Ctl*UN@8jQPC@nLL#WR2kf3cg#)_o`^y;ROciP=hQPHuO{e3jou&t7&A zQV;cay=!-BwAd1JV>ojn;xy3DUeHXD?50OJSIwwvkr3X#PE{v?^ybT})D3VQ>1pKt zMhX<%>yE@7|DaKN)%-_7fqxLD|NPblImx8Ut9hQe>Lxsz_qfv2%w~1fz4pytl65tyvZtpsh`{_|)wH*Tn4BgF|bqbYzXiUxQEVL|$goM$e9J-4;#$J#1oNa7$;Aar|tj zaA#)->;8SpsRjy&XQUw4{OP0jeh=O|T?`T#+Rj18Js1Uw4MJ7x#T`9Vy*Kd?b`C48 zS)Z-IPHd^gRiEwP&d)DTa0&@U&a~4B3)lZj5qI%dg?*KCo;XovrIM}x{;~Q>olDqG zt$8OL9;c&NeARvNa=c3;FOP_bSB_b2EGT|p0=S^Zt);L3KAZ)r0XhS4?X0K8dn|9Y z;Wuy3EEXPkh|l_C?)cXdwmNNkQde{CWYRO;Pn!9Lga&H#5eu0>mZpyvIHdDkNcXRG zem>c9TO-`$6k)L_i&7iqM#65XSiIuiV>+X2@?%gxUY14VZtj!?$@V_VlVtRx|7R% zJOk@-{fv4*C~&DGT|TmKp&@KXu{Di;a*etK z@gxc5{H%F&8kxWbcTOO!tTt3b&Kh>qtqR5V=kz9a3{KQ}y6|NL?5Cwl(^>k1aufFU z48@+k{ro(k1jmw5M`h$dUIx$ZRuGUaGSM;Ne}-*_CwVR-hUoDW!h>)f1>@AjfPvgE z>l1ENpu9T))YE$bB_jXqCMqC-Lg>0}$E%1Q{xn$&HhCXsZ4{D6OU7cZxAdX%c6Ty! zT%#XKsN0=PipS+a4)_-x&3lixOTP@YpOEw|fftFYJTRwWFZ z3QNtU3tPO%l#0QYq8*i&n}dhqzlCXNsI~>vPXD|$Rz(=sEG*27WcGOuYH}h&$*Y{g z;>;V8J6@a!>w0CO@*9tS@Zf;Kw%S>1b}q#;*Ac^`9r$|R?e}B40%*fB$|8tXr7lYudNoHqErH2p!b!67f&e{-*M1X*L*>g%x{pxo z*0N_imDG}C9a_poi2VY;a*~!?(i>zYvv8AH>)>c!uQxe$WUO&{L0ebSy_x(x$!t;F zbZherfRCiK-(cM6=~jr%RK5E8CTiCD=hs=??9+7#{F5BgpxG1kydMfmjm zmvxYYlecOxr7;IW#CdVhVZB>w_BIv5=;OoMt+58z?MYKD{5HCjPcP3vr>ju5Z?)d7 zaKdB!?1tFnOs;IVloKC28`~4z;xY1afAgGb8C5rr#agRu>GAOxhbG-A0`7n}MiCyj5k$M%c47}SV zMMA-91U9#PK7Dsmvl?q#+qBPj70*@8tG7SS;4;vW8hZ)SEA4k%qEb1G0@ z2br@HRx3?$cHk{-sOr!xoKL5K^ve5nr{x}L@b>J93$X>%Iat%`i!u9z0C-zlIqiiD z?5w_bhBR}q+Mb?@l@4yJ&H&pc->N4`zdFRWXnufgb}kqM1);dwq2u)hu5MUeV_1pf zxaVZ$&?EIu=%wKFI($l<*6pJOH$Hlfv!2hd*>A{~r8>1)0yM;f-l@PId`Nm7A3CB|NgI}Xe1CXaS57SuBcVR)_YGlu1>uH zB4E1p-_t3gS0lBa41eIgVt2F`XNb?-v%<7e!{etzIunEAN_SGUUdGH0ZFFV$Bcj7u zoBCaB@VZD9)_V!@{2Hn|>v`8;79=q|+eedjP$6z6mEV94s_jd@A1%|}_g_I`cyuL3 z@n@h`GpCG9DQ*>gNAl5C_W86+HW60KQv{vb)y6s31A?jb(g;QNgXVx77xd=(kl`#S zV6p3&kvP>Vx4R_6Yq}NpwKc3O)hk`V=#IH|#@Tp-;w`n_^nh0^-$iXT1@)>}I5&PZ z2dEP8^ASE;UdvO=Y|SC4=$s*pPr7iPPDmR^Rq=M5TLOcq9V$yI^@X)o@sox8x7?T6_UZaNPPQ9kF(QwQ9=ifE;=s>u|f z?uLXUh&qi$&K*-KooW!4Y;7=y-Ce(nUmCsF^{~+qRSbByJ>{gDT@1J9A65A=a9jb{ zDc08|?_Dc|Pm}hx%*6VQJLIXe-o<=4&tKj7M4F55QGBNh^ZW=>@xb?P*{R?Y6nt#} z3~8g~=2CH%-z>YNSBPjHDOaZEFeH;;R24DhQu9MS-)ODr)C;}5n>mK1-L5;cr)US3 zCm7f`RE87oX8A`Wkx&1F!X5M=V8l-tsrb8RF7U961 zpt#62oEP#%GtERxIo!x8cW5)NdS`>55fZRc8|*si?lV)?8M7LLqQQ41Y2+w9pV3=V zbFswZHoEXWs%^CyEiH2*A-(zqu>Mqb_|`WePbP^NsnbVlFb1Mc&cA;lXz5~6K;gJT zMDBy(%`HgCx<-49T~~0;hY#hTL5FD<#+3Ckj7mX3zz<^EF{x}f(=BmCz(86QY> z{-m1uhQC@)=;2#!Nf;#L?SCJ!(~m^$dss6mHbFBly+0du<*V?V~VWl&v#il-ADvIN~r@m4<&jR{+J@_*x?K;E86ww<70c-YU7Lu#5 zIxztw z$S=T>cD?`URnTCM$kUq^U9IloXRX*~G=g({9mw&*92qUTgy; zIloGdA1GbV2GXbgTrDPP|GlRX4n7`|lG;tZSJ{F7zq`lbcw-4U^+dWYQ=JxQ&@`T& zMs-UuX+TK-{hbI2(5goxM`mAqLv~B&^};~m>wP*}*Pi!<2J%8yEqkdqKo&iq?bLl< znVT*{1@RRR``AfLFJ0HN>=0jWd|KMe;rh6>3b?dWHTkfo-b&wL<|Gwlgb~<_0A)<; z+2FAKEW>YO2P5KFji=~%Zq6>`F}43*<3FtFVU$`S%{Se)upeD-vbrbM6Palj1>w%}Q!w+4a9Bike>b`27jk3ISalk=v*#iiT^lJT8d*pYE zh5vA@{$|b;)@frv$%yj_CpRCxTT#C>D1dgW&>p# z^NReSVkTs;^uUEL3KBdR5BQr#gSX1%n=MG@7iadYL2Ygf5WR(!7{&{l8W5X&RXPlv z*$eiWAPSnO}V(K%teiD}KXh+)Df#b&zRH>GJk(UN*Ly0%nYExxgZ zE1>f>YUQz+_I?{Zuiw95?X*7EamD+ht`x(&!Dol2^{i$`K3?P1%{R63%*pMN$B1=+r5?Nol-EkD#Yp$L&j8QjW}Pps&(?xrdVogIrB|{m$GOUMOBu zCj1)AaqW&$5BDMXoF~Ezm(=7-*)#2)dW+YEem&AOAKkSBtHlwP9{qDx=ekgyb-YzS zKAj3s`iopUtrCT^0kQKn(fPUN@4+;wcv4i<{ z7KR+l&HTMu9A||a^bM0GwO$?1bV;PxNSw$~M3POR&E{TRY*^roC`vS{Wxa>Znsl{~>#( zB53NrFETY#^KiN3J1hwcWmaV2gVvdIi`fcjnW44qF$gy2_L%;bPwpI( zzkaxLadVgM1P~_S771bp#n|PLv$OCRuHHlm+#kclDK0)GcOAp%Yh>gK84h{Lt#y`1 zyOx^CK!sb=hz*>(Yd5Q-nY~`ZkJJoOM|4@TQntM?W#Xcc0KZlWizL$zVlM-ufFD74 zqVs-Um_?9Tb|o%|qBp6=|L4z!?Sf7zbX+_JbIyJe@3PQ0tyA7fSgv*iMa*1pcCfhJ z4-cAh89!1p>RSw#3iD-VJ^>%AJ@~XEtp~RA$9qpts%6A*zdEWU@gmykzs#5jZplvj z&9NhLewr3gDPj;xnK$ zfL^0yM^_Jfjk-PMDKYwZ)7*Q3i$TI6PQTP#J_P+{wHpm8Yr-!}>z-v*cyt|9sOx|# z$>@Slpcz{m$d!Qvy<3W>bN!k!vB861>Ge~yL`5qo` z&DS<2c0mMHQ-Z|Sa7DgzT}glvFEq8xyo~`}2f2uyKLq_jFB#W6oo*_6BDl*Fy~I2w zD1r!E>F`@`=W#2}bbQ>nyHYm`V%hPaUt`-ut((o};*jXmU*Gi`#*0m*h*?NtI}hoa zc|S)ysKR>CWmfy}zW>iqo*B^9Bsy8b5pQt+Y|m`mH!!<53HqkB1Q}4rAqVP2iS;%c z-@`LcrL$kdeZtbU3YwJLz5&5#71-boC@`8gfuJkwV*v)GfVcsDvo_WKu&GNt&@E>( zs!jUuE{lSeIbUfIRwFl}K7a~JVy{m%psVek>`D?-Im;q<6?CDbeo@ysCV1Uu4Rmm6 z2ld+k=~lZ;PTWYu&$P#uxnm7NLqnr=6n4lU)SnbukjFphm5pVCYJM{o083_$7>Y|m z;#u$WGW=y|($RD5iWo>>ubjRNeJpKeiLPpXSudmSlR)aoe}$Gw&&i? z@LuE!1bwA?4KR$nHtWpE?`k2*jc2&v; zH9j7+!7Md?(=|4=lSp?H-2U#W)C~hE-vuF0X1@q}k(*!x?Dm_0cHY*mWIwA8v3Wcc zp@49mRo_6EI@iETKZByA_?k|rdseA65NiudP577jbiE34xakS2c0_3tb2jDF5V$?) zP2^(xJkAu9X1g($2Qq=9RE-tEeOhK}73^FNE_n;vE_VLiuVhy1YO}$DaP}|-C1E?Y zB^R)(!ITV^n&xQ!#$R73-t^^dHX^KkOAGuU_RHL6CnknKf1`xU9;fyloxKHMbCw{3 z-(T%w(dXIYUK(T$JTGw<9W%epp?$|&X9dW?erY#@hr2vv_|wHr1hj1v;iJ8I)Ss9X z4)X6cevr;To!KHlmL=kD^tnIHi)(;lA57ZhQd r1T9q`0MFtZ_3~&ekNAZBM?OYmLGJvMhVy`jurqkN`njxgN@xNA7WvTl literal 0 HcmV?d00001 diff --git a/test/image/mocks/zz-multi-legends.json b/test/image/mocks/zz-multi-legends.json new file mode 100644 index 00000000000..32f39cc5e37 --- /dev/null +++ b/test/image/mocks/zz-multi-legends.json @@ -0,0 +1,63 @@ +{ + "data": [ + { + "y": [0] + }, + { + "y": [1] + }, + { + "y": [2] + }, + { + "y": [3], + "legendgroup": "2" + }, + { + "y": [4], + "legendgroup": "3" + }, + { + "y": [5], + "legendgroup": "3" + } + ], + "layout": { + "title": { + "text": "Multiple legends" + }, + "width": 500, + "height": 500, + "yaxis": { + "autorange": "reversed" + }, + "legend": { + "bgcolor": "lightgray", + "title": { + "text": "Legend" + } + }, + "legend2": { + "x": -0.05, + "y": 0.5, + "xanchor": "right", + "yanchor": "middle", + "bgcolor": "lightblue", + "title": { + "text": "Legend 2" + } + }, + "legend3": { + "y": 0, + "yanchor": "bottom", + "bgcolor": "yellow", + "title": { + "text": "Legend 3" + } + }, + "hovermode": "x unified" + }, + "config": { + "editable": true + } +} From 72c13544d85bbc58fee0a8e4f0464798540355bc Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Wed, 22 Mar 2023 09:01:04 -0400 Subject: [PATCH 07/15] add legend to traces - allow legendgroup to group inside each legend --- src/components/legend/defaults.js | 10 +- src/components/legend/draw.js | 7 +- src/components/legend/get_legend_data.js | 9 +- src/plots/attributes.js | 11 + src/plots/plots.js | 1 + src/traces/parcats/attributes.js | 1 + test/image/mocks/zz-multi-legends.json | 6 +- test/plot-schema.json | 329 +++++++++++++++++++++++ 8 files changed, 359 insertions(+), 15 deletions(-) diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index c45ca0afb62..8358a2d54cb 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -10,7 +10,7 @@ var basePlotLayoutAttributes = require('../../plots/layout_attributes'); var helpers = require('./helpers'); function getLegendName(id) { - return 'legend' + id; + return 'legend' + (id || ''); } function groupDefaults(id, layoutIn, layoutOut, fullData) { @@ -157,15 +157,15 @@ function groupDefaults(id, layoutIn, layoutOut, fullData) { module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { var i; - var groups = ['']; + var legends = [0]; for(i = 0; i < fullData.length; i++) { - Lib.pushUnique(groups, fullData[i].legendgroup); + Lib.pushUnique(legends, fullData[i].legend); } layoutOut._legends = []; - for(i = 0; i < groups.length; i++) { - var id = groups[i]; + for(i = 0; i < legends.length; i++) { + var id = legends[i]; var name = getLegendName(id); if(id && !layoutIn[name]) continue; diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index f8050467e20..e3c26957a0a 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -28,9 +28,10 @@ module.exports = function draw(gd, opts) { if(opts) { drawOne(gd, opts); } else { - var legendGroups = gd._fullLayout._legends; - for(var i = 0; i < legendGroups.length; i++) { - drawOne(gd, gd._fullLayout['legend' + legendGroups[i]]); + var legends = gd._fullLayout._legends; + for(var i = 0; i < legends.length; i++) { + var legendObj = gd._fullLayout['legend' + (legends[i] || '')]; + drawOne(gd, legendObj); } } }; diff --git a/src/components/legend/get_legend_data.js b/src/components/legend/get_legend_data.js index 070bea64d4d..d4123556120 100644 --- a/src/components/legend/get_legend_data.js +++ b/src/components/legend/get_legend_data.js @@ -16,8 +16,8 @@ module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { var maxNameLength = 0; var i, j; - function addOneItem(legendGroup, legendItem) { - if(hasMultipleLegends && legendGroup !== opts._id) return; + function addOneItem(legendId, legendGroup, legendItem) { + if(hasMultipleLegends && legendId !== opts._id) return; // each '' legend group is treated as a separate group if(legendGroup === '' || !helpers.isGrouped(opts)) { @@ -40,6 +40,7 @@ module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { var cd = calcdata[i]; var cd0 = cd[0]; var trace = cd0.trace; + var lid = trace.legend; var lgroup = trace.legendgroup; if(!inHover && (!trace.visible || !trace.showlegend)) continue; @@ -51,7 +52,7 @@ module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { var labelj = cd[j].label; if(!slicesShown[lgroup][labelj]) { - addOneItem(lgroup, { + addOneItem(lid, lgroup, { label: labelj, color: cd[j].color, i: cd[j].i, @@ -64,7 +65,7 @@ module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { } } } else { - addOneItem(lgroup, cd0); + addOneItem(lid, lgroup, cd0); maxNameLength = Math.max(maxNameLength, (trace.name || '').length); } } diff --git a/src/plots/attributes.js b/src/plots/attributes.js index 9f9952cbfc5..41b91643986 100644 --- a/src/plots/attributes.js +++ b/src/plots/attributes.js @@ -32,6 +32,17 @@ module.exports = { 'trace is shown in the legend.' ].join(' ') }, + legend: { + valType: 'number', + dflt: 0, + min: 2, + editType: 'style', + description: [ + 'Sets the legend id to show this trace in.', + 'If *0* (the default value), it refers to `layout.legend`.', + 'If *2*, it refers to `layout.legend2`, and so on.' + ].join(' ') + }, legendgroup: { valType: 'string', dflt: '', diff --git a/src/plots/plots.js b/src/plots/plots.js index 385df065112..45900550cfb 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1321,6 +1321,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac 'showlegend' ); + coerce('legend'); coerce('legendwidth'); coerce('legendgroup'); coerce('legendgrouptitle.text'); diff --git a/src/traces/parcats/attributes.js b/src/traces/parcats/attributes.js index cb0ddb4d912..f04f0c73921 100644 --- a/src/traces/parcats/attributes.js +++ b/src/traces/parcats/attributes.js @@ -197,6 +197,7 @@ module.exports = { customdata: undefined, hoverlabel: undefined, ids: undefined, + legend: undefined, legendgroup: undefined, legendrank: undefined, opacity: undefined, diff --git a/test/image/mocks/zz-multi-legends.json b/test/image/mocks/zz-multi-legends.json index 32f39cc5e37..b5f4365fa93 100644 --- a/test/image/mocks/zz-multi-legends.json +++ b/test/image/mocks/zz-multi-legends.json @@ -11,15 +11,15 @@ }, { "y": [3], - "legendgroup": "2" + "legend": 2 }, { "y": [4], - "legendgroup": "3" + "legend": 3 }, { "y": [5], - "legendgroup": "3" + "legend": 3 } ], "layout": { diff --git a/test/plot-schema.json b/test/plot-schema.json index 411afae1354..d3b82ef547e 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -12894,6 +12894,13 @@ "valType": "string" } }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -14421,6 +14428,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -15727,6 +15741,13 @@ "min": 0, "valType": "number" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -17071,6 +17092,13 @@ }, "role": "object" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -18591,6 +18619,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -19445,6 +19480,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -20444,6 +20486,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -21472,6 +21521,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -22676,6 +22732,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -23926,6 +23989,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -24887,6 +24957,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -25424,6 +25501,13 @@ "valType": "string" } }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -26857,6 +26941,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -27939,6 +28030,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -29082,6 +29180,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -29869,6 +29974,13 @@ "valType": "number" } }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -31839,6 +31951,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -33111,6 +33230,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -33874,6 +34000,13 @@ }, "role": "object" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -35095,6 +35228,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -35966,6 +36106,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -36999,6 +37146,13 @@ "editType": "calc", "valType": "number" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -38288,6 +38442,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -38916,6 +39077,13 @@ }, "role": "object" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -40390,6 +40558,13 @@ "bottom" ] }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -41591,6 +41766,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -42187,6 +42369,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -42657,6 +42846,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -43859,6 +44055,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -46216,6 +46419,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -48217,6 +48427,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -50110,6 +50327,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -52170,6 +52394,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -54173,6 +54404,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -55350,6 +55588,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -57265,6 +57510,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -59111,6 +59363,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -61024,6 +61283,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -62939,6 +63205,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -65133,6 +65406,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -65845,6 +66125,13 @@ }, "role": "object" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -67773,6 +68060,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -68678,6 +68972,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -69090,6 +69391,13 @@ "editType": "none", "valType": "string" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgrouptitle": { "editType": "style", "font": { @@ -70420,6 +70728,13 @@ "min": 0, "valType": "number" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -72235,6 +72550,13 @@ "editType": "calc", "valType": "number" }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", @@ -73080,6 +73402,13 @@ "valType": "string" } }, + "legend": { + "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 0, + "editType": "style", + "min": 2, + "valType": "number" + }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", "dflt": "", From df04d68c0a38096c8aec4d1e443cf19a1d333825 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 24 Mar 2023 12:31:16 -0400 Subject: [PATCH 08/15] revise legend dflt --- src/components/legend/defaults.js | 6 +- src/components/legend/draw.js | 6 +- src/plots/attributes.js | 6 +- test/plot-schema.json | 282 +++++++++++++++--------------- 4 files changed, 151 insertions(+), 149 deletions(-) diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 8358a2d54cb..8e6cddb31fb 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -10,7 +10,7 @@ var basePlotLayoutAttributes = require('../../plots/layout_attributes'); var helpers = require('./helpers'); function getLegendName(id) { - return 'legend' + (id || ''); + return 'legend' + (id > 1 ? id : ''); } function groupDefaults(id, layoutIn, layoutOut, fullData) { @@ -157,7 +157,7 @@ function groupDefaults(id, layoutIn, layoutOut, fullData) { module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { var i; - var legends = [0]; + var legends = [1]; for(i = 0; i < fullData.length; i++) { Lib.pushUnique(legends, fullData[i].legend); @@ -167,7 +167,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { for(i = 0; i < legends.length; i++) { var id = legends[i]; var name = getLegendName(id); - if(id && !layoutIn[name]) continue; + if(id > 1 && !layoutIn[name]) continue; groupDefaults(id, layoutIn, layoutOut, fullData); diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index e3c26957a0a..235854ddcd4 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -30,7 +30,8 @@ module.exports = function draw(gd, opts) { } else { var legends = gd._fullLayout._legends; for(var i = 0; i < legends.length; i++) { - var legendObj = gd._fullLayout['legend' + (legends[i] || '')]; + var id = legends[i]; + var legendObj = gd._fullLayout['legend' + (id > 1 ? id : '')]; drawOne(gd, legendObj); } } @@ -887,5 +888,6 @@ function getYanchor(legendObj) { } function getId(legendObj) { - return legendObj._id || ''; + var id = legendObj._id; + return id > 1 ? id : ''; } diff --git a/src/plots/attributes.js b/src/plots/attributes.js index 41b91643986..4377dac35aa 100644 --- a/src/plots/attributes.js +++ b/src/plots/attributes.js @@ -34,12 +34,12 @@ module.exports = { }, legend: { valType: 'number', - dflt: 0, - min: 2, + dflt: 1, + min: 1, editType: 'style', description: [ 'Sets the legend id to show this trace in.', - 'If *0* (the default value), it refers to `layout.legend`.', + 'If *1* (the default value), it refers to `layout.legend`.', 'If *2*, it refers to `layout.legend2`, and so on.' ].join(' ') }, diff --git a/test/plot-schema.json b/test/plot-schema.json index d3b82ef547e..55a9bf7ebb4 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -12895,10 +12895,10 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -14429,10 +14429,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -15742,10 +15742,10 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -17093,10 +17093,10 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -18620,10 +18620,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -19481,10 +19481,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -20487,10 +20487,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -21522,10 +21522,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -22733,10 +22733,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -23990,10 +23990,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -24958,10 +24958,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -25502,10 +25502,10 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -26942,10 +26942,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -28031,10 +28031,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -29181,10 +29181,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -29975,10 +29975,10 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -31952,10 +31952,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -33231,10 +33231,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -34001,10 +34001,10 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -35229,10 +35229,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -36107,10 +36107,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -37147,10 +37147,10 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -38443,10 +38443,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -39078,10 +39078,10 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -40559,10 +40559,10 @@ ] }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -41767,10 +41767,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -42370,10 +42370,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -42847,10 +42847,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -44056,10 +44056,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -46420,10 +46420,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -48428,10 +48428,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -50328,10 +50328,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -52395,10 +52395,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -54405,10 +54405,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -55589,10 +55589,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -57511,10 +57511,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -59364,10 +59364,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -61284,10 +61284,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -63206,10 +63206,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -65407,10 +65407,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -66126,10 +66126,10 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -68061,10 +68061,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -68973,10 +68973,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -69392,10 +69392,10 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgrouptitle": { @@ -70729,10 +70729,10 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -72551,10 +72551,10 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { @@ -73403,10 +73403,10 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *0* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 0, + "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", + "dflt": 1, "editType": "style", - "min": 2, + "min": 1, "valType": "number" }, "legendgroup": { From 7c95b4b695eb352e53865acb06da966ee27cc9fd Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 28 Mar 2023 12:24:35 -0400 Subject: [PATCH 09/15] revise legend valType - pass validate test --- src/components/legend/attributes.js | 5 + src/components/legend/defaults.js | 25 +- src/components/legend/draw.js | 65 ++-- src/plots/attributes.js | 14 +- tasks/test_mock.js | 3 +- test/image/mocks/zz-multi-legends.json | 6 +- test/jasmine/bundle_tests/plotschema_test.js | 1 + test/plot-schema.json | 377 ++++++++++--------- 8 files changed, 249 insertions(+), 247 deletions(-) diff --git a/src/components/legend/attributes.js b/src/components/legend/attributes.js index 3ef9b701e98..2691d56407f 100644 --- a/src/components/legend/attributes.js +++ b/src/components/legend/attributes.js @@ -5,6 +5,11 @@ var colorAttrs = require('../color/attributes'); module.exports = { + // not really a 'subplot' attribute container, + // but this is the flag we use to denote attributes that + // support yaxis, yaxis2, yaxis3, ... counters + _isSubplotObj: true, + bgcolor: { valType: 'color', editType: 'legend', diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 8e6cddb31fb..2458a02f4ab 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -9,14 +9,9 @@ var attributes = require('./attributes'); var basePlotLayoutAttributes = require('../../plots/layout_attributes'); var helpers = require('./helpers'); -function getLegendName(id) { - return 'legend' + (id > 1 ? id : ''); -} - -function groupDefaults(id, layoutIn, layoutOut, fullData) { - var name = getLegendName(id); - var containerIn = layoutIn[name] || {}; - var containerOut = Template.newContainer(layoutOut, name); +function groupDefaults(legendId, layoutIn, layoutOut, fullData) { + var containerIn = layoutIn[legendId] || {}; + var containerOut = Template.newContainer(layoutOut, legendId); function coerce(attr, dflt) { return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); @@ -157,7 +152,7 @@ function groupDefaults(id, layoutIn, layoutOut, fullData) { module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { var i; - var legends = [1]; + var legends = ['legend']; for(i = 0; i < fullData.length; i++) { Lib.pushUnique(legends, fullData[i].legend); @@ -165,16 +160,14 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { layoutOut._legends = []; for(i = 0; i < legends.length; i++) { - var id = legends[i]; - var name = getLegendName(id); - if(id > 1 && !layoutIn[name]) continue; + var legendId = legends[i]; - groupDefaults(id, layoutIn, layoutOut, fullData); + groupDefaults(legendId, layoutIn, layoutOut, fullData); - if(layoutOut[name]) { - layoutOut[name]._id = id; + if(layoutOut[legendId]) { + layoutOut[legendId]._id = legendId; } - layoutOut._legends.push(id); + layoutOut._legends.push(legendId); } }; diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 235854ddcd4..cd68c43d3af 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -30,8 +30,8 @@ module.exports = function draw(gd, opts) { } else { var legends = gd._fullLayout._legends; for(var i = 0; i < legends.length; i++) { - var id = legends[i]; - var legendObj = gd._fullLayout['legend' + (id > 1 ? id : '')]; + var legendId = legends[i]; + var legendObj = gd._fullLayout[legendId]; drawOne(gd, legendObj); } } @@ -41,7 +41,7 @@ function drawOne(gd, opts) { var legendObj = opts || {}; var fullLayout = gd._fullLayout; - var id = getId(legendObj); + var legendId = getId(legendObj); var clipId, layer; @@ -51,7 +51,7 @@ function drawOne(gd, opts) { clipId = 'hover'; } else { layer = fullLayout._infolayer; - clipId = 'legend' + id; + clipId = legendId; } if(!layer) return; clipId += fullLayout._uid; @@ -70,12 +70,12 @@ function drawOne(gd, opts) { var hiddenSlices = fullLayout.hiddenlabels || []; if(!inHover && (!fullLayout.showlegend || !legendData.length)) { - layer.selectAll('.legend' + id).remove(); + layer.selectAll('.' + legendId).remove(); fullLayout._topdefs.select('#' + clipId).remove(); - return Plots.autoMargin(gd, 'legend' + id); + return Plots.autoMargin(gd, legendId); } - var legend = Lib.ensureSingle(layer, 'g', 'legend' + id, function(s) { + var legend = Lib.ensureSingle(layer, 'g', legendId, function(s) { if(!inHover) s.attr('pointer-events', 'all'); }); @@ -96,14 +96,14 @@ function drawOne(gd, opts) { legendObj._titleWidth = 0; legendObj._titleHeight = 0; if(title.text) { - var titleEl = Lib.ensureSingle(scrollBox, 'text', 'legend' + id + 'titletext'); + var titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext'); titleEl.attr('text-anchor', 'start') .call(Drawing.font, title.font) .text(title.text); textLayout(titleEl, scrollBox, gd, legendObj, MAIN_TITLE); // handle mathjax or multi-line text and compute title height } else { - scrollBox.selectAll('.legend' + id + 'titletext').remove(); + scrollBox.selectAll('.' + legendId + 'titletext').remove(); } var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) { @@ -129,7 +129,7 @@ function drawOne(gd, opts) { }) .each(function() { d3.select(this).call(drawTexts, gd, legendObj); }) .call(style, gd, legendObj) - .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd, id); }); + .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd, legendId); }); Lib.syncOrAsync([ Plots.previousPromises, @@ -139,7 +139,7 @@ function drawOne(gd, opts) { var bw = legendObj.borderwidth; if(!inHover) { - var expMargin = expandMargin(gd, id); + var expMargin = expandMargin(gd, legendId); // IF expandMargin return a Promise (which is truthy), // we're under a doAutoMargin redraw, so we don't have to @@ -157,10 +157,10 @@ function drawOne(gd, opts) { ly = Lib.constrain(ly, 0, fullLayout.height - legendObj._effHeight); if(lx !== lx0) { - Lib.log('Constrain legend' + id + '.x to make legend fit inside graph'); + Lib.log('Constrain ' + legendId + '.x to make legend fit inside graph'); } if(ly !== ly0) { - Lib.log('Constrain legend' + id + '.y to make legend fit inside graph'); + Lib.log('Constrain ' + legendId + '.y to make legend fit inside graph'); } } @@ -306,7 +306,7 @@ function drawOne(gd, opts) { } function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) { - legendObj._scrollY = gd._fullLayout['legend' + id]._scrollY = scrollBoxY; + legendObj._scrollY = gd._fullLayout[legendId]._scrollY = scrollBoxY; Drawing.setTranslate(scrollBox, 0, -scrollBoxY); Drawing.setRect( @@ -343,8 +343,8 @@ function drawOne(gd, opts) { doneFn: function() { if(xf !== undefined && yf !== undefined) { var obj = {}; - obj['legend' + id + '.x'] = xf; - obj['legend' + id + '.y'] = yf; + obj[legendId + '.x'] = xf; + obj[legendId + '.y'] = yf; Registry.call('_guiRelayout', gd, obj); } }, @@ -417,7 +417,7 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) { } function drawTexts(g, gd, legendObj) { - var id = getId(legendObj); + var legendId = getId(legendObj); var legendItem = g.data()[0][0]; var trace = legendItem.trace; var isPieLike = Registry.traceIs(trace, 'pie-like'); @@ -440,7 +440,7 @@ function drawTexts(g, gd, legendObj) { } } - var textEl = Lib.ensureSingle(g, 'text', 'legend' + id + 'text'); + var textEl = Lib.ensureSingle(g, 'text', legendId + 'text'); textEl.attr('text-anchor', 'start') .call(Drawing.font, font) @@ -494,12 +494,12 @@ function ensureLength(str, maxLength) { return str; } -function setupTraceToggle(g, gd, id) { +function setupTraceToggle(g, gd, legendId) { var doubleClickDelay = gd._context.doubleClickDelay; var newMouseDownTime; var numClicks = 1; - var traceToggle = Lib.ensureSingle(g, 'rect', 'legend' + id + 'toggle', function(s) { + var traceToggle = Lib.ensureSingle(g, 'rect', legendId + 'toggle', function(s) { if(!gd._context.staticPlot) { s.style('cursor', 'pointer').attr('pointer-events', 'all'); } @@ -521,7 +521,7 @@ function setupTraceToggle(g, gd, id) { }); traceToggle.on('mouseup', function() { if(gd._dragged || gd._editing) return; - var legend = gd._fullLayout['legend' + id]; + var legend = gd._fullLayout[legendId]; if((new Date()).getTime() - gd._legendMouseDownTime > doubleClickDelay) { numClicks = Math.max(numClicks - 1, 1); @@ -548,9 +548,9 @@ function computeTextDimensions(g, gd, legendObj, aTitle) { var mathjaxGroup = g.select('g[class*=math-group]'); var mathjaxNode = mathjaxGroup.node(); - var id = getId(legendObj); + var legendId = getId(legendObj); if(!legendObj) { - legendObj = gd._fullLayout['legend' + id]; + legendObj = gd._fullLayout[legendId]; } var bw = legendObj.borderwidth; var font; @@ -576,7 +576,7 @@ function computeTextDimensions(g, gd, legendObj, aTitle) { Drawing.setTranslate(mathjaxGroup, 0, height * 0.25); } } else { - var cls = '.legend' + id + ( + var cls = '.' + legendId + ( aTitle === MAIN_TITLE ? 'title' : '' ) + 'text'; @@ -642,7 +642,7 @@ function getTitleSize(legendObj) { } /* - * Computes in fullLayout['legend' + id]: + * Computes in fullLayout[legendId]: * * - _height: legend height including items past scrollbox height * - _maxHeight: maximum legend height before scrollbox is required @@ -653,9 +653,9 @@ function getTitleSize(legendObj) { */ function computeLegendDimensions(gd, groups, traces, legendObj) { var fullLayout = gd._fullLayout; - var id = getId(legendObj); + var legendId = getId(legendObj); if(!legendObj) { - legendObj = fullLayout['legend' + id]; + legendObj = fullLayout[legendId]; } var gs = fullLayout._size; @@ -844,7 +844,7 @@ function computeLegendDimensions(gd, groups, traces, legendObj) { var edits = gd._context.edits; var isEditable = edits.legendText || edits.legendPosition; traces.each(function(d) { - var traceToggle = d3.select(this).select('.legend' + id + 'toggle'); + var traceToggle = d3.select(this).select('.' + legendId + 'toggle'); var h = d[0].height; var legendgroup = d[0].trace.legendgroup; var traceWidth = getTraceWidth(d, legendObj, textGap); @@ -859,13 +859,13 @@ function computeLegendDimensions(gd, groups, traces, legendObj) { }); } -function expandMargin(gd, id) { +function expandMargin(gd, legendId) { var fullLayout = gd._fullLayout; - var legendObj = fullLayout['legend' + id]; + var legendObj = fullLayout[legendId]; var xanchor = getXanchor(legendObj); var yanchor = getYanchor(legendObj); - return Plots.autoMargin(gd, 'legend' + id, { + return Plots.autoMargin(gd, legendId, { x: legendObj.x, y: legendObj.y, l: legendObj._width * (FROM_TL[xanchor]), @@ -888,6 +888,5 @@ function getYanchor(legendObj) { } function getId(legendObj) { - var id = legendObj._id; - return id > 1 ? id : ''; + return legendObj._id || 'legend'; } diff --git a/src/plots/attributes.js b/src/plots/attributes.js index 4377dac35aa..dc09610c596 100644 --- a/src/plots/attributes.js +++ b/src/plots/attributes.js @@ -2,6 +2,7 @@ var fontAttrs = require('./font_attributes'); var fxAttrs = require('../components/fx/attributes'); +var counterRegex = require('../lib/regex').counter; module.exports = { type: { @@ -33,14 +34,15 @@ module.exports = { ].join(' ') }, legend: { - valType: 'number', - dflt: 1, - min: 1, + valType: 'subplotid', + dflt: 'legend', editType: 'style', + regex: counterRegex('legend'), description: [ - 'Sets the legend id to show this trace in.', - 'If *1* (the default value), it refers to `layout.legend`.', - 'If *2*, it refers to `layout.legend2`, and so on.' + 'Sets the reference to a legend to show this trace in.', + 'References to these legends are *legend*, *legend2*, *legend3*, etc.', + 'Settings for these legends are set in the layout, under', + '`layout.legend`, `layout.legend2`, etc.' ].join(' ') }, legendgroup: { diff --git a/tasks/test_mock.js b/tasks/test_mock.js index 401e4e5eea4..11482ce2b1c 100644 --- a/tasks/test_mock.js +++ b/tasks/test_mock.js @@ -61,9 +61,10 @@ function assert(name, v) { var condition = ( e.code === 'invisible' || e.code === 'dynamic' || + e.path[e.path.length - 1] === 'legend' || e.path[e.path.length - 1] === 'coloraxis' ); - expectToBe(condition, true); // we accept invisible, dynamic and coloraxis for now + expectToBe(condition, true); // we accept invisible, dynamic, legend and coloraxis for now if(!condition) { console.log('file:', name); console.log(JSON.stringify(v, null, 2)); diff --git a/test/image/mocks/zz-multi-legends.json b/test/image/mocks/zz-multi-legends.json index b5f4365fa93..ad2d01466a9 100644 --- a/test/image/mocks/zz-multi-legends.json +++ b/test/image/mocks/zz-multi-legends.json @@ -11,15 +11,15 @@ }, { "y": [3], - "legend": 2 + "legend": "legend2" }, { "y": [4], - "legend": 3 + "legend": "legend3" }, { "y": [5], - "legend": 3 + "legend": "legend3" } ], "layout": { diff --git a/test/jasmine/bundle_tests/plotschema_test.js b/test/jasmine/bundle_tests/plotschema_test.js index 81139ab5f06..6d1f4546b3a 100644 --- a/test/jasmine/bundle_tests/plotschema_test.js +++ b/test/jasmine/bundle_tests/plotschema_test.js @@ -138,6 +138,7 @@ describe('plot schema', function() { // not really a 'subplot' object but supports yaxis, yaxis2, yaxis3, // ... counters, so list it here 'xaxis.rangeslider.yaxis', + 'legend', 'coloraxis' ]; diff --git a/test/plot-schema.json b/test/plot-schema.json index 55a9bf7ebb4..eadc23234dc 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -2743,6 +2743,7 @@ "role": "object" }, "legend": { + "_isSubplotObj": true, "bgcolor": { "description": "Sets the legend background color. Defaults to `layout.paper_bgcolor`.", "editType": "legend", @@ -12895,11 +12896,11 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -14429,11 +14430,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -15742,11 +15743,11 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -17093,11 +17094,11 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -18620,11 +18621,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -19481,11 +19482,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -20487,11 +20488,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -21522,11 +21523,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -22733,11 +22734,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -23990,11 +23991,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -24958,11 +24959,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -25502,11 +25503,11 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -26942,11 +26943,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -28031,11 +28032,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -29181,11 +29182,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -29975,11 +29976,11 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -31952,11 +31953,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -33231,11 +33232,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -34001,11 +34002,11 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -35229,11 +35230,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -36107,11 +36108,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -37147,11 +37148,11 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -38443,11 +38444,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -39078,11 +39079,11 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -40559,11 +40560,11 @@ ] }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -41767,11 +41768,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -42370,11 +42371,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -42847,11 +42848,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -44056,11 +44057,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -46420,11 +46421,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -48428,11 +48429,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -50328,11 +50329,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -52395,11 +52396,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -54405,11 +54406,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -55589,11 +55590,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -57511,11 +57512,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -59364,11 +59365,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -61284,11 +61285,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -63206,11 +63207,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -65407,11 +65408,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -66126,11 +66127,11 @@ "role": "object" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -68061,11 +68062,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -68973,11 +68974,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -69392,11 +69393,11 @@ "valType": "string" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgrouptitle": { "editType": "style", @@ -70729,11 +70730,11 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -72551,11 +72552,11 @@ "valType": "number" }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", @@ -73403,11 +73404,11 @@ } }, "legend": { - "description": "Sets the legend id to show this trace in. If *1* (the default value), it refers to `layout.legend`. If *2*, it refers to `layout.legend2`, and so on.", - "dflt": 1, + "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", + "dflt": "legend", "editType": "style", - "min": 1, - "valType": "number" + "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", + "valType": "subplotid" }, "legendgroup": { "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items.", From 3c468de1e2beda84fceb14c0e0a4fa0d5af2a954 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 28 Mar 2023 16:20:40 -0400 Subject: [PATCH 10/15] fix legend attribute and validate test --- src/plots/attributes.js | 3 +-- tasks/test_mock.js | 3 +-- test/plot-schema.json | 47 ----------------------------------------- 3 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/plots/attributes.js b/src/plots/attributes.js index dc09610c596..c76def47a14 100644 --- a/src/plots/attributes.js +++ b/src/plots/attributes.js @@ -2,7 +2,6 @@ var fontAttrs = require('./font_attributes'); var fxAttrs = require('../components/fx/attributes'); -var counterRegex = require('../lib/regex').counter; module.exports = { type: { @@ -37,7 +36,7 @@ module.exports = { valType: 'subplotid', dflt: 'legend', editType: 'style', - regex: counterRegex('legend'), + description: [ 'Sets the reference to a legend to show this trace in.', 'References to these legends are *legend*, *legend2*, *legend3*, etc.', diff --git a/tasks/test_mock.js b/tasks/test_mock.js index 11482ce2b1c..401e4e5eea4 100644 --- a/tasks/test_mock.js +++ b/tasks/test_mock.js @@ -61,10 +61,9 @@ function assert(name, v) { var condition = ( e.code === 'invisible' || e.code === 'dynamic' || - e.path[e.path.length - 1] === 'legend' || e.path[e.path.length - 1] === 'coloraxis' ); - expectToBe(condition, true); // we accept invisible, dynamic, legend and coloraxis for now + expectToBe(condition, true); // we accept invisible, dynamic and coloraxis for now if(!condition) { console.log('file:', name); console.log(JSON.stringify(v, null, 2)); diff --git a/test/plot-schema.json b/test/plot-schema.json index eadc23234dc..c6a4ba48c7c 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -12899,7 +12899,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -14433,7 +14432,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -15746,7 +15744,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -17097,7 +17094,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -18624,7 +18620,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -19485,7 +19480,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -20491,7 +20485,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -21526,7 +21519,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -22737,7 +22729,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -23994,7 +23985,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -24962,7 +24952,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -25506,7 +25495,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -26946,7 +26934,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -28035,7 +28022,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -29185,7 +29171,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -29979,7 +29964,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -31956,7 +31940,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -33235,7 +33218,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -34005,7 +33987,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -35233,7 +35214,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -36111,7 +36091,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -37151,7 +37130,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -38447,7 +38425,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -39082,7 +39059,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -40563,7 +40539,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -41771,7 +41746,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -42374,7 +42348,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -42851,7 +42824,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -44060,7 +44032,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -46424,7 +46395,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -48432,7 +48402,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -50332,7 +50301,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -52399,7 +52367,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -54409,7 +54376,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -55593,7 +55559,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -57515,7 +57480,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -59368,7 +59332,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -61288,7 +61251,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -63210,7 +63172,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -65411,7 +65372,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -66130,7 +66090,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -68065,7 +68024,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -68977,7 +68935,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -69396,7 +69353,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgrouptitle": { @@ -70733,7 +70689,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -72555,7 +72510,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { @@ -73407,7 +73361,6 @@ "description": "Sets the reference to a legend to show this trace in. References to these legends are *legend*, *legend2*, *legend3*, etc. Settings for these legends are set in the layout, under `layout.legend`, `layout.legend2`, etc.", "dflt": "legend", "editType": "style", - "regex": "/^legend([2-9]|[1-9][0-9]+)?$/", "valType": "subplotid" }, "legendgroup": { From 76b66121d81f57ddba6a569e20d44823e0d0d50d Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 28 Mar 2023 16:34:12 -0400 Subject: [PATCH 11/15] draft log for PR 6535 --- draftlogs/6535_add.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 draftlogs/6535_add.md diff --git a/draftlogs/6535_add.md b/draftlogs/6535_add.md new file mode 100644 index 00000000000..c4500a10fdf --- /dev/null +++ b/draftlogs/6535_add.md @@ -0,0 +1,3 @@ + - Add `legend` refrences to traces and `legend2`, `legend3`, etc. to layout + to allow positioning multiple legends on a graph [[#6535](https://github.com/plotly/plotly.js/pull/6535)], + this feature was anonymously sponsored: thank you to our sponsor! From 923ec2e686f7fec185b1b6e6c5e9fde5445ec8ce Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 28 Mar 2023 16:51:08 -0400 Subject: [PATCH 12/15] add visible to legend --- src/components/legend/attributes.js | 9 +++++++++ src/components/legend/defaults.js | 16 ++++++++++++---- src/components/legend/get_legend_data.js | 1 + test/plot-schema.json | 6 ++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/components/legend/attributes.js b/src/components/legend/attributes.js index 2691d56407f..135f1209b69 100644 --- a/src/components/legend/attributes.js +++ b/src/components/legend/attributes.js @@ -10,6 +10,15 @@ module.exports = { // support yaxis, yaxis2, yaxis3, ... counters _isSubplotObj: true, + visible: { + valType: 'boolean', + dflt: true, + editType: 'legend', + description: [ + 'Determines whether or not this legend is visible.' + ].join(' ') + }, + bgcolor: { valType: 'color', editType: 'legend', diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 2458a02f4ab..a3040f21bdc 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -17,6 +17,14 @@ function groupDefaults(legendId, layoutIn, layoutOut, fullData) { return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); } + // N.B. unified hover needs to inherit from font, bgcolor & bordercolor even when legend.visible is false + var itemFont = Lib.coerceFont(coerce, 'font', layoutOut.font); + coerce('bgcolor', layoutOut.paper_bgcolor); + coerce('bordercolor'); + + var visible = coerce('visible'); + if(!visible) return; + var trace; var traceCoerce = function(attr, dflt) { var traceIn = trace._input; @@ -90,10 +98,7 @@ function groupDefaults(legendId, layoutIn, layoutOut, fullData) { if(showLegend === false) return; - coerce('bgcolor', layoutOut.paper_bgcolor); - coerce('bordercolor'); coerce('borderwidth'); - var itemFont = Lib.coerceFont(coerce, 'font', layoutOut.font); var orientation = coerce('orientation'); var isHorizontal = orientation === 'h'; @@ -164,7 +169,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { groupDefaults(legendId, layoutIn, layoutOut, fullData); - if(layoutOut[legendId]) { + if( + layoutOut[legendId] && + layoutOut[legendId].visible + ) { layoutOut[legendId]._id = legendId; } diff --git a/src/components/legend/get_legend_data.js b/src/components/legend/get_legend_data.js index d4123556120..4bb7ec60f27 100644 --- a/src/components/legend/get_legend_data.js +++ b/src/components/legend/get_legend_data.js @@ -17,6 +17,7 @@ module.exports = function getLegendData(calcdata, opts, hasMultipleLegends) { var i, j; function addOneItem(legendId, legendGroup, legendItem) { + if(opts.visible === false) return; if(hasMultipleLegends && legendId !== opts._id) return; // each '' legend group is treated as a separate group diff --git a/test/plot-schema.json b/test/plot-schema.json index c6a4ba48c7c..e8fe9297497 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -2957,6 +2957,12 @@ "bottom" ] }, + "visible": { + "description": "Determines whether or not this legend is visible.", + "dflt": true, + "editType": "legend", + "valType": "boolean" + }, "x": { "description": "Sets the x position (in normalized coordinates) of the legend. Defaults to *1.02* for vertical legends and defaults to *0* for horizontal legends.", "editType": "legend", From b4bf884d083144b88e49551c85aa8b0de497931e Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com> Date: Wed, 29 Mar 2023 13:31:38 -0400 Subject: [PATCH 13/15] Update draftlogs/6535_add.md Co-authored-by: Liam Connors --- draftlogs/6535_add.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draftlogs/6535_add.md b/draftlogs/6535_add.md index c4500a10fdf..05b1d98d823 100644 --- a/draftlogs/6535_add.md +++ b/draftlogs/6535_add.md @@ -1,3 +1,3 @@ - - Add `legend` refrences to traces and `legend2`, `legend3`, etc. to layout + - Add `legend` references to traces and `legend2`, `legend3`, etc. to layout to allow positioning multiple legends on a graph [[#6535](https://github.com/plotly/plotly.js/pull/6535)], this feature was anonymously sponsored: thank you to our sponsor! From 8e8046174810f0efadc85a9813fb96d8148a3070 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 3 Apr 2023 19:34:50 -0400 Subject: [PATCH 14/15] no longer need to return from group defaults --- src/components/legend/defaults.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index a3040f21bdc..3906070cb1c 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -151,8 +151,6 @@ function groupDefaults(legendId, layoutIn, layoutOut, fullData) { Lib.coerceFont(coerce, 'title.font', dfltTitleFont); } - - return true; } module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { From d7f278aba67831646862d6f7df82b7d0335abaa9 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 24 Apr 2023 11:22:37 -0400 Subject: [PATCH 15/15] clear old legends for react calls --- src/components/legend/draw.js | 23 ++++++++++++++++--- test/jasmine/tests/legend_test.js | 38 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index cd68c43d3af..dcb9093b927 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -24,13 +24,30 @@ var helpers = require('./helpers'); var MAIN_TITLE = 1; +var LEGEND_PATTERN = /^legend[0-9]*$/; + module.exports = function draw(gd, opts) { if(opts) { drawOne(gd, opts); } else { - var legends = gd._fullLayout._legends; - for(var i = 0; i < legends.length; i++) { - var legendId = legends[i]; + var fullLayout = gd._fullLayout; + var newLegends = fullLayout._legends; + + // remove old legends that won't stay on the graph + var oldLegends = fullLayout._infolayer.selectAll('[class^="legend"]'); + + oldLegends.each(function() { + var el = d3.select(this); + var classes = el.attr('class'); + var cls = classes.split(' ')[0]; + if(cls.match(LEGEND_PATTERN) && newLegends.indexOf(cls) === -1) { + el.remove(); + } + }); + + // draw/update new legends + for(var i = 0; i < newLegends.length; i++) { + var legendId = newLegends[i]; var legendObj = gd._fullLayout[legendId]; drawOne(gd, legendObj); } diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index 0f7a1ceb99b..5172048bcd0 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -1122,6 +1122,44 @@ describe('legend relayout update', function() { }) .then(done, done.fail); }); + + it('should be able to add & clear multiple legends using react', function(done) { + var fig1 = { + data: [{ + y: [1, 2, 3] + }] + }; + + var fig2 = { + data: [{ + y: [1, 2, 3] + }, { + y: [3, 1, 2], + legend: 'legend2' + }], + layout: { + legend2: {y: 0.5} + } + }; + + Plotly.newPlot(gd, fig1) + .then(function() { + expect(d3SelectAll('.legend2')[0].length).toBe(0); + }) + .then(function() { + return Plotly.react(gd, fig2); + }) + .then(function() { + expect(d3SelectAll('.legend2')[0].length).toBe(1); + }) + .then(function() { + return Plotly.react(gd, fig1); + }) + .then(function() { + expect(d3SelectAll('.legend2')[0].length).toBe(0); + }) + .then(done, done.fail); + }); }); describe('legend orientation change:', function() {