From bb6051097da808d7a14791a264059f2c776e4bcf Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 22 Jul 2016 10:52:35 -0800 Subject: [PATCH 01/11] Might fix #769 - added check for pushing past plot margin and starting new row of legend items --- src/components/legend/draw.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 4a81fb12f1d..1fe9906932a 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -568,18 +568,33 @@ function computeLegendDimensions(gd, groups, traces) { else { opts.width = 0; opts.height = 0; + var rowHeight = 0; + var maxTraceHeight = 0; + var startX = 0; traces.each(function(d) { + var legendItem = d[0], traceWidth = 40 + legendItem.width, traceGap = opts.tracegroupgap || 5; - Lib.setTranslate(this, - (borderwidth + opts.width), - (5 + borderwidth + legendItem.height / 2)); + if((borderwidth + startX + traceGap + traceWidth) > fullLayout.width - fullLayout.margin.r) { + startX = 0; + rowHeight = rowHeight + maxTraceHeight; + opts.height = opts.height + maxTraceHeight; + } opts.width += traceGap + traceWidth; opts.height = Math.max(opts.height, legendItem.height); + + Lib.setTranslate(this, + (borderwidth + startX), + (5 + borderwidth + legendItem.height / 2) + rowHeight); + + + //keep track of tallest trace in group + startX += traceGap + traceWidth; + maxTraceHeight = (legendItem.height > maxTraceHeight) ? legendItem.height : maxTraceHeight; }); opts.width += borderwidth * 2; From 5f385957f0a0ca860720a06c0df33bae52503923 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 22 Jul 2016 11:23:44 -0800 Subject: [PATCH 02/11] linted --- src/components/legend/draw.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 1fe9906932a..79e83cfe99b 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -579,9 +579,9 @@ function computeLegendDimensions(gd, groups, traces) { traceGap = opts.tracegroupgap || 5; if((borderwidth + startX + traceGap + traceWidth) > fullLayout.width - fullLayout.margin.r) { - startX = 0; - rowHeight = rowHeight + maxTraceHeight; - opts.height = opts.height + maxTraceHeight; + startX = 0; + rowHeight = rowHeight + maxTraceHeight; + opts.height = opts.height + maxTraceHeight; } opts.width += traceGap + traceWidth; From 5b5a102874974be5d726bc7ef6edf54c16746de7 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 22 Jul 2016 11:27:33 -0800 Subject: [PATCH 03/11] code in original order --- src/components/legend/draw.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 79e83cfe99b..5d0f928fa0d 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -584,13 +584,12 @@ function computeLegendDimensions(gd, groups, traces) { opts.height = opts.height + maxTraceHeight; } - opts.width += traceGap + traceWidth; - opts.height = Math.max(opts.height, legendItem.height); - Lib.setTranslate(this, (borderwidth + startX), (5 + borderwidth + legendItem.height / 2) + rowHeight); + opts.width += traceGap + traceWidth; + opts.height = Math.max(opts.height, legendItem.height); //keep track of tallest trace in group startX += traceGap + traceWidth; From d0934f3d3f42c05e13f941e0604101ac5484fdac Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 25 Jul 2016 10:58:48 -0800 Subject: [PATCH 04/11] changes based on @n-riesco comments --- src/components/legend/draw.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 5d0f928fa0d..62d2d842845 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -568,9 +568,9 @@ function computeLegendDimensions(gd, groups, traces) { else { opts.width = 0; opts.height = 0; - var rowHeight = 0; - var maxTraceHeight = 0; - var startX = 0; + var rowHeight = 0, + maxTraceHeight = 0, + offsetX = 0; traces.each(function(d) { @@ -578,22 +578,24 @@ function computeLegendDimensions(gd, groups, traces) { traceWidth = 40 + legendItem.width, traceGap = opts.tracegroupgap || 5; - if((borderwidth + startX + traceGap + traceWidth) > fullLayout.width - fullLayout.margin.r) { - startX = 0; + if((borderwidth + offsetX + traceGap + traceWidth) > fullLayout.width - fullLayout.margin.r) { + offsetX = 0; rowHeight = rowHeight + maxTraceHeight; opts.height = opts.height + maxTraceHeight; + //reset for next row + maxTraceHeight = 0; } Lib.setTranslate(this, - (borderwidth + startX), + (borderwidth + offsetX), (5 + borderwidth + legendItem.height / 2) + rowHeight); opts.width += traceGap + traceWidth; opts.height = Math.max(opts.height, legendItem.height); //keep track of tallest trace in group - startX += traceGap + traceWidth; - maxTraceHeight = (legendItem.height > maxTraceHeight) ? legendItem.height : maxTraceHeight; + offsetX += traceGap + traceWidth; + maxTraceHeight = Math.max(legendItem.height, maxTraceHeight); }); opts.width += borderwidth * 2; From e7a286fc4abdbd04da39ee21e5b4e6977a1719db Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 25 Jul 2016 13:57:01 -0800 Subject: [PATCH 05/11] need both margins for proper wrapping --- 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 62d2d842845..8321e4072e5 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -578,7 +578,7 @@ function computeLegendDimensions(gd, groups, traces) { traceWidth = 40 + legendItem.width, traceGap = opts.tracegroupgap || 5; - if((borderwidth + offsetX + traceGap + traceWidth) > fullLayout.width - fullLayout.margin.r) { + if((borderwidth + offsetX + traceGap + traceWidth) > (fullLayout.width - (fullLayout.margin.r + fullLayout.margin.l))) { offsetX = 0; rowHeight = rowHeight + maxTraceHeight; opts.height = opts.height + maxTraceHeight; From 91d384ba0c3cd958366f6000445b34b316673fa4 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 26 Jul 2016 09:50:22 -0800 Subject: [PATCH 06/11] put horizontal legend traces in columns --- src/components/legend/draw.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 8321e4072e5..1a7a063d470 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -570,12 +570,18 @@ function computeLegendDimensions(gd, groups, traces) { opts.height = 0; var rowHeight = 0, maxTraceHeight = 0, + maxTraceWidth = 0, offsetX = 0; + //calculate largest width for traces and use for width of all legend items + traces.each(function(d) { + maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); + }); + traces.each(function(d) { var legendItem = d[0], - traceWidth = 40 + legendItem.width, + traceWidth = maxTraceWidth, traceGap = opts.tracegroupgap || 5; if((borderwidth + offsetX + traceGap + traceWidth) > (fullLayout.width - (fullLayout.margin.r + fullLayout.margin.l))) { From 8d6299fb01468b7437e9bb6fcfd84daa5b843807 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Wed, 27 Jul 2016 09:28:14 -0800 Subject: [PATCH 07/11] lint --- 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 1a7a063d470..0e8d9f88600 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -575,7 +575,7 @@ function computeLegendDimensions(gd, groups, traces) { //calculate largest width for traces and use for width of all legend items traces.each(function(d) { - maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); + maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); }); traces.each(function(d) { From 3a2cf7ba56337542fe17467ca4c934b9fb374e5e Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 28 Jul 2016 11:14:56 -0800 Subject: [PATCH 08/11] image mock and test --- .../mocks/legend_horizontal_autowrap.json | 542 ++++++++++++++++++ test/jasmine/tests/legend_test.js | 70 +++ 2 files changed, 612 insertions(+) create mode 100644 test/image/mocks/legend_horizontal_autowrap.json diff --git a/test/image/mocks/legend_horizontal_autowrap.json b/test/image/mocks/legend_horizontal_autowrap.json new file mode 100644 index 00000000000..1e682eb2149 --- /dev/null +++ b/test/image/mocks/legend_horizontal_autowrap.json @@ -0,0 +1,542 @@ +{ + "data": [ + { + "x": [1, 2, 3, 4], + "y": [63.69, 62.55, 61.64, 61.39], + "text": ["FiscalYear: 2012
Percent: 63.69
Students: 1235
Race: 1
Race: Average", "FiscalYear: 2013
Percent: 62.55
Students: 1149
Race: 1
Race: Average", "FiscalYear: 2014
Percent: 61.64
Students: 1080
Race: 1
Race: Average", "FiscalYear: 2015
Percent: 61.39
Students: 1035
Race: 1
Race: Average"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Average", + "line": { + "width": 1.8898, + "color": "rgba(0,0,0,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [58.24, 54.93, 42.11, 50.75], + "text": ["FiscalYear: 2012
Percent: 58.24
Students: 53
Race: 2
Race: African American", "FiscalYear: 2013
Percent: 54.93
Students: 39
Race: 2
Race: African American", "FiscalYear: 2014
Percent: 42.11
Students: 32
Race: 2
Race: African American", "FiscalYear: 2015
Percent: 50.75
Students: 34
Race: 2
Race: African American"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "African American", + "line": { + "width": 1.8898, + "color": "rgba(248,118,109,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [51.49, 49.59, 37.12, 31.45], + "text": ["FiscalYear: 2012
Percent: 51.49
Students: 69
Race: 3
Race: Alaska Native", "FiscalYear: 2013
Percent: 49.59
Students: 60
Race: 3
Race: Alaska Native", "FiscalYear: 2014
Percent: 37.12
Students: 49
Race: 3
Race: Alaska Native", "FiscalYear: 2015
Percent: 31.45
Students: 39
Race: 3
Race: Alaska Native"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Alaska Native", + "line": { + "width": 1.8898, + "color": "rgba(216,144,0,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [49.09, 58.54, 53.91, 43.12], + "text": ["FiscalYear: 2012
Percent: 49.09
Students: 54
Race: 4
Race: Alaska Native Multirace", "FiscalYear: 2013
Percent: 58.54
Students: 72
Race: 4
Race: Alaska Native Multirace", "FiscalYear: 2014
Percent: 53.91
Students: 62
Race: 4
Race: Alaska Native Multirace", "FiscalYear: 2015
Percent: 43.12
Students: 47
Race: 4
Race: Alaska Native Multirace"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Alaska Native Multirace", + "line": { + "width": 1.8898, + "color": "rgba(163,165,0,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [70.53, 72.51, 72.28, 78.65], + "text": ["FiscalYear: 2012
Percent: 70.53
Students: 146
Race: 5
Race: Asian", "FiscalYear: 2013
Percent: 72.51
Students: 124
Race: 5
Race: Asian", "FiscalYear: 2014
Percent: 72.28
Students: 133
Race: 5
Race: Asian", "FiscalYear: 2015
Percent: 78.65
Students: 140
Race: 5
Race: Asian"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Asian", + "line": { + "width": 1.8898, + "color": "rgba(57,182,0,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [62.69, 59.09, 63.82, 62], + "text": ["FiscalYear: 2012
Percent: 62.69
Students: 84
Race: 6
Race: Hispanic", "FiscalYear: 2013
Percent: 59.09
Students: 91
Race: 6
Race: Hispanic", "FiscalYear: 2014
Percent: 63.82
Students: 97
Race: 6
Race: Hispanic", "FiscalYear: 2015
Percent: 62
Students: 93
Race: 6
Race: Hispanic"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Hispanic", + "line": { + "width": 1.8898, + "color": "rgba(0,191,125,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [76.27, 71.43, 59.83, 64.34], + "text": ["FiscalYear: 2012
Percent: 76.27
Students: 90
Race: 7
Race: Non Hispanic Multirace", "FiscalYear: 2013
Percent: 71.43
Students: 95
Race: 7
Race: Non Hispanic Multirace", "FiscalYear: 2014
Percent: 59.83
Students: 70
Race: 7
Race: Non Hispanic Multirace", "FiscalYear: 2015
Percent: 64.34
Students: 83
Race: 7
Race: Non Hispanic Multirace"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Non Hispanic Multirace", + "line": { + "width": 1.8898, + "color": "rgba(0,191,196,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [71.15, 81.82, 88.46, 74.29], + "text": ["FiscalYear: 2012
Percent: 71.15
Students: 37
Race: 8
Race: Non Resident Alien", "FiscalYear: 2013
Percent: 81.82
Students: 27
Race: 8
Race: Non Resident Alien", "FiscalYear: 2014
Percent: 88.46
Students: 23
Race: 8
Race: Non Resident Alien", "FiscalYear: 2015
Percent: 74.29
Students: 26
Race: 8
Race: Non Resident Alien"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Non Resident Alien", + "line": { + "width": 1.8898, + "color": "rgba(0,176,246,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [57.89, 57.38, 52.08, 63.83], + "text": ["FiscalYear: 2012
Percent: 57.89
Students: 44
Race: 9
Race: Unknown", "FiscalYear: 2013
Percent: 57.38
Students: 35
Race: 9
Race: Unknown", "FiscalYear: 2014
Percent: 52.08
Students: 25
Race: 9
Race: Unknown", "FiscalYear: 2015
Percent: 63.83
Students: 30
Race: 9
Race: Unknown"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "Unknown", + "line": { + "width": 1.8898, + "color": "rgba(149,144,255,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [65.4, 63.27, 65.78, 64.03], + "text": ["FiscalYear: 2012
Percent: 65.4
Students: 635
Race: 10
Race: White", "FiscalYear: 2013
Percent: 63.27
Students: 577
Race: 10
Race: White", "FiscalYear: 2014
Percent: 65.78
Students: 571
Race: 10
Race: White", "FiscalYear: 2015
Percent: 64.03
Students: 518
Race: 10
Race: White"], + "key": null, + "type": "scatter", + "mode": "lines", + "name": "White", + "line": { + "width": 1.8898, + "color": "rgba(231,107,243,1)", + "dash": "solid" + }, + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [63.69, 62.55, 61.64, 61.39], + "text": ["FiscalYear: 2012
Percent: 63.69
Students: 1235
Race: Average", "FiscalYear: 2013
Percent: 62.55
Students: 1149
Race: Average", "FiscalYear: 2014
Percent: 61.64
Students: 1080
Race: Average", "FiscalYear: 2015
Percent: 61.39
Students: 1035
Race: Average"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(0,0,0,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(0,0,0,1)" + } + }, + "name": "Average", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [58.24, 54.93, 42.11, 50.75], + "text": ["FiscalYear: 2012
Percent: 58.24
Students: 53
Race: African American", "FiscalYear: 2013
Percent: 54.93
Students: 39
Race: African American", "FiscalYear: 2014
Percent: 42.11
Students: 32
Race: African American", "FiscalYear: 2015
Percent: 50.75
Students: 34
Race: African American"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(248,118,109,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(248,118,109,1)" + } + }, + "name": "African American", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [51.49, 49.59, 37.12, 31.45], + "text": ["FiscalYear: 2012
Percent: 51.49
Students: 69
Race: Alaska Native", "FiscalYear: 2013
Percent: 49.59
Students: 60
Race: Alaska Native", "FiscalYear: 2014
Percent: 37.12
Students: 49
Race: Alaska Native", "FiscalYear: 2015
Percent: 31.45
Students: 39
Race: Alaska Native"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(216,144,0,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(216,144,0,1)" + } + }, + "name": "Alaska Native", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [49.09, 58.54, 53.91, 43.12], + "text": ["FiscalYear: 2012
Percent: 49.09
Students: 54
Race: Alaska Native Multirace", "FiscalYear: 2013
Percent: 58.54
Students: 72
Race: Alaska Native Multirace", "FiscalYear: 2014
Percent: 53.91
Students: 62
Race: Alaska Native Multirace", "FiscalYear: 2015
Percent: 43.12
Students: 47
Race: Alaska Native Multirace"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(163,165,0,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(163,165,0,1)" + } + }, + "name": "Alaska Native Multirace", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [70.53, 72.51, 72.28, 78.65], + "text": ["FiscalYear: 2012
Percent: 70.53
Students: 146
Race: Asian", "FiscalYear: 2013
Percent: 72.51
Students: 124
Race: Asian", "FiscalYear: 2014
Percent: 72.28
Students: 133
Race: Asian", "FiscalYear: 2015
Percent: 78.65
Students: 140
Race: Asian"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(57,182,0,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(57,182,0,1)" + } + }, + "name": "Asian", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [62.69, 59.09, 63.82, 62], + "text": ["FiscalYear: 2012
Percent: 62.69
Students: 84
Race: Hispanic", "FiscalYear: 2013
Percent: 59.09
Students: 91
Race: Hispanic", "FiscalYear: 2014
Percent: 63.82
Students: 97
Race: Hispanic", "FiscalYear: 2015
Percent: 62
Students: 93
Race: Hispanic"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(0,191,125,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(0,191,125,1)" + } + }, + "name": "Hispanic", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [76.27, 71.43, 59.83, 64.34], + "text": ["FiscalYear: 2012
Percent: 76.27
Students: 90
Race: Non Hispanic Multirace", "FiscalYear: 2013
Percent: 71.43
Students: 95
Race: Non Hispanic Multirace", "FiscalYear: 2014
Percent: 59.83
Students: 70
Race: Non Hispanic Multirace", "FiscalYear: 2015
Percent: 64.34
Students: 83
Race: Non Hispanic Multirace"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(0,191,196,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(0,191,196,1)" + } + }, + "name": "Non Hispanic Multirace", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [71.15, 81.82, 88.46, 74.29], + "text": ["FiscalYear: 2012
Percent: 71.15
Students: 37
Race: Non Resident Alien", "FiscalYear: 2013
Percent: 81.82
Students: 27
Race: Non Resident Alien", "FiscalYear: 2014
Percent: 88.46
Students: 23
Race: Non Resident Alien", "FiscalYear: 2015
Percent: 74.29
Students: 26
Race: Non Resident Alien"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(0,176,246,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(0,176,246,1)" + } + }, + "name": "Non Resident Alien", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [57.89, 57.38, 52.08, 63.83], + "text": ["FiscalYear: 2012
Percent: 57.89
Students: 44
Race: Unknown", "FiscalYear: 2013
Percent: 57.38
Students: 35
Race: Unknown", "FiscalYear: 2014
Percent: 52.08
Students: 25
Race: Unknown", "FiscalYear: 2015
Percent: 63.83
Students: 30
Race: Unknown"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(149,144,255,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(149,144,255,1)" + } + }, + "name": "Unknown", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + }, + { + "x": [1, 2, 3, 4], + "y": [65.4, 63.27, 65.78, 64.03], + "text": ["FiscalYear: 2012
Percent: 65.4
Students: 635
Race: White", "FiscalYear: 2013
Percent: 63.27
Students: 577
Race: White", "FiscalYear: 2014
Percent: 65.78
Students: 571
Race: White", "FiscalYear: 2015
Percent: 64.03
Students: 518
Race: White"], + "key": null, + "type": "scatter", + "mode": "markers", + "marker": { + "autocolorscale": false, + "color": "rgba(231,107,243,1)", + "opacity": 1, + "size": 5.6693, + "symbol": "circle", + "line": { + "width": 1.8898, + "color": "rgba(231,107,243,1)" + } + }, + "name": "White", + "showlegend": true, + "xaxis": "x", + "yaxis": "y", + "hoverinfo": "text" + } + ], + "layout": { + "margin": { + "t": 34.8976, + "r": 75.5906, + "b": 51.243, + "l": 57.6191 + }, + "plot_bgcolor": "rgba(255,255,255,1)", + "paper_bgcolor": "rgba(255,255,255,1)", + "font": { + "color": "rgba(34,34,34,1)", + "family": "Roboto", + "size": 15.9402 + }, + "xaxis": { + "type": "linear", + "autorange": false, + "tickmode": "array", + "range": [0.4, 4.6], + "ticktext": ["2012", "2013", "2014", "2015"], + "tickvals": [1, 2, 3, 4], + "ticks": "", + "tickcolor": null, + "ticklen": 3.653, + "tickwidth": 0, + "showticklabels": true, + "tickfont": { + "color": "rgba(77,77,77,1)", + "family": "Roboto", + "size": 12.7522 + }, + "tickangle": -0, + "showline": false, + "linecolor": null, + "linewidth": 0, + "showgrid": true, + "domain": [0, 1], + "gridcolor": "rgba(216,216,216,1)", + "gridwidth": 0.6642, + "zeroline": false, + "anchor": "y", + "title": "Fiscal year", + "titlefont": { + "color": "rgba(34,34,34,1)", + "family": "Roboto", + "size": 15.9402 + }, + "hoverformat": ".2f" + }, + "yaxis": { + "type": "linear", + "autorange": false, + "tickmode": "array", + "range": [-5, 105], + "ticktext": ["0", "25", "50", "75", "100"], + "tickvals": [0, 25, 50, 75, 100], + "ticks": "", + "tickcolor": null, + "ticklen": 3.653, + "tickwidth": 0, + "showticklabels": true, + "tickfont": { + "color": "rgba(77,77,77,1)", + "family": "Roboto", + "size": 12.7522 + }, + "tickangle": -0, + "showline": false, + "linecolor": null, + "linewidth": 0, + "showgrid": true, + "domain": [0, 1], + "gridcolor": "rgba(216,216,216,1)", + "gridwidth": 0.6642, + "zeroline": false, + "anchor": "x", + "title": "% of students", + "titlefont": { + "color": "rgba(34,34,34,1)", + "family": "Roboto", + "size": 15.9402 + }, + "hoverformat": ".2f" + }, + "shapes": [ + { + "type": "rect", + "fillcolor": "transparent", + "line": { + "color": "rgba(0,0,0,1)", + "width": 0, + "linetype": "solid" + }, + "yref": "paper", + "xref": "paper", + "x0": 0, + "x1": 1, + "y0": 0, + "y1": 1 + } + ], + "showlegend": true, + "legend": { + "bgcolor": "rgba(255,255,255,1)", + "bordercolor": "transparent", + "borderwidth": 1.8898, + "font": { + "color": "rgba(34,34,34,1)", + "family": "Roboto", + "size": 11.9552 + }, + "y": -0.4, + "orientation": "h" + }, + "hovermode": "closest", + "width": 680, + "height": 450 + } +} diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index 1e6b3490aa8..f39a604de29 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -540,3 +540,73 @@ describe('legend relayout update', function() { }); }); }); + +describe('legend orientation change:', function() { + 'use strict'; + + var mock = require('@mocks/legend_horizontal_autowrap.json'), + gd, + node; + + beforeEach(function(done) { + gd = createGraphDiv(); + Plotly.plot(gd, mock.data, mock.layout).then(function() { + node = d3.select('g.legend').select('rect'); + done(); + }); + }); + + afterEach(destroyGraphDiv); + + it('horizontal with lots of items wraps traces to new lines', function(done) { + var nw = node.property('width').baseVal.value; + var gw = mock.layout.width; + var maxTraceHeight = 0, + maxTraceWidth = 0, + maxOffsetX = 0, + maxOffsetY = 0, + traceGap = gd._fullLayout.legend.tracegroupgap || 5; + + d3.selectAll('g.legend g.traces').each(function() { + var b = d3.select(this).select('text').node().getBBox(), + w = b.width + traceGap + 40, + h = d3.select(this).node().getBBox().height, + t = d3.transform(d3.select(this).attr('transform')); + //console.log(t.translate[0], t.translate[1], w, h); + maxOffsetX = Math.max(maxOffsetX, t.translate[0]); + maxOffsetY = Math.max(maxOffsetY, t.translate[1]); + maxTraceWidth = Math.max(maxTraceWidth, w); + maxTraceHeight = Math.max(maxTraceHeight, h); + }); + + //legend rect less than width of plot + expect(nw).toBeLessThan(gw); + expect(maxTraceHeight).toBeGreaterThan(0); + expect(maxTraceWidth).toBeGreaterThan(0); + expect(maxOffsetX).toBeGreaterThan(0); + expect(maxOffsetY).toBeGreaterThan(0); + + //none of the traces are pushed off the graph + expect(maxOffsetX).toBeLessThan(mock.layout.width); + expect(maxOffsetY).toBeLessThan(mock.layout.height); + + done(); + }); + + it('changing to vertical orientation', function(done) { + //change mock layout and refresh graph + mock.layout.legend.orientation = 'v'; + mock.layout.legend.y = 1; + done(); + }); + + it('changed to vertical, scrollbar appeared', function(done) { + //changed orientation to vertical + expect(gd._fullLayout.legend.orientation).toBe('v'); + //scrollbar has width and height now + var bbox = d3.select('rect.scrollbar').node().getBBox(); + expect(bbox.width).toBeGreaterThan(0); + expect(bbox.height).toBeGreaterThan(0); + done(); + }); +}); From e1225fa45c497944f27eba7b1ef5bdd241a1b5e6 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 30 Jul 2016 13:01:06 -0800 Subject: [PATCH 09/11] add image test --- .../baselines/legend_horizontal_autowrap.png | Bin 0 -> 48419 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/image/baselines/legend_horizontal_autowrap.png diff --git a/test/image/baselines/legend_horizontal_autowrap.png b/test/image/baselines/legend_horizontal_autowrap.png new file mode 100644 index 0000000000000000000000000000000000000000..afd09cf300e8d7cb4369225fccab7696659f04c5 GIT binary patch literal 48419 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 Date: Tue, 2 Aug 2016 10:51:22 -0800 Subject: [PATCH 10/11] test rewrite per request --- test/jasmine/tests/legend_test.js | 120 +++++++++++++++--------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index f39a604de29..7c6ad3148d6 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -544,69 +544,71 @@ describe('legend relayout update', function() { describe('legend orientation change:', function() { 'use strict'; - var mock = require('@mocks/legend_horizontal_autowrap.json'), - gd, - node; - - beforeEach(function(done) { - gd = createGraphDiv(); - Plotly.plot(gd, mock.data, mock.layout).then(function() { - node = d3.select('g.legend').select('rect'); - done(); - }); - }); - afterEach(destroyGraphDiv); - it('horizontal with lots of items wraps traces to new lines', function(done) { - var nw = node.property('width').baseVal.value; - var gw = mock.layout.width; - var maxTraceHeight = 0, - maxTraceWidth = 0, - maxOffsetX = 0, - maxOffsetY = 0, - traceGap = gd._fullLayout.legend.tracegroupgap || 5; - - d3.selectAll('g.legend g.traces').each(function() { - var b = d3.select(this).select('text').node().getBBox(), - w = b.width + traceGap + 40, - h = d3.select(this).node().getBBox().height, - t = d3.transform(d3.select(this).attr('transform')); - //console.log(t.translate[0], t.translate[1], w, h); - maxOffsetX = Math.max(maxOffsetX, t.translate[0]); - maxOffsetY = Math.max(maxOffsetY, t.translate[1]); - maxTraceWidth = Math.max(maxTraceWidth, w); - maxTraceHeight = Math.max(maxTraceHeight, h); - }); - - //legend rect less than width of plot - expect(nw).toBeLessThan(gw); - expect(maxTraceHeight).toBeGreaterThan(0); - expect(maxTraceWidth).toBeGreaterThan(0); - expect(maxOffsetX).toBeGreaterThan(0); - expect(maxOffsetY).toBeGreaterThan(0); + it('should update legend orientation', function(done) { + var mock = require('@mocks/legend_horizontal_autowrap.json'), + gd = createGraphDiv(), + initialLegendY = mock.layout.legend.y; - //none of the traces are pushed off the graph - expect(maxOffsetX).toBeLessThan(mock.layout.width); - expect(maxOffsetY).toBeLessThan(mock.layout.height); - - done(); - }); + Plotly.plot(gd, mock.data, mock.layout).then(function() { + var node = d3.select('g.legend').select('rect'), + nw = node.property('width').baseVal.value, + gw = mock.layout.width, + maxTraceHeight = 0, + maxTraceWidth = 0, + maxOffsetX = 0, + maxOffsetY = 0, + traceGap = gd._fullLayout.legend.tracegroupgap || 5; + + d3.selectAll('g.legend g.traces').each(function() { + var b = d3.select(this).select('text').node().getBBox(), + w = b.width + traceGap + 40, + h = d3.select(this).node().getBBox().height, + t = d3.transform(d3.select(this).attr('transform')); + //console.log(t.translate[0], t.translate[1], w, h); + maxOffsetX = Math.max(maxOffsetX, t.translate[0]); + maxOffsetY = Math.max(maxOffsetY, t.translate[1]); + maxTraceWidth = Math.max(maxTraceWidth, w); + maxTraceHeight = Math.max(maxTraceHeight, h); + }); - it('changing to vertical orientation', function(done) { - //change mock layout and refresh graph - mock.layout.legend.orientation = 'v'; - mock.layout.legend.y = 1; - done(); + //legend rect less than width of plot + expect(nw).toBeLessThan(gw); + expect(maxTraceHeight).toBeGreaterThan(0); + expect(maxTraceWidth).toBeGreaterThan(0); + expect(maxOffsetX).toBeGreaterThan(0); + expect(maxOffsetY).toBeGreaterThan(0); + + //none of the traces are pushed off the graph + expect(maxOffsetX).toBeLessThan(mock.layout.width); + expect(maxOffsetY).toBeLessThan(mock.layout.height); + + //update mock + mock.layout.legend.orientation = 'v'; + mock.layout.legend.y = 1; + //re-graph + destroyGraphDiv(gd); + gd = createGraphDiv(); + return Plotly.plot(gd, mock.data, mock.layout); + }).then(function() { + expect(gd._fullLayout.legend.orientation).toBe('v'); + //scrollbar has width and height now + var bbox = d3.select('rect.scrollbar').node().getBBox(); + expect(bbox.width).toBeGreaterThan(0); + expect(bbox.height).toBeGreaterThan(0); + //update mock and re-graph + mock.layout.legend.orientation = 'h'; + mock.layout.legend.y = initialLegendY; + destroyGraphDiv(gd); + gd = createGraphDiv(); + return Plotly.plot(gd, mock.data, mock.layout); + }).then(function() { + //back to base case + expect(gd._fullLayout.legend.orientation).toBe('h'); + expect(gd._fullLayout.legend.y).toBe(initialLegendY); + done(); + }); }); - it('changed to vertical, scrollbar appeared', function(done) { - //changed orientation to vertical - expect(gd._fullLayout.legend.orientation).toBe('v'); - //scrollbar has width and height now - var bbox = d3.select('rect.scrollbar').node().getBBox(); - expect(bbox.width).toBeGreaterThan(0); - expect(bbox.height).toBeGreaterThan(0); - done(); - }); }); From 75bb57f35c6c5aed5fa21404e34e5babec571538 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 2 Aug 2016 11:58:46 -0800 Subject: [PATCH 11/11] remove duplicative test, add relayout test --- test/jasmine/tests/legend_test.js | 63 ++++--------------------------- 1 file changed, 7 insertions(+), 56 deletions(-) diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index 7c6ad3148d6..e2934588545 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -546,69 +546,20 @@ describe('legend orientation change:', function() { afterEach(destroyGraphDiv); - it('should update legend orientation', function(done) { + it('should update plot background', function(done) { var mock = require('@mocks/legend_horizontal_autowrap.json'), gd = createGraphDiv(), - initialLegendY = mock.layout.legend.y; + initialLegendBGColor; Plotly.plot(gd, mock.data, mock.layout).then(function() { - var node = d3.select('g.legend').select('rect'), - nw = node.property('width').baseVal.value, - gw = mock.layout.width, - maxTraceHeight = 0, - maxTraceWidth = 0, - maxOffsetX = 0, - maxOffsetY = 0, - traceGap = gd._fullLayout.legend.tracegroupgap || 5; - - d3.selectAll('g.legend g.traces').each(function() { - var b = d3.select(this).select('text').node().getBBox(), - w = b.width + traceGap + 40, - h = d3.select(this).node().getBBox().height, - t = d3.transform(d3.select(this).attr('transform')); - //console.log(t.translate[0], t.translate[1], w, h); - maxOffsetX = Math.max(maxOffsetX, t.translate[0]); - maxOffsetY = Math.max(maxOffsetY, t.translate[1]); - maxTraceWidth = Math.max(maxTraceWidth, w); - maxTraceHeight = Math.max(maxTraceHeight, h); - }); - - //legend rect less than width of plot - expect(nw).toBeLessThan(gw); - expect(maxTraceHeight).toBeGreaterThan(0); - expect(maxTraceWidth).toBeGreaterThan(0); - expect(maxOffsetX).toBeGreaterThan(0); - expect(maxOffsetY).toBeGreaterThan(0); - - //none of the traces are pushed off the graph - expect(maxOffsetX).toBeLessThan(mock.layout.width); - expect(maxOffsetY).toBeLessThan(mock.layout.height); - - //update mock - mock.layout.legend.orientation = 'v'; - mock.layout.legend.y = 1; - //re-graph - destroyGraphDiv(gd); - gd = createGraphDiv(); - return Plotly.plot(gd, mock.data, mock.layout); + initialLegendBGColor = gd._fullLayout.legend.bgcolor; + return Plotly.relayout(gd, 'legend.bgcolor', '#000000'); }).then(function() { - expect(gd._fullLayout.legend.orientation).toBe('v'); - //scrollbar has width and height now - var bbox = d3.select('rect.scrollbar').node().getBBox(); - expect(bbox.width).toBeGreaterThan(0); - expect(bbox.height).toBeGreaterThan(0); - //update mock and re-graph - mock.layout.legend.orientation = 'h'; - mock.layout.legend.y = initialLegendY; - destroyGraphDiv(gd); - gd = createGraphDiv(); - return Plotly.plot(gd, mock.data, mock.layout); + expect(gd._fullLayout.legend.bgcolor).toBe('#000000'); + return Plotly.relayout(gd, 'legend.bgcolor', initialLegendBGColor); }).then(function() { - //back to base case - expect(gd._fullLayout.legend.orientation).toBe('h'); - expect(gd._fullLayout.legend.y).toBe(initialLegendY); + expect(gd._fullLayout.legend.bgcolor).toBe(initialLegendBGColor); done(); }); }); - });