From 39ab95d2c0dca4c5251bfcc344a42d587963767c Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Thu, 22 Sep 2016 18:26:26 -0400 Subject: [PATCH 01/11] Add button type to updatemenus --- src/components/updatemenus/attributes.js | 31 ++++ src/components/updatemenus/constants.js | 6 +- src/components/updatemenus/defaults.js | 3 + src/components/updatemenus/draw.js | 183 ++++++++++++++++++----- 4 files changed, 181 insertions(+), 42 deletions(-) diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js index 715f35ddd30..eff6237c4d4 100644 --- a/src/components/updatemenus/attributes.js +++ b/src/components/updatemenus/attributes.js @@ -57,6 +57,37 @@ module.exports = { ].join(' ') }, + openreverse: { + valType: 'boolean', + role: 'info', + dflt: false, + description: [ + 'For dropdown menus, opens the menu in the reverse direction' + ] + }, + + type: { + valType: 'enumerated', + values: ['dropdown', 'buttons'], + dflt: 'dropdown', + role: 'info', + description: [ + 'Determines whether the buttons are accessible via a dropdown menu', + 'or whether the buttons are stacked horizontally or vertically' + ].join(' ') + }, + + orientation: { + valType: 'enumerated', + values: ['h', 'v'], + dflt: 'v', + role: 'info', + description: [ + 'Determines whether the menu and buttons are laid out vertically', + 'or horizontally' + ] + }, + active: { valType: 'integer', role: 'info', diff --git a/src/components/updatemenus/constants.js b/src/components/updatemenus/constants.js index d9bfa1a9a11..488b7fb77ec 100644 --- a/src/components/updatemenus/constants.js +++ b/src/components/updatemenus/constants.js @@ -21,7 +21,8 @@ module.exports = { headerGroupClassName: 'updatemenu-header-group', headerClassName: 'updatemenu-header', headerArrowClassName: 'updatemenu-header-arrow', - buttonGroupClassName: 'updatemenu-button-group', + dropdownButtonGroupClassName: 'updatemenu-button-group', + dropdownButtonClassName: 'updatemenu-dropdown-button', buttonClassName: 'updatemenu-button', itemRectClassName: 'updatemenu-item-rect', itemTextClassName: 'updatemenu-item-text', @@ -41,7 +42,8 @@ module.exports = { minHeight: 30, // padding around item text - textPadX: 40, + textPadX: 24, + arrowPadX: 16, // font size to height scale fontSizeToHeight: 1.3, diff --git a/src/components/updatemenus/defaults.js b/src/components/updatemenus/defaults.js index 5574d5f5040..33bcdea656c 100644 --- a/src/components/updatemenus/defaults.js +++ b/src/components/updatemenus/defaults.js @@ -49,6 +49,9 @@ function menuDefaults(menuIn, menuOut, layoutOut) { if(!visible) return; coerce('active'); + coerce('orientation'); + coerce('type'); + coerce('openreverse'); coerce('x'); coerce('y'); diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index cbab8c534b6..3044ff9c36c 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -43,12 +43,12 @@ module.exports = function draw(gd) { * * * - * + * * * ... * * - * + * * * ... */ @@ -77,12 +77,12 @@ module.exports = function draw(gd) { headerGroups.enter().append('g') .classed(constants.headerGroupClassName, true); - // draw button container - var gButton = menus.selectAll('g.' + constants.buttonGroupClassName) + // draw dropdown button container + var gButton = menus.selectAll('g.' + constants.dropdownButtonGroupClassName) .data([0]); gButton.enter().append('g') - .classed(constants.buttonGroupClassName, true) + .classed(constants.dropdownButtonGroupClassName, true) .style('pointer-events', 'all'); // whenever we add new menu, attach 'state' variable to node @@ -114,12 +114,18 @@ module.exports = function draw(gd) { // draw headers! headerGroups.each(function(menuOpts) { var gHeader = d3.select(this); - drawHeader(gd, gHeader, gButton, menuOpts); - // update buttons if they are dropped - if(areMenuButtonsDropped(gButton, menuOpts)) { - drawButtons(gd, gHeader, gButton, menuOpts); + if(menuOpts.type === 'dropdown') { + drawHeader(gd, gHeader, gButton, menuOpts); + + // update buttons if they are dropped + if(areMenuButtonsDropped(gButton, menuOpts)) { + drawButtons(gd, gHeader, gButton, menuOpts); + } + } else { + drawButtons(gd, gHeader, null, menuOpts); } + }); }; @@ -163,11 +169,15 @@ function drawHeader(gd, gHeader, gButton, menuOpts) { var active = menuOpts.active, headerOpts = menuOpts.buttons[active] || constants.blankHeaderOpts, - posOpts = { y: 0, yPad: 0 }; + posOpts = { y: 0, yPad: 0, x: 0, xPad: 0, index: 0 }, + positionOverrides = { + width: menuOpts.headerWidth, + height: menuOpts.headerHeight + }; header .call(drawItem, menuOpts, headerOpts) - .call(setItemPosition, menuOpts, posOpts); + .call(setItemPosition, menuOpts, posOpts, positionOverrides); // draw drop arrow at the right edge var arrow = gHeader.selectAll('text.' + constants.headerArrowClassName) @@ -181,8 +191,8 @@ function drawHeader(gd, gHeader, gButton, menuOpts) { .text('▼'); arrow.attr({ - x: menuOpts.width - constants.arrowOffsetX, - y: menuOpts.height1 / 2 + constants.textOffsetY + x: menuOpts.headerWidth - constants.arrowOffsetX, + y: menuOpts.headerHeight / 2 + constants.textOffsetY }); header.on('click', function() { @@ -211,27 +221,63 @@ function drawHeader(gd, gHeader, gButton, menuOpts) { } function drawButtons(gd, gHeader, gButton, menuOpts) { - var buttonData = gButton.attr(constants.menuIndexAttrName) !== '-1' ? + if(!gButton) { + gButton = gHeader; + gButton.attr('pointer-events', 'all'); + } + + var buttonData = (gButton.attr(constants.menuIndexAttrName) !== '-1' || menuOpts.type === 'buttons') ? menuOpts.buttons : []; - var buttons = gButton.selectAll('g.' + constants.buttonClassName) + var klass = menuOpts.type === 'dropdown' ? constants.dropdownButtonClassName : constants.buttonClassName; + + var buttons = gButton.selectAll('g.' + klass) .data(buttonData); - buttons.enter().append('g') - .classed(constants.buttonClassName, true) - .attr('opacity', '0') - .transition() - .attr('opacity', '1'); + var enter = buttons.enter().append('g') + .classed(klass, true); + + var exit = buttons.exit(); + + if(menuOpts.type === 'dropdown') { + enter.attr('opacity', '0') + .transition() + .attr('opacity', '1'); + + exit.transition() + .attr('opacity', '0') + .remove(); + } else { + exit.remove(); + } + - buttons.exit() - .transition() - .attr('opacity', '0') - .remove(); + var x0 = 0; + var y0 = 0; + + if(menuOpts.type === 'dropdown') { + if(menuOpts.orientation === 'v') { + y0 = menuOpts.headerHeight + constants.gapButtonHeader; + } else { + x0 = menuOpts.headerWidth + constants.gapButtonHeader; + } + } + + if(menuOpts.type === 'dropdown' && menuOpts.openreverse) { + if(menuOpts.orientation === 'v') { + y0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.totalHeight; + } else { + x0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.totalWidth; + } + } var posOpts = { - y: menuOpts.height1 + constants.gapButtonHeader, - yPad: constants.gapButton + x: x0, + y: y0, + yPad: constants.gapButton, + xPad: constants.gapButton, + index: 0, }; buttons.each(function(buttonOpts, buttonIndex) { @@ -247,7 +293,11 @@ function drawButtons(gd, gHeader, gButton, menuOpts) { // fold up buttons and redraw header gButton.attr(constants.menuIndexAttrName, '-1'); - drawHeader(gd, gHeader, gButton, menuOpts); + + if(menuOpts.type === 'dropdown') { + drawHeader(gd, gHeader, gButton, menuOpts); + } + drawButtons(gd, gHeader, gButton, menuOpts); // call button method @@ -332,20 +382,27 @@ function styleOnMouseOut(item, menuOpts) { // find item dimensions (this mutates menuOpts) function findDimenstions(gd, menuOpts) { + var i; + menuOpts.width = 0; + menuOpts.width1 = 0; menuOpts.height = 0; menuOpts.height1 = 0; + menuOpts.heights = []; + menuOpts.widths = []; + menuOpts.totalWidth = 0; + menuOpts.totalHeight = 0; menuOpts.lx = 0; menuOpts.ly = 0; - var fakeButtons = gd._tester.selectAll('g.' + constants.buttonClassName) + var fakeButtons = gd._tester.selectAll('g.' + constants.dropdownButtonClassName) .data(menuOpts.buttons); fakeButtons.enter().append('g') - .classed(constants.buttonClassName, true); + .classed(constants.dropdownButtonClassName, true); // loop over fake buttons to find width / height - fakeButtons.each(function(buttonOpts) { + fakeButtons.each(function(buttonOpts, i) { var button = d3.select(this); button.call(drawItem, menuOpts, buttonOpts); @@ -362,11 +419,49 @@ function findDimenstions(gd, menuOpts) { tLines = tspans[0].length || 1, hEff = Math.max(tHeight * tLines, constants.minHeight) + constants.textOffsetY; - menuOpts.width = Math.max(menuOpts.width, wEff); + // Store per-item sizes since a row of horizontal buttons, for example, + // don't all need to be the same width: + menuOpts.widths[i] = wEff; + menuOpts.heights[i] = hEff; + + if(menuOpts.orientation === 'v' | menuOpts.type === 'dropdown') { + menuOpts.width = Math.max(menuOpts.width, wEff); + } else { + menuOpts.width += wEff; + } + // Height and width of individual element: menuOpts.height1 = Math.max(menuOpts.height1, hEff); - menuOpts.height += menuOpts.height1; + menuOpts.width1 = Math.max(menuOpts.width1, wEff); + + if(menuOpts.orientation === 'v') { + menuOpts.totalWidth = Math.max(menuOpts.totalWidth, wEff); + menuOpts.totalHeight += hEff; + } else { + menuOpts.totalWidth += wEff; + menuOpts.totalHeight += Math.max(menuOpts.totalWidth, hEff); + } }); + menuOpts.headerWidth = menuOpts.width1 + constants.arrowPadX; + menuOpts.headerHeight = menuOpts.height1; + + if(menuOpts.orientation === 'v') { + menuOpts.width = menuOpts.width1; + + if(menuOpts.type === 'dropdown') { + menuOpts.width1 += constants.arrowPadX; + } + + for(i = 0; i < menuOpts.heights; i++) { + menuOpts.height += menuOpts.heights[i]; + } + } else { + menuOpts.height = menuOpts.height1; + for(i = 0; i < menuOpts.heights; i++) { + menuOpts.width += menuOpts.width[i]; + } + } + fakeButtons.remove(); var graphSize = gd._fullLayout._size; @@ -409,19 +504,21 @@ function findDimenstions(gd, menuOpts) { } // set item positions (mutates posOpts) -function setItemPosition(item, menuOpts, posOpts) { +function setItemPosition(item, menuOpts, posOpts, overrideOpts) { + overrideOpts = overrideOpts || {}; var rect = item.select('.' + constants.itemRectClassName), text = item.select('.' + constants.itemTextClassName), tspans = text.selectAll('tspan'), - borderWidth = menuOpts.borderwidth; + borderWidth = menuOpts.borderwidth, + index = posOpts.index; - Lib.setTranslate(item, borderWidth, borderWidth + posOpts.y); + Lib.setTranslate(item, borderWidth + posOpts.x, borderWidth + posOpts.y); rect.attr({ x: 0, y: 0, - width: menuOpts.width, - height: menuOpts.height1 + width: overrideOpts.width || (menuOpts.orientation === 'v' ? menuOpts.width1 : menuOpts.widths[index]), + height: overrideOpts.height || (menuOpts.orientation === 'v' ? menuOpts.heights[index] : menuOpts.height1) }); var tHeight = menuOpts.font.size * constants.fontSizeToHeight, @@ -430,17 +527,23 @@ function setItemPosition(item, menuOpts, posOpts) { var textAttrs = { x: constants.textOffsetX, - y: menuOpts.height1 / 2 - spanOffset + constants.textOffsetY + y: menuOpts.heights[index] / 2 - spanOffset + constants.textOffsetY }; text.attr(textAttrs); tspans.attr(textAttrs); - posOpts.y += menuOpts.height1 + posOpts.yPad; + if(menuOpts.orientation === 'v') { + posOpts.y += menuOpts.heights[index] + posOpts.yPad; + } else { + posOpts.x += menuOpts.widths[index] + posOpts.xPad; + } + + posOpts.index++; } function removeAllButtons(gButton) { - gButton.selectAll('g.' + constants.buttonClassName).remove(); + gButton.selectAll('g.' + constants.dropdownButtonClassName).remove(); } function clearPushMargins(gd) { From ddc15fc261397a36bbc4d0e5e397f9bbb9193ca3 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 00:22:26 -0400 Subject: [PATCH 02/11] Fix a couple updatemenus anchor cases --- src/components/updatemenus/draw.js | 59 +++++++++++++----------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 3044ff9c36c..43af5688436 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -266,9 +266,9 @@ function drawButtons(gd, gHeader, gButton, menuOpts) { if(menuOpts.type === 'dropdown' && menuOpts.openreverse) { if(menuOpts.orientation === 'v') { - y0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.totalHeight; + y0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.openHeight; } else { - x0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.totalWidth; + x0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.openWidth; } } @@ -384,14 +384,14 @@ function styleOnMouseOut(item, menuOpts) { function findDimenstions(gd, menuOpts) { var i; - menuOpts.width = 0; menuOpts.width1 = 0; - menuOpts.height = 0; menuOpts.height1 = 0; menuOpts.heights = []; menuOpts.widths = []; menuOpts.totalWidth = 0; menuOpts.totalHeight = 0; + menuOpts.openWidth = 0; + menuOpts.openHeight = 0; menuOpts.lx = 0; menuOpts.ly = 0; @@ -424,41 +424,32 @@ function findDimenstions(gd, menuOpts) { menuOpts.widths[i] = wEff; menuOpts.heights[i] = hEff; - if(menuOpts.orientation === 'v' | menuOpts.type === 'dropdown') { - menuOpts.width = Math.max(menuOpts.width, wEff); - } else { - menuOpts.width += wEff; - } // Height and width of individual element: menuOpts.height1 = Math.max(menuOpts.height1, hEff); menuOpts.width1 = Math.max(menuOpts.width1, wEff); if(menuOpts.orientation === 'v') { menuOpts.totalWidth = Math.max(menuOpts.totalWidth, wEff); + menuOpts.openWidth = menuOpts.totalWidth; menuOpts.totalHeight += hEff; + menuOpts.openHeight += hEff; } else { menuOpts.totalWidth += wEff; - menuOpts.totalHeight += Math.max(menuOpts.totalWidth, hEff); + menuOpts.openWidth += wEff; + menuOpts.totalHeight = Math.max(menuOpts.totalHeight, hEff); + menuOpts.openHeight = menuOpts.totalHeight; } }); menuOpts.headerWidth = menuOpts.width1 + constants.arrowPadX; menuOpts.headerHeight = menuOpts.height1; - if(menuOpts.orientation === 'v') { - menuOpts.width = menuOpts.width1; - - if(menuOpts.type === 'dropdown') { + if(menuOpts.type === 'dropdown') { + if(menuOpts.orientation === 'v') { menuOpts.width1 += constants.arrowPadX; - } - - for(i = 0; i < menuOpts.heights; i++) { - menuOpts.height += menuOpts.heights[i]; - } - } else { - menuOpts.height = menuOpts.height1; - for(i = 0; i < menuOpts.heights; i++) { - menuOpts.width += menuOpts.width[i]; + menuOpts.totalHeight = menuOpts.height1; + } else { + menuOpts.totalWidth = menuOpts.width1; } } @@ -470,37 +461,39 @@ function findDimenstions(gd, menuOpts) { var xanchor = 'left'; if(anchorUtils.isRightAnchor(menuOpts)) { - menuOpts.lx -= menuOpts.width; + menuOpts.lx -= menuOpts.totalWidth; xanchor = 'right'; } if(anchorUtils.isCenterAnchor(menuOpts)) { - menuOpts.lx -= menuOpts.width / 2; + menuOpts.lx -= menuOpts.totalWidth / 2; xanchor = 'center'; } var yanchor = 'top'; if(anchorUtils.isBottomAnchor(menuOpts)) { - menuOpts.ly -= menuOpts.height; + menuOpts.ly -= menuOpts.totalHeight; yanchor = 'bottom'; } if(anchorUtils.isMiddleAnchor(menuOpts)) { - menuOpts.ly -= menuOpts.height / 2; + menuOpts.ly -= menuOpts.totalHeight / 2; yanchor = 'middle'; } - menuOpts.width = Math.ceil(menuOpts.width); - menuOpts.height = Math.ceil(menuOpts.height); + menuOpts.totalWidth = Math.ceil(menuOpts.totalWidth); + menuOpts.totalHeight = Math.ceil(menuOpts.totalHeight); menuOpts.lx = Math.round(menuOpts.lx); menuOpts.ly = Math.round(menuOpts.ly); Plots.autoMargin(gd, constants.autoMarginIdRoot + menuOpts._index, { x: menuOpts.x, y: menuOpts.y, - l: menuOpts.width * ({right: 1, center: 0.5}[xanchor] || 0), - r: menuOpts.width * ({left: 1, center: 0.5}[xanchor] || 0), - b: menuOpts.height * ({top: 1, middle: 0.5}[yanchor] || 0), - t: menuOpts.height * ({bottom: 1, middle: 0.5}[yanchor] || 0) + l: menuOpts.totalWidth * ({right: 1, center: 0.5}[xanchor] || 0), + r: menuOpts.totalWidth * ({left: 1, center: 0.5}[xanchor] || 0), + b: menuOpts.totalHeight * ({top: 1, middle: 0.5}[yanchor] || 0), + t: menuOpts.totalHeight * ({bottom: 1, middle: 0.5}[yanchor] || 0) }); + + console.log('menuOpts:', menuOpts); } // set item positions (mutates posOpts) From 9ee47b1715feb5a9235da221cb18eca9a48def39 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 00:43:35 -0400 Subject: [PATCH 03/11] Fix minor gapbutton issues --- src/components/updatemenus/draw.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 43af5688436..0498950e070 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -431,16 +431,23 @@ function findDimenstions(gd, menuOpts) { if(menuOpts.orientation === 'v') { menuOpts.totalWidth = Math.max(menuOpts.totalWidth, wEff); menuOpts.openWidth = menuOpts.totalWidth; - menuOpts.totalHeight += hEff; - menuOpts.openHeight += hEff; + menuOpts.totalHeight += hEff + constants.gapButton; + menuOpts.openHeight += hEff + constants.gapButton; } else { - menuOpts.totalWidth += wEff; - menuOpts.openWidth += wEff; + menuOpts.totalWidth += wEff + constants.gapButton; + menuOpts.openWidth += wEff + constants.gapButton; menuOpts.totalHeight = Math.max(menuOpts.totalHeight, hEff); menuOpts.openHeight = menuOpts.totalHeight; } }); + if(menuOpts.orientation === 'v') { + menuOpts.totalHeight -= constants.gapButton; + } else { + menuOpts.totalWidth -= constants.gapButton; + } + + menuOpts.headerWidth = menuOpts.width1 + constants.arrowPadX; menuOpts.headerHeight = menuOpts.height1; From 28fff11691a95367268ffb2f5c5b5a8f4bf13029 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 00:48:22 -0400 Subject: [PATCH 04/11] Fix lint errors and another pixel fix for updatemenus --- src/components/updatemenus/draw.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 0498950e070..52c472498c1 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -266,9 +266,9 @@ function drawButtons(gd, gHeader, gButton, menuOpts) { if(menuOpts.type === 'dropdown' && menuOpts.openreverse) { if(menuOpts.orientation === 'v') { - y0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.openHeight; + y0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openHeight; } else { - x0 = -2 * constants.gapButtonHeader - constants.gapButton - menuOpts.openWidth; + x0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openWidth; } } @@ -382,8 +382,6 @@ function styleOnMouseOut(item, menuOpts) { // find item dimensions (this mutates menuOpts) function findDimenstions(gd, menuOpts) { - var i; - menuOpts.width1 = 0; menuOpts.height1 = 0; menuOpts.heights = []; @@ -499,8 +497,6 @@ function findDimenstions(gd, menuOpts) { b: menuOpts.totalHeight * ({top: 1, middle: 0.5}[yanchor] || 0), t: menuOpts.totalHeight * ({bottom: 1, middle: 0.5}[yanchor] || 0) }); - - console.log('menuOpts:', menuOpts); } // set item positions (mutates posOpts) From fb6adc323fcea40556566f274e4ad610411ea1fd Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 01:02:58 -0400 Subject: [PATCH 05/11] Add showactive attribute to buttons --- src/components/updatemenus/attributes.js | 7 +++++++ src/components/updatemenus/defaults.js | 1 + src/components/updatemenus/draw.js | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js index eff6237c4d4..5460335ddba 100644 --- a/src/components/updatemenus/attributes.js +++ b/src/components/updatemenus/attributes.js @@ -99,6 +99,13 @@ module.exports = { ].join(' ') }, + showactive: { + valType: 'boolean', + role: 'info', + dflt: true, + description: 'Highlights active dropdown item or active button if true.' + }, + buttons: buttonsAttrs, x: { diff --git a/src/components/updatemenus/defaults.js b/src/components/updatemenus/defaults.js index 33bcdea656c..a0a87890887 100644 --- a/src/components/updatemenus/defaults.js +++ b/src/components/updatemenus/defaults.js @@ -52,6 +52,7 @@ function menuDefaults(menuIn, menuOut, layoutOut) { coerce('orientation'); coerce('type'); coerce('openreverse'); + coerce('showactive'); coerce('x'); coerce('y'); diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 52c472498c1..5a160b2d8cf 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -363,7 +363,7 @@ function styleButtons(buttons, menuOpts) { buttons.each(function(buttonOpts, i) { var button = d3.select(this); - if(i === active) { + if(i === active && menuOpts.showactive) { button.select('rect.' + constants.itemRectClassName) .call(Color.fill, constants.activeColor); } @@ -417,6 +417,9 @@ function findDimenstions(gd, menuOpts) { tLines = tspans[0].length || 1, hEff = Math.max(tHeight * tLines, constants.minHeight) + constants.textOffsetY; + hEff = Math.ceil(hEff); + wEff = Math.ceil(wEff); + // Store per-item sizes since a row of horizontal buttons, for example, // don't all need to be the same width: menuOpts.widths[i] = wEff; From 65d71d3dd75a3f2995be060c8465e046f57c7010 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 10:04:04 -0400 Subject: [PATCH 06/11] Account for arrow padding in updatemenus --- src/components/updatemenus/draw.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 5a160b2d8cf..0d287d0f2b2 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -459,6 +459,7 @@ function findDimenstions(gd, menuOpts) { } else { menuOpts.totalWidth = menuOpts.width1; } + menuOpts.totalWidth += constants.arrowPadX; } fakeButtons.remove(); From 7f1d35cc35026853e8ac176b3c285f0f2577b44e Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 13:44:38 -0400 Subject: [PATCH 07/11] Fix updatemenus descriptions and mocks --- src/components/updatemenus/attributes.js | 4 +- test/image/baselines/updatemenus.png | Bin 28969 -> 28970 bytes .../baselines/updatemenus_positioning.png | Bin 0 -> 37495 bytes test/image/mocks/updatemenus_positioning.json | 204 ++++++++++++++++++ 4 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 test/image/baselines/updatemenus_positioning.png create mode 100644 test/image/mocks/updatemenus_positioning.json diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js index 5460335ddba..db70273840f 100644 --- a/src/components/updatemenus/attributes.js +++ b/src/components/updatemenus/attributes.js @@ -63,7 +63,7 @@ module.exports = { dflt: false, description: [ 'For dropdown menus, opens the menu in the reverse direction' - ] + ].join(' ') }, type: { @@ -85,7 +85,7 @@ module.exports = { description: [ 'Determines whether the menu and buttons are laid out vertically', 'or horizontally' - ] + ].join(' ') }, active: { diff --git a/test/image/baselines/updatemenus.png b/test/image/baselines/updatemenus.png index 1dc3c383b2c5f9b32ecc2d27d73fc592a97e278e..81809e1739de07c723c9e5a829b53942f8dc7279 100644 GIT binary patch delta 19759 zcmZ^LcRbba`+plDL}ZtlUD=zg5VEt5ls!5j9K@@#Lded}&OEZmK^_I(_w)UJe(R6-qjz+#>%Q)5J)hUB;LrKOKj+JCvO!PK$3OI;j=slX{qg>+@}=M3 z3Yt}SoAsxOIOwf6M=^?Pw?;Da$@=WtmwhN*BWDzQ^rC*5%e&VXqo1P2`cN!p-*2fe zbHJ>*g(Fv0Ve$K~H0fNw@&VpZ<8yTerv(-LQ!fY6(gC zncZ6}KJyyVms+{;;_{;-wxO!P;=)&rWespo8J1n2}-13VyIJuCIASoJyp`(8iVqN5g9(aLe9VuPAlMu zgNjxb(|xsH)Xme@%|=SEQ4nLR7%m2mviKVz7;P>6V-&7S7lVlpTYY|geL*@*al?T# zP+VZ3(*5rFK=BawtlQXOqQC9Y>^9w>?p5WB6r0!S+5Sr9F{^ft{uxf!^+h+^QLQLn ze97UO<ovg2h`&ubt9Uth0tyf1%268p&;J!+WztU{hC#o=#4L;8TUid(J!^Vw?;~R|! zuvN9__*o#GN2-CN*SrD=i_8C!}efN3JCX`m1JJ@*eW`veVkY~Mn3a)0dj&0b8*VhQyflfQju5r^Y(Hej!Wy) z5hME>+``Kjw@{K~rojy#AlwA$HT2|NUki_+;WqAcO5H=zG)l}xW$s6m{l{U2MVe+z zG1|oNfxrS*tcU%zTc~T7g)b^8BGxaT$GUuKgg8vDbBoxA6K|g1I3;~oUtd&&Qs)j7 zcR&wC;iN=}C}AP*lHO+CLhZkMgB!8iWKGOX{LJamC5bjmY+%u zQXk0O$RjSxy&bZ15!++ccYn$za1{2E5_7Z`D;M+O2Ii=H?_oKort(5JRlmSBb*?~h z_4=VS66`Qz9R`e>;I-$FzRmIC@4@Oni* z!?BE^G3?;k~|`1Cya zLw}V2F8gwSc1WuK(Q;_3TU#Xa_VlKI&3<)x0Hgjme$7rE;@kAw^lhwgK{jkidH;S( zgsO1K=4iZ`^)=;JDQde@Ri5k?O4nXL@7@JsWMkc1Aj6E^XzK|!AV1#$@yYm_VBCZ+ zhNjVm551~n{MNkYMVh(qdKIQ{IYJzBr#`vCYZG?3V%*HTnCc$6RJh_&GtC7QH&%&4 z)Tg_Ux$lJ%3mS7`P%~X86Ot&Dzznq;z01-9i93kKX+|sJR|$X+<1_9@j0V z$5LxcD8eAThveDGPUDTIH~KfBv*Ya!9shFApqc`d|L^PS0mKH_>{c(xLq6_jej5DbUG* z8mnJr`qT zLqR^+AUc!_P0fsd!vS=*mxwp9OXH-FKPmI#gi~UNl1c_qVY<7|2iExCiIIzWWTuQ*b=O%P5e*aZ0xbwunEZ>4rZKkSe_k?%GUX> z6y&2CYwD}M>(rFEuXu<2gyZ3|&-pzX0 zu9jR(hZTL7rh(!7b`{xJ0N%OHreVc3(8ImlyIRj%KWtS?i*TT{=3VT+O;)>5`;k1-36l8pp51z5s?Ke-q-Lbc z)Il>qj>E1enKOjdzt;Ta_sj8PS5Cd4cw^2fx|zJI?5MZ>G55{^qkS$Xu>2Ov<9nVf zM^g2BoR~~z2n8L`DC;P0B?Pt4r^hZT7mNbEj`!EIAYWtXbSK02*jOI-mZJURZKb)w zqSBajS>MjH)6Fv!gkwr^ueoqbMd+-8Y_4f?le6}b%wHs8``+7kb z1N+^dt>){oR6ubAhk)XtUNQa5vn7740N+N({HycS!AfgAIWH1#Jgt|BhI}U+@;m-+%{FG$ub`aA?{5ZGhf;Ho{Gy2e zL&dI&@DtKG@~Tf1e=+dYVdfohjKrMVmpI?xu5jAOu>u?9z`*x`7(Tlr5itu~*G?~$ zBbn+gQ7rigv)kp{;GbnGr+>agiTRwC&S2`GR6xXHlkH20;aLb$V@Yr^bHKNOi=q5o)0z;Rw|MgA zJey|1`z4jEBeu*AFn^A^g%$BFl$E^=hY&g?T0vrf9L#?!)|{W|nzEA$g8HXfZ6_7X z_qJMWFh4&OOO5S$bSHI*7)P*a;G>42o>>1@h;H&z*}X*m z{~!6!KnE7}y!G3t_{Go7~79Yos(0Hu)>4yHt&C5-%Pg zX0PYGHn>0xH*llptAWqR(aXKA{lF>@JK9}l=dCOAi0co3Xw*e{dr;f<()D$mi$3MoEp4&&H_x%5JVE+8;eFi^#1*?EU4V3E6(hfw)-e-@=#>-|*>&mhM&Fu{Y>(9u z@3t79GY}@E`=khpzQ;*j@3HAh@aC(J<2tn~Mmb~TO zbMr7m!+E^%(C)lYP3+8BQ=QDwlD6b}Wn+O=AH{z6;nP~RC^_Yg=H}d~mo0+y!nQhP z4!2k!7Gb*dNe}8v5{bb^ivqPCuh5)%|ty9q&_J-uq(trp0$fM5RC0+HIrjkTw zy_eSy;%E?!?sj4&LIucOmvqIh0e!yKNEUC=^t!Itw5pTZ1d@+nku@zWD$2F%O|OFT zi@wR@mvwAfKhP8Yf?mvknqDs{v6f4*fjq_kU%ASUY0D|?)xaw*KuyFK_b!I|-|hE0 z*RLx%R ze&}uS^`@j-4#>9h_Tz%%`HX#zJ!+iC*~00B5_Gdwy&KacT(eF_A$(%0_d?P(2uM1} z#ixFgl&#a*fmLEj{>e!NnBAdV%lH(jZC-m06D+yLih|tP(PDu5HDCM=m?=)H(KVD(y%PqFlb+5j&h^_d{_Xm|4;@H2d zMs|$hI(Snu|9V%~^Bo42|7aMD5woGJLgV*0t})#isDV2`Hgb*+5ZN)==H}q#n!k$^ zR|VD~_`ZP(G5n6XsxTcsR}}B~`sdZ?TFclF@~ddZgeTLCTYt>YN8p0(bV!6RQNo0o z3VwosX7t<-V#8Y~s?YSidatmojzP{V2ey*~!^SOC>ujXII1>#gQRq3h0 zIAGyg_=v$k;?}`NtFOZr$?1zcK2ZpPG;=FYi7rE4?gWus)?Q}X2!1p6g?zntBhjya0eP2k4p)4b_ z6DY@BV-;N)3DFv75h6d}<_bl_J_sCKxF=ap6;bCA{7{}fZt~a<= z)tdzu0>!V3u?L0mqpG#-`@VtG=Odf%v+k`~gYmwxt~cl)r|6*3W<7~tRK~h3Z*i)e z+}qv4Y{0_~l$b5QiYOz&l52iA$pdPf_fSvA8C;BWU^K4+g5643@5>kTs;2&EDVtEE z^(C7x8kCsFwJSD8lLT*-p;`i&vE{F4? zPD?Bx{Bhz7oQCvm)Ykj9aVP@U`dnvu2?$|n?T*7IaGIO;-&QCwZ$4jdH!{FhdE}O{ zJ_r=YSi@=`TZ1=!hxG}N*BTFV8ZgCa%$(%Z3JCIx03~TrbwbsIL*; z`hZwmb`-7T+Fh#Y0Oo&h4f_A>t-6%PHb{IwuB1faU_xSjC$h(3J=0?`P2od@nV zFI3Oc8VJPt)z_&*#+NK8~K?uZR+l|35@H@w@6KHeQ7Py!Ox0p6mmD8exvWyQ^r=| z(aFKASkWCN%6WcJ79jI=B+)sCCGY)kodirleZeeqLgp$GDqTx=)4;!-_CB*aRcTqe?zyFUKP=^m7n(#ocATFJ?$3QhhlAHF|P1#+H1Gvb^pc$ zBc%AAeuf;Iu7dt`6qA?aF13(e0Q0p z_i@SWD`&-*Wo@rvMcdMo(cltVw%8!AcZ7??is^c=7$NYD@1#D6I=v$)Zr-NZPwf-Q zek_8GaQk3*eM46Q{w8?ol(wg$wBu|f$g|;tGOJv_5ix4CQ-c2|LM~IW zRv;h&ZbyR8jq4H6lAABJgGMc^KOxWqlp~r<)QeR)2jvvf;o4>a7T37e;2tY zla`50RS-RDx0Z6*h>_m=LpMJFlkXLSGX?%k5tpj7*DP;#DKjuZ|AplE@xDH zq{LWf{oag+JFZ?ur-1ig0&bJ^{dcz zbSDYtW((F?-?@$Qd>5^P9WK)F5bgWXoRD84j#?C=YuW|9*=4cLm_ zFp>SY*RfjQ5fHLl59{FKf5+jAzxGsfD0aUG5Otx0NOLV3JUvtod*J^18x5OH6E`pc zRBM>V$*VUkqM?zdG{m1!qX{9$>?13O-gMak5Zyew^>-^Or7MW8`XdE|Xa@0N8zRFX z$9LC$J+13_>^Zz^Ie$|aquO^h-WLcm2Y?oe;d6qPQ7k3aI}5ztD+RIx4F{)>b}cia z8a&ryl&(o~P~%+-s1som4_-8s)O}z+j_gjZs=+{g82@9J%}rBKtQaWMr`H4(bA5-l zVO2_)8e0P>FThp226EJ^*crrMq<&zQHuBkB(zT1bc!lgEq29O~yH6zlSCL-SG42(p z`-t^|Itd8VK}b0V0=;-p5d5xjtm0w-9j*#x8kLyZT=+h2SCgQ|;vguFsa0!@gi6jx z2bH;-4;mBP@OuLDgBkv6{(F4VthiT9osHf*3+cP{pA23_$)8d#_gOWc%(9+!3{ma{ z$X>9L<8T@ki`Cb0VYg`5NLtriuCRFiG*N|8sWcz zU2sdyXOqf(59^z9zt6}$Td}YEY|c0TTvLhj!PaSGf!XNT0A-XwZZ@#%*%e&|9rIm@ zU4@24gj}Ht&miklX<%%u32ruJZFSr(LqPuTcZ#`o_NYoJU;?3Qr~D*HNJkCN;pIbk_e92{aiG*TI_nW&8RjHrMlt7)lI{!bDDNE< zRlyH329bxf0;U}6lQnR+xMZD!BNm^fOe2R|C{LW7I%4qk_kxoMH;egU@vcGbQqs)^ zqVEX!+T?F&@`(%;#@g-(?$17e%y_7jh`NR9D9`r{96gl$Oo5ALSL^(A@42In!;?C< zTrY-}1OYQt32D9YLDeX1=Tv&5b{0i9$?_Vf=zX-D-}t&(KRxJx0_vlnXUorck@D>C zegy~0!P)K(cMi8`@ss{t#Y1f96(MXnF0am%H5CEza1-L_zb8lM)hx*@DpYe`8-w5} zos+Yh5>#}_+8zy+I}CCq-FqJFJY8>C|7!V<3%oC}e*_=|0Or~^a^0IL1(kT6cYB<< zvr+P}SF1`&i+g#pUu3Rs29vV|5V8I}vY4Sb>CjQ$wJkv96axdr8`tW2MP960DC;F; zf{2yTl-%g0MKdNoo!^e|GYh~O*{VfagOIc1W$p;^rELyWJ?|IG&>2K_d&Zf$S6Rk! zYC95QKK~|{&4db*w~yxxZH2zKwpP^$0$(h;`ef^eZWrzEaDRgA~2mtdN&@W_WbhD!H&aAMyl3Cjp8g~W=&N=tEtG@@}Veg<=k z@CR!$xn93-2r#rN#T~4B+ zY`ni6IOu}JN$GqH!kGC`@x)2T2LX!!C5;sLkBDcC7E|Z0=~kqEu(T3wNHpEa+_Rawvo3Gh#UBgN4&+%dLYN(Oam6F-T8e0yt6$ z*qrvqHv-sU0Wx;gIBm;5>+M35vrFgv##Z}ftc=5`e^{7RxnTF`ljc~0QX&#Z&8cB$ z=CdNbdXd+i2+7})%?Vs*mwqg}4azAj)Rge7_xcJO!H@aypjdBuevs*=sEt?&rj6#xOvkhy~yasr=>gi?;-@dk6F@?St1JLl#>D zL`^J)2~~!$6!a=IoRquH;?RUz07^)tChKc_ChoM;kjc#iW^|u{Hqt#tq_=+uz}ZpD zA)j#qY^b1&3*+ZM2ICUCUQ7t79}3wmryI&v-RA4a!%fs{*YfQDYqBGEX-&R8t)Dls zT4&2UNGO!a!=PY#p$AeCL_I#($(x}tsrFb}jNAAyV;@7qLpGkfyn06- z-XlidE+p`}CmS;vG<)`Yd3)Q*q-e9I`jq+EgHF2(XvXzLHtm9Fc9o5$h8N@xLQ+4L z%u|a3W!x4- zd7DqGATG*AM%by$29xsQdfi-1 zeTA5iP|;zdDq>y6L$J|c4&!^!RfIJ1hM3#Yv;JCWHeg&81Ny>o)dSf&P~t5j!fZYkaZ8-p{%Ij~cnr$(FkTf8())VRbjrI=Ly zN;!!f)QBvmUcw?7xGs`~#q?H=l(b6g;vu@x~r8Ye8G?rzH3&7EJ_kQK>DD1uV8=`NVJH*bE6P- z!lu2wx~f2J4E&9p#7LiIs6yad13kM=54pTi7{7Pv&VcLYviH zz8h3u@dAm5x_ZxPfe$kIprLq7V~9}uK-r)8t=?0hrRg#QB2O4MUb_bZEf$9Ydr705IBm_FE>Y2 z(V0kP^|RbC)eZpDU9p)UR=!n?OUS4?{z1)lv;eWho_(v?6Ln2SuaY*EwytLE#KlNx z2vVSnglNc_o`el0iyj_79`9oUYKos@=0~0O#>)|T_($LRNOL|A66Yx&VoX-Ji4~a9 zv3L6^@G762rmQhvR13QY)y;49tZ_ufbkzfcy^}aBT#|hPil(|>l6c(9aE>KMs$WC~s;1;_HFiF62j|(1h>DK^oW@XFRGib_UY-Ev?{3 z%^!PeMbr%RK7dTmB5`>t_5RZ2Byd`cO_^F?!XO*SXjPIud9Q=Tyk-20|9tD(|2jT4 z@-Yv$BH2;z_-QnrX^>UBoF7#mp;#kaTMn-|S)|00ZyRWE=_sLB&&(adj|7z_SdU`q zd8%vyOp;Rdo~Bk_F>q8q`g@fnTC7GihZ8lwIKBbRWXyza%v`s77B5uN8s7DgPIuJ0$w>d?}6P;WpE{!bAnHZE^OO{9Xg3at^0-1yz(`&|V*SOG|XYS+%RurN*RdDnAR(LY7Vhn?#L>7W>oJi4}%rUJi+1G?uc=sz*GsMRl@)@mb%YAQewuv zv)G$h=f3E}K0tKz`+I;579BKDYSG}6{rY69ZJq$T=NJ|lZD&&WeTl@a2w5>Mck)5V zIQL(YYT6Rmz=?$#I5I}auOOn>V)D^1sa58~WgV~aB~xAyy2&4QDCInF!*3rnZ$8S^ z0`dR^F2yX;vnDzpcYwqEG`_KH`51<07mDrAH9b4>>9|bVE@GY zQJ+&_6n9va;Fr1*1a^#GacdAUY-w_4gD^PPWY z;Bzyvb52JrcNc+q@Pk^X*yR*WYSx~m(lgh>iV>FyeA+GPP?_=4&k8Px63Gr(bsn1v8Z25Bxl5E7pIBvrOP$enR{8dA9fn=cl7#K zi|Y+`T0mPh_Wf*n-ugi&8Nw00gE|do?s=pa>IcTEUCi`}3%GBc$K&-34TqPAoX-|l zP&@k_X9cLptSwhCT|z;;B01FBQOb9)%A)-2#|X>z0CTWK}1cbYi*?&0Bx(o zkc*MqD1dI!INElKROKp~-I34YhmS_3+*TG)2Nf|WmMz7tu`5w15vWFJY0Qzs?ovMh zF9c+L_lxljZ7jZzPPY@A5q!3bfKUcr%_B69nBIqo=pyS;v_a`I{i=y zvEz?bejY2e;TQ*^*TiX*WiRu7W&kdj(^e3o#O~3_?3&om?yI|J=jQQ)^H$JA-1O`J zA7&%;|D-mqRDJw;1LIV>Y~kAyEB7}n;R+e0NxAZmA3v`sj&Ta0O3fvrfAAs&uma_4 zj!aaTTROqk+n1&*D5$sczf->GuDHg6+W`4^lIpK=BsP z7)Vd~N-2TvCg!?K9<&3_9PPBum-3>;G+Ke&#u-rutj9b$lmo<;#PEI_I&9UkGC6=n zWJF!Rhfh-t`WS&E*d$c>?eV>rpAmfZ^A02Y(VBuhTyd4g%CWStM8Q;hXVoJi#%qjR zSk02Mig;iMmL_GKEN^U_thW$A~2e=j$1L8p+ zl3t@e{HLJ9`P2j)TZ4xkfY?{_l~FrU9!?f1VlKR%StkM3(b`l6#KC0I;Ly=!y6qh2 z&zy?3rQmfc)>9I(C38iBX9Dvg`$$e6)G5!EdTukwyDqg8k|e@k6(h%{N$4sYcZ$@Z zI$3OA0Ne?(PwHV*MO4jynGEXQPo6LbW!iempQ%yUtu~e2Cr_s_pB;AXqrG&DyAIp` zc*vK`cEr$NDlNZ-tI7B~obf%uf6n65V`$0Ki$ND%C{5J(dpsLGeK8t(I?do-!p}3^6n?$isHUfC}H)Ox!U8 zFWUji zUnAogp&T$}*3v`ZD@0mQ?KenGuUt)>x&Fjq#_Bq{X#HT-c;dl8gO@{4&HJ`vQPCTe z5X@Kp4v2f?Cq9PXS^L=<2Ze%UWu`Nr|a{%YViTKRca!mzslX^3BXZo%+lp4`Lau zjzo|7ChI4P%4fz#t_-53yZAX!~5sEL(8ijm~^{gVHadEgKp=6rFME%3V8uInU2zFHcyh;?)j*eBI z0NDh~u?OE-9HG?C8P6VxJCfH?m!pVf5Z{|1uwA3h%OVobp(k+$4}Dmj_0Yb%{cOB8 z@vtd3JkdAH+|kBLs9sbBGCAe}d921pr2~=CiHD)F@!;OYD?I-|4*48zKdE5rQIPrb zm`PO3O>vKZPpp7QNxi6U*^?58D~wwvcS??VjTID#*vt7;P z`9zrheoh^euk&DbKLy2+UUI41VIpG5h)#9`il7@r_go@?cCmG{SK)Dt$)MW-_iS%ttg@|mCiinuj|?!@`pKd zpEX#ktGjhct~A->fA;PN*$a~bjJrp(J>VhCt1Oa$oGJ_h3A^0v;F)u>Fp1d<(+!XbK)QA|oy zgROw1_muWSsfDIxPwWcy-(?+@U$O_^W}qb{wkSE?EMS~I#sEd(>aG1s`v|~gsn~ie z->=-z#I_0GBu*U8e=O^EJrUdXG29jnA~)#1@qtZ(lu;_6$! zwIU!&7~_zpOEQT3pQUrqURa~bn$H3EqaK}$=>wKKFZvM9l>+OzD}dt8Fqg7;6M*GA z1HT9Q9(@t3_0F+OO6w}JdP(RK&7o@B)47fy+3!gx|eKIQGkmQ znOHDIjO2;IuHGXEh1aiNzjvM!Qv3`U*h22?fR=&DQ_>ZTt&bWVS~uki8a)e(CgpyI ze{vi3T_WjM5Fi{fpyUP#zA8VxtdmjZno4&lj`rRPJ+m;{O!BUJDjckaC*_vl{o=+i zN(4~1*kyBKq(j#CRZXA~hOlW&nXMMC>0`wcu-3Dm(u3J52#7C)nYu&`^?zY}|9ug$*I_Qxmht8<3qtDu zYw_nn;xgQWoSz3-m-}iVlv;%AIMF09OL4|p$xLtGYla$v0u*QCs z?_qC?;p(d_&-H9B6ocA(oHC$GkQ9Djd8CJ^B0434>yuviuBuWh1K#xxW$wFODl9pR z{n?Z{wVT5Of)*gwo&aOeY0U#@9z8ETKp1tDX{IFq+UZ%mxVf`=Zv?KM1E&u z(V*j>y=WHNemryLp9CmP2hG($`D8Afl0L&9hktQy1?>%9=u6Rc?kaiO0*w+6t^)cH zd27cj!N5_G{@;7K1Y3kmx6dv@<-N!ylhbgsjRubE=NILr!T&!#=>a+F)B6KX+`K!0 z9V%Z;PjuCQexEvQFe6)~V>L0FG1czyq6LyZG8UK&2zx1{DJ1;Te?AIzB}A3+scMBVmpFmFdk~I@0Tp51Y@N1c4WT6F7EXuY6|xlq~8*TNl}KZFMPr8g;0( zJmw0``GgrghO|Wu4GnL&ERD1=di^qERnV6HIFfpX-!yACv8&oiS92O|n*ZTm@Vsrn zJ%Q%moJN8FYU+X<^ju~LS@H9>$aof6ACWQ38|sUBTaBpAZtW6yD=UV5P-!-b2Xdbnu4JMAHJ zuR>;;w3i0R02|L9E>k^T_5s}W95CCmsD>uXTMMYc)0-8y%h;MTXeT%L$f)?^SZ{mI zF@5E!MEG^Z$(NF>=+%d>68|@R@ry$Gt3G;NWYbZh`RlEpS?J@hQGSmE8`kc3pt;qm zMFLYkoQ6Mh1((*4`(1u5jZPW;Q^&m`_qL2MHRssC(|6A*r3NMjJ~!?lpFyLtDAyW) z6-I&Fazgizp2)LZ8_@NIflYxdbadoCXml$mElmK)uGo_uLdu&sy3u^*Pe@pEKq_?4 zhqCz&0Ms(iv})zLvztCq83US!8^AbxNSS#4#g~Ycq=LnYv<%1R;T(HU7Gn!icv>P7 zrc6K`#unmXxOY@;)p8|C*e(*VNPCM^{>>m{BQQW?MKeI2?>6aD(-E!4LZ3~v70!mj z(kFlHsYN?IsBejyintDVz7lLG0zJ|J0AyJa1>rtx(b@C0z;e}I64ryU{$^K;jJx-| zbtrwH%xzvHNzy&fdAuAn@4)z>Y}JUEL`#2@iE0-8}c)1;~*K{==V4Uzj z=>x@2tna(_ykx@eHQyh?H~3s+`Y*bWejOFSEm}rnt8tDL_;8;m^W>~TiNG#iQ*j^6 z)4Kn>m2AA;qv+N0z|TocU!A+1NrPuece?DP^jB<>UHX=`dmn^v5HPL8ZCij=6}L)A zG(v@i7>@YMRZ1Vpj^YZGKKU}uL$K|f1Tz9SLoTs~FyF0Tdce^pWa;9X0C$p0Vah3Z zmKeD)Zc(lr7$0l@RS8h2!p*K?BQ)>&cr)^$inmpx5;ZxgV2N2tJ72+&3pWpvu@Y$C zzgUP3j{2Uq*U#3*L#|u*Qy>J_%6YR91rQ8l@7Z)mYQMR-N)Y%~F`u76f{Kl53fXA@ z3O+M%PsU2$0J~SC|7x8#OT0N6P5l&@W}sgLvSIeHl_sLg*t?GEzUkUF>?*d$_Y(7p zJepD9Q$4znuOvB(Nr%=DAqk0_La0vQFF;^aa2^}+pyv@iKuMb2Kj%+=*^MDE>I95X z!m_4;;y#E!|BRWfr1#5t5wDC`|3M9yodCAtLDfrq-js2kfnA6B1xJSgA1EG(}F z2EG52nn3x_LO!UI7y_$V*AbxTkA?MHL9LJY1fB;ynHQz*l^K4ATi`K`Jh*|4VEHZ4 z77K_fzh)v>ine2j!85XQQUtVl;l!D0TzRLHV1joM3AV@V2h#>{QbM)5QQSZ$skz>F zr}61o2xJv?<=6w&v!D8t@UNmchA@m#*3(-k6t^Jz?%EzJHiEAE%XJ17gbpNE_o~8F zE8>0nPt7o3(IZ*~Uho8p3w~dk2k;}|;w;lOL76f#{kfkSV)im<^@x6ZQ3ahYOmBqf z(g_-CmWO48!x%uT;KhF^{OKsy7pm`ZtrWvnA@LXm|E-?` zlkJLnPq2Hv`1KjcQkgS_<{x^YMJkXGlh0PCtqS4tT4aP~Bhm-NK*?HcdC-#?6ckTL zsOCqi%Fv9t5r5g;E3N?Ex;cTxTTzKF^4rR=Dc%Nsat_rWaCzz})ybe>+nRApx3rgx z4`t5HB(LpHPK=aHumUXDmcIKb;(UB4DPE}Y_V!Y?=IrzMQRmc(CyWG-MN;T|}MGUA&-m?xQDoLle*s2c#~5W|BIn_H)bc z0xm-fYHqr))uTt?oKBI)Wf8VbW?M`CPnxstDPz*AL8$c-% zx`E=!JwHK%M%(>IfI~^BlG^GbOy)%yXNyOIakirOFR#&|odlPx1T#VHd#cn{P|jZq zaINwb9YKus7!;+Af)Wie)_>A+O{qY!D*LyeBBDq8&F93&ptjSf`XnfEoy_(*Xib@? zuM`Uuzr(Y02#R9G+sRQL&WX^VX8QB4o zuJ?1*ZO}23)SGAnu-18iwNhD#+^Pd_&4W9kj+F%MBo=sDSS(k$hhk;j6{k*UX^lDi+ANr{ZqVk3OR(0-BnPcZcyKN&= zfSz7-9}hhI3x1Jwr2xcZgu0vw9cDY|LL({!oOI!BgeetB030e5!QCB(Vlz5?Tj_Hv z+!;0E14m~VsOEkU?XbUW04=xLuL&AjrMP6Jaqb*tk2)X(3>T9k_jNN8`HbF|L7h(U zbdLV}ApSL6`2aj%L|{qB10UFnnip)7HQ~i3>{)zGMEQAv;%iAw3u?bTBY?O0OYk-X zFokc(!y^$GWcQ!1x(E^b5M2@|LeX2qUiM%GJ%te&86dAYvN=AW>n|bar~o{Q3Yh?K zr-W`POF)P;nTJGK5BP`P<7{tV-Te+qEnLD>ylFz?pKvQHrA@_oXI+NqjvrUBTER|) zyZr|=KoJWSp*nibn~Accs@n%&$O5%EuUTd3}mGf2WfwVi5cKB_A=8d1Jyc zJ&_Y2W-e##rQ&zqg6{zksua2K$iYriN|=z7J5Y2bS& z+kfO}O(+r|*zeC%_CWv32s=#~1b_}kr~q41gNY%u?SQV>Uq)QMBSyCDo4(8yWY3ZusgR0=cf{~}1SsC1T$ZVj zk(hB>*-qE|CI9O9^M_si;05&8+LR7~gIJ%Q9NzcZFh|0V6j)^tW&DtN?c<3mr%`*z z5`n!;AS!{DP39_ZgLIc1^;oVB(5;*6wTTf+7BWa-S2gI!QZXctJgl8nPJivjYV4SI zm)&z?iU)+dyQl2AY6=-qN7&~72|pV=)eQ~fLEJATu6&9kiXPN~8|61IrZ-q_Gmw?DPctKz9>Bb&`C{J(ZEu^>uhVs*w^Q|YEdi^k=vOeEZ5^PgigVQ z@lxcr*+cz&?LCf0(0@&9Dg=wQ{EN=q9@6hwC4Y@Yr`>=0ZSv>EXI4LWVaW#P9xh)8 zEi}Z+_1#rfGQSSPg+L!o1JY3TiPH#*Qw?HG!(7k>ozjC8pOgS0BJz^^@<496>#QnV zGa%zt_?yyC=|g>faI@+g6pF3Jl% z)b#h*@cuMaD!>TM{bPiN0lZ&q!e(Qc?t{bZumCPXRa(A?hWY+3lqBG?xaJf%--0b=>eprndI(c zX}>#;MZiF{vl9%IA);zVDfs;q1cjz_ZmidYlQG#xu?vKN!cDMULdW%^bFBYcXH6$y zse%qFfpWywGq|X+WekC63CYl(4&}?m7l63Y6Wu>HjP~@=FE#?_*#c~bm%SA@#~DjR zW@TZQ*cIO$Zf)RHnSAK^8UU+q^G6V99n%2G3u>JlWI+i)jXQzt8mSpyA(82GeOW5u zQjN{ac_|E2M;{kJ2d0Pvt3ByIVVw$My$sZaUiKONXcZmteLW<>SFwuYiBn(i}1dhm_o)CV0>m2y`H&?Lc?0H+nfB)n&p@So<_y3;g zw+tB^bP*E*e-qGn|7vYaSFmpG`top*F-v{=s$A3Q(JHi^&5D0``nOG919X4SJ!d`s z^np?Q*Re1U^93K%Z(dD1%;2LADS*_OKWP8mY`n@Tamsr!ZF??OM+3ao51@%lZm&S+ zMykek%M56R1DB?Dda@|r1=M72NMC1f%!%wF<-`9%^X+549RQ}w@>E>~8TeKSphiPN zqZVFi|1=BNdpNaoKKy;Sn332F8uz!yd;Ld_FN=7r7##lKmb-07U6qt^GRM8WQiSx`F^_tHI@#`;FRu6% zGpHjk`xDk@5Dk2hN~Hgl)>4Si-12y0bS_^W?@;m^=H4T^{Zq)lKUPT3=aTgC zqZ$2ecX_Z8=_$XH)SENrcrRsu!l&LtP2L=QZGo@cwud25JgA@yJc;pI*X*TvBBAD! zauoPTL+sb*Z9Z(O8VPTH?eHN{17;>?K+*!u$J3k28ImplKdZKK4EfdooPORr!wcY3 z1v4tm&xQmbGXEpch`;9dv(${~;W8xx5L;F1R#%Jxggod_`K?6e@9%*0SAMHzGchx# z`!#?D@2)8S2>ImegQkPVO?B{`=76=0IXlcai(W-G%jL4r)X?KU=AU>pH6JddU>>M7 z`{Tn%1EceSDr+%Ik|$6jK*0rdgLZmmK7SH|H(OkjKY1y6yjJlx{=#{`(78OoVw%?U z1O03{eb2t8^u_-)sj%%Jyj0m7Vz|$a6=*~xe6WN%oFdpKciS4PCs*`uEKVXd`{pbn)^F zY-00C?!mL-Qo*COX7D`(@NEdKw*@)EyM)ek*20-%%z+R2>9P*AZ8WwwuJlfU;nI_T zeHcYu!I;iN#S4)1F^~}Z^q;bq*ar@i)dF+ZIm*0uY&VO{=S%W0eOv>iU~${*4z~`+k0Yep<0zMoH@sa51DK zFt9;quy{JubH23PbKds*ob9Kqfm;H8zHqna+S>EZj|U0q-9`4Tv- zdpUWn?#sH;scV77aO))_^< zyHW>UatbS)fW=tBEQUj`ODZH~AjK89U^{eL2A7I@XxWEH2~Abhli*fbI0WK<5(ABj z4yhlgfQN>AJ*ZA2lt^f(qMoGGN_~gG{6A1BpdOTeapq3y`xhGBaPK-3S4==0a^OF^ XvsU)XET_~d3_#%N>gTe~DWM4ftubf| delta 19821 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 literal 0 HcmV?d00001 diff --git a/test/image/mocks/updatemenus_positioning.json b/test/image/mocks/updatemenus_positioning.json new file mode 100644 index 00000000000..ad91de0179e --- /dev/null +++ b/test/image/mocks/updatemenus_positioning.json @@ -0,0 +1,204 @@ +{ + "data": [ + { + "y": [ + 0.8894873976401985, + 0.014899350293371638, + 0.6973412552835649, + 0.4322110719369108, + 0.6435204579331169, + 0.7913368293479852, + 0.45608188941724737, + 0.8773020090286707, + 0.7857950507320299, + 0.1565801184767599 + ], + "line": { + "shape": "spline", + "color": "blue" + }, + "name": "Data set 0" + } + ], + "layout": { + "updatemenus": [ + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.3, + "y": 1.0, + "yanchor": "top", + "xanchor": "left" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.3, + "y": 0.66, + "yanchor": "top", + "xanchor": "left", + "orientation": "h" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.3, + "y": 0.33, + "yanchor": "top", + "xanchor": "left", + "orientation": "h", + "openreverse": true + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.3, + "y": 0.0, + "yanchor": "top", + "xanchor": "left", + "orientation": "v", + "openreverse": true + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "type": "buttons", + "x": -0.12, + "y": 1.0, + "yanchor": "top", + "xanchor": "left", + "showactive": false + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "type": "buttons", + "x": -0.12, + "y": 1.01, + "yanchor": "bottom", + "xanchor": "left", + "orientation": "h", + "showactive": false + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]} + ], + "type": "buttons", + "x": 1, + "y": 0.03, + "yanchor": "bottom", + "xanchor": "right" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]} + ], + "type": "buttons", + "x": 1, + "y": 0.02, + "yanchor": "top", + "xanchor": "right", + "orientation": "h" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.6, + "y": 0.9, + "yanchor": "top", + "xanchor": "right" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]}, + {"label": "green", "method": "restyle", "args": ["marker.color", "green"]}, + {"label": "yellow", "method": "restyle", "args": ["marker.color", "yellow"]}, + {"label": "orange", "method": "restyle", "args": ["marker.color", "orange"]} + ], + "x": 0.6, + "y": 0.9, + "yanchor": "bottom", + "xanchor": "left" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]} + ], + "x": 0.6, + "y": 0.4, + "type": "buttons", + "yanchor": "top", + "xanchor": "right" + }, + { + "buttons": [ + {"label": "red", "method": "restyle", "args": ["marker.color", "red"]}, + {"label": "blue", "method": "restyle", "args": ["marker.color", "blue"]} + ], + "type": "buttons", + "x": 0.6, + "y": 0.4, + "yanchor": "bottom", + "xanchor": "left" + } + ], + "xaxis": { + "range": [ + -0.5484683986041102, + 9.54846839860411 + ], + "autorange": true + }, + "yaxis": { + "type": "linear", + "range": [ + 0.14689768330153566, + 0.9369323077136202 + ], + "autorange": true + }, + "height": 450, + "width": 1100, + "autosize": true + } +} From 9a17f69abede6b138cd9b4b1d1be8bbc9430a0fd Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 14:14:08 -0400 Subject: [PATCH 08/11] Fix updatemenus tests --- test/jasmine/tests/updatemenus_test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index 36fe6366325..c96ad2fab69 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -339,7 +339,7 @@ describe('update menus interactions', function() { return Plotly.relayout(gd, 'updatemenus[1].buttons[1].label', 'a looooooooooooong
label'); }).then(function() { - assertItemDims(selectHeader(1), 179, 34.2); + assertItemDims(selectHeader(1), 179, 35); return click(selectHeader(1)); }).then(function() { @@ -381,21 +381,21 @@ describe('update menus interactions', function() { assertNodeCount('.' + constants.containerClassName, 1); assertNodeCount('.' + constants.headerClassName, expectedMenus.length); - var gButton = d3.select('.' + constants.buttonGroupClassName), + var gButton = d3.select('.' + constants.dropdownButtonGroupClassName), actualActiveIndex = +gButton.attr(constants.menuIndexAttrName), hasActive = false; expectedMenus.forEach(function(expected, i) { if(expected) { expect(actualActiveIndex).toEqual(i); - assertNodeCount('.' + constants.buttonClassName, expected); + assertNodeCount('.' + constants.dropdownButtonClassName, expected); hasActive = true; } }); if(!hasActive) { expect(actualActiveIndex).toEqual(-1); - assertNodeCount('.' + constants.buttonClassName, 0); + assertNodeCount('.' + constants.dropdownButtonClassName, 0); } } @@ -448,7 +448,7 @@ describe('update menus interactions', function() { } function selectButton(buttonIndex) { - var buttons = d3.selectAll('.' + constants.buttonClassName), + var buttons = d3.selectAll('.' + constants.dropdownButtonClassName), button = d3.select(buttons[0][buttonIndex]); return button; } From 68ca4da9edeef7b83a7458ffd5c35eb5555868f3 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 14:45:56 -0400 Subject: [PATCH 09/11] Add button dropdown tests --- src/components/updatemenus/constants.js | 2 +- test/jasmine/tests/updatemenus_test.js | 85 +++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/components/updatemenus/constants.js b/src/components/updatemenus/constants.js index 488b7fb77ec..8b6cea3439b 100644 --- a/src/components/updatemenus/constants.js +++ b/src/components/updatemenus/constants.js @@ -21,7 +21,7 @@ module.exports = { headerGroupClassName: 'updatemenu-header-group', headerClassName: 'updatemenu-header', headerArrowClassName: 'updatemenu-header-arrow', - dropdownButtonGroupClassName: 'updatemenu-button-group', + dropdownButtonGroupClassName: 'updatemenu-dropdown-button-group', dropdownButtonClassName: 'updatemenu-dropdown-button', buttonClassName: 'updatemenu-button', itemRectClassName: 'updatemenu-item-rect', diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index c96ad2fab69..666a5820a93 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -147,6 +147,91 @@ describe('update menus defaults', function() { expect(layoutOut.updatemenus[0].bgcolor).toEqual('blue'); expect(layoutOut.updatemenus[1].bgcolor).toEqual('red'); }); + + it('should default \'type\' to \'dropdown\'', function() { + layoutIn.updatemenus = [{ + buttons: [{method: 'relayout', args: ['title', 'Hello World']}] + }]; + + supply(layoutIn, layoutOut); + + expect(layoutOut.updatemenus[0].type).toEqual('dropdown'); + }); + + it('should default \'orientation\' to \'v\'', function() { + layoutIn.updatemenus = [{ + buttons: [{method: 'relayout', args: ['title', 'Hello World']}] + }]; + + supply(layoutIn, layoutOut); + + expect(layoutOut.updatemenus[0].orientation).toEqual('v'); + }); + + it('should default \'showactive\' to true', function() { + layoutIn.updatemenus = [{ + buttons: [{method: 'relayout', args: ['title', 'Hello World']}] + }]; + + supply(layoutIn, layoutOut); + + expect(layoutOut.updatemenus[0].showactive).toEqual(true); + }); + + it('should default \'openreverse\' to false', function() { + layoutIn.updatemenus = [{ + buttons: [{method: 'relayout', args: ['title', 'Hello World']}] + }]; + + supply(layoutIn, layoutOut); + + expect(layoutOut.updatemenus[0].openreverse).toEqual(false); + }); +}); + +describe('update menus buttons', function() { + var mock = require('@mocks/updatemenus_positioning.json'); + var gd; + var allMenus, buttonMenus, dropdownMenus; + + beforeEach(function(done) { + gd = createGraphDiv(); + + // move update menu #2 to click on them separately + var mockCopy = Lib.extendDeep({}, mock); + mockCopy.layout.updatemenus[1].x = 1; + + allMenus = mockCopy.layout.updatemenus; + buttonMenus = allMenus.filter(function(opts) {return opts.type === 'buttons';}); + dropdownMenus = allMenus.filter(function(opts) {return opts.type !== 'buttons';}); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + }); + + afterEach(function() { + Plotly.purge(gd); + destroyGraphDiv(); + }); + + it('creates button menus', function(done) { + assertNodeCount('.' + constants.containerClassName, 1); + + // 12 menus, but button menus don't have headers, so there are only six headers: + assertNodeCount('.' + constants.headerClassName, dropdownMenus.length); + + // Count the *total* number of buttons we expect for this mock: + var buttonCount = 0; + buttonMenus.forEach(function(menu) {buttonCount += menu.buttons.length;}); + + assertNodeCount('.' + constants.buttonClassName, buttonCount); + + done(); + + }); + + function assertNodeCount(query, cnt) { + expect(d3.selectAll(query).size()).toEqual(cnt); + } }); describe('update menus interactions', function() { From f8fba325f57e8f5d73b0c93739726ce246d3e016 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 17:58:15 -0400 Subject: [PATCH 10/11] Change updatemenus orientation/openreverse to simply 'direction' --- src/components/updatemenus/attributes.js | 21 ++++-------- src/components/updatemenus/defaults.js | 3 +- src/components/updatemenus/draw.js | 32 +++++++++++-------- test/image/mocks/updatemenus_positioning.json | 12 +++---- test/jasmine/tests/updatemenus_test.js | 14 ++------ 5 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js index db70273840f..eb3a55a766b 100644 --- a/src/components/updatemenus/attributes.js +++ b/src/components/updatemenus/attributes.js @@ -57,15 +57,6 @@ module.exports = { ].join(' ') }, - openreverse: { - valType: 'boolean', - role: 'info', - dflt: false, - description: [ - 'For dropdown menus, opens the menu in the reverse direction' - ].join(' ') - }, - type: { valType: 'enumerated', values: ['dropdown', 'buttons'], @@ -77,14 +68,16 @@ module.exports = { ].join(' ') }, - orientation: { + direction: { valType: 'enumerated', - values: ['h', 'v'], - dflt: 'v', + values: ['left', 'right', 'up', 'down'], + dflt: 'down', role: 'info', description: [ - 'Determines whether the menu and buttons are laid out vertically', - 'or horizontally' + 'Determines the direction in which the buttons are laid out, whether', + 'in a dropdown menu or a row/column of buttons. For `left` and `up`,', + 'the buttons will still appear in left-to-right or top-to-bottom order', + 'respectively.' ].join(' ') }, diff --git a/src/components/updatemenus/defaults.js b/src/components/updatemenus/defaults.js index a0a87890887..39f662c9003 100644 --- a/src/components/updatemenus/defaults.js +++ b/src/components/updatemenus/defaults.js @@ -49,9 +49,8 @@ function menuDefaults(menuIn, menuOut, layoutOut) { if(!visible) return; coerce('active'); - coerce('orientation'); + coerce('direction'); coerce('type'); - coerce('openreverse'); coerce('showactive'); coerce('x'); diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 0d287d0f2b2..87d1af69748 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -256,20 +256,22 @@ function drawButtons(gd, gHeader, gButton, menuOpts) { var x0 = 0; var y0 = 0; + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + if(menuOpts.type === 'dropdown') { - if(menuOpts.orientation === 'v') { + if(isVertical) { y0 = menuOpts.headerHeight + constants.gapButtonHeader; } else { x0 = menuOpts.headerWidth + constants.gapButtonHeader; } } - if(menuOpts.type === 'dropdown' && menuOpts.openreverse) { - if(menuOpts.orientation === 'v') { - y0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openHeight; - } else { - x0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openWidth; - } + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'up') { + y0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openHeight; + } + + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'left') { + x0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openWidth; } var posOpts = { @@ -399,6 +401,8 @@ function findDimenstions(gd, menuOpts) { fakeButtons.enter().append('g') .classed(constants.dropdownButtonClassName, true); + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + // loop over fake buttons to find width / height fakeButtons.each(function(buttonOpts, i) { var button = d3.select(this); @@ -429,7 +433,7 @@ function findDimenstions(gd, menuOpts) { menuOpts.height1 = Math.max(menuOpts.height1, hEff); menuOpts.width1 = Math.max(menuOpts.width1, wEff); - if(menuOpts.orientation === 'v') { + if(isVertical) { menuOpts.totalWidth = Math.max(menuOpts.totalWidth, wEff); menuOpts.openWidth = menuOpts.totalWidth; menuOpts.totalHeight += hEff + constants.gapButton; @@ -442,7 +446,7 @@ function findDimenstions(gd, menuOpts) { } }); - if(menuOpts.orientation === 'v') { + if(isVertical) { menuOpts.totalHeight -= constants.gapButton; } else { menuOpts.totalWidth -= constants.gapButton; @@ -453,7 +457,7 @@ function findDimenstions(gd, menuOpts) { menuOpts.headerHeight = menuOpts.height1; if(menuOpts.type === 'dropdown') { - if(menuOpts.orientation === 'v') { + if(isVertical) { menuOpts.width1 += constants.arrowPadX; menuOpts.totalHeight = menuOpts.height1; } else { @@ -514,11 +518,13 @@ function setItemPosition(item, menuOpts, posOpts, overrideOpts) { Lib.setTranslate(item, borderWidth + posOpts.x, borderWidth + posOpts.y); + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + rect.attr({ x: 0, y: 0, - width: overrideOpts.width || (menuOpts.orientation === 'v' ? menuOpts.width1 : menuOpts.widths[index]), - height: overrideOpts.height || (menuOpts.orientation === 'v' ? menuOpts.heights[index] : menuOpts.height1) + width: overrideOpts.width || (isVertical ? menuOpts.width1 : menuOpts.widths[index]), + height: overrideOpts.height || (isVertical ? menuOpts.heights[index] : menuOpts.height1) }); var tHeight = menuOpts.font.size * constants.fontSizeToHeight, @@ -533,7 +539,7 @@ function setItemPosition(item, menuOpts, posOpts, overrideOpts) { text.attr(textAttrs); tspans.attr(textAttrs); - if(menuOpts.orientation === 'v') { + if(isVertical) { posOpts.y += menuOpts.heights[index] + posOpts.yPad; } else { posOpts.x += menuOpts.widths[index] + posOpts.xPad; diff --git a/test/image/mocks/updatemenus_positioning.json b/test/image/mocks/updatemenus_positioning.json index ad91de0179e..ecff0b0c906 100644 --- a/test/image/mocks/updatemenus_positioning.json +++ b/test/image/mocks/updatemenus_positioning.json @@ -47,7 +47,7 @@ "y": 0.66, "yanchor": "top", "xanchor": "left", - "orientation": "h" + "direction": "right" }, { "buttons": [ @@ -61,8 +61,7 @@ "y": 0.33, "yanchor": "top", "xanchor": "left", - "orientation": "h", - "openreverse": true + "direction": "left" }, { "buttons": [ @@ -76,8 +75,7 @@ "y": 0.0, "yanchor": "top", "xanchor": "left", - "orientation": "v", - "openreverse": true + "direction": "up" }, { "buttons": [ @@ -107,7 +105,7 @@ "y": 1.01, "yanchor": "bottom", "xanchor": "left", - "orientation": "h", + "direction": "right", "showactive": false }, { @@ -131,7 +129,7 @@ "y": 0.02, "yanchor": "top", "xanchor": "right", - "orientation": "h" + "direction": "right" }, { "buttons": [ diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index 666a5820a93..e155bf27eff 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -158,14 +158,14 @@ describe('update menus defaults', function() { expect(layoutOut.updatemenus[0].type).toEqual('dropdown'); }); - it('should default \'orientation\' to \'v\'', function() { + it('should default \'direction\' to \'down\'', function() { layoutIn.updatemenus = [{ buttons: [{method: 'relayout', args: ['title', 'Hello World']}] }]; supply(layoutIn, layoutOut); - expect(layoutOut.updatemenus[0].orientation).toEqual('v'); + expect(layoutOut.updatemenus[0].direction).toEqual('down'); }); it('should default \'showactive\' to true', function() { @@ -177,16 +177,6 @@ describe('update menus defaults', function() { expect(layoutOut.updatemenus[0].showactive).toEqual(true); }); - - it('should default \'openreverse\' to false', function() { - layoutIn.updatemenus = [{ - buttons: [{method: 'relayout', args: ['title', 'Hello World']}] - }]; - - supply(layoutIn, layoutOut); - - expect(layoutOut.updatemenus[0].openreverse).toEqual(false); - }); }); describe('update menus buttons', function() { From 570a448a0dd6f3f4ae9a13ff3e596911e73464b2 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Fri, 23 Sep 2016 18:14:38 -0400 Subject: [PATCH 11/11] Unmangle updatemenus comments --- src/components/updatemenus/draw.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 87d1af69748..8acf51820ca 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -43,12 +43,12 @@ module.exports = function draw(gd) { * * * - * + * * * ... * * - * + * * * ... */