diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 6b51ce15461..bfcd58944d8 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -57,7 +57,7 @@ function draw(gd) { function drawOne(gd, index) { // remove the existing shape if there is one. // because indices can change, we need to look in all shape layers - gd._fullLayout._paper + gd._fullLayout._paperdiv .selectAll('.shapelayer [data-index="' + index + '"]') .remove(); diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 39efaf73cdd..6c6a470fecf 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -54,7 +54,7 @@ module.exports = function draw(gd) { */ // draw update menu container - var menus = fullLayout._infolayer + var menus = fullLayout._menulayer .selectAll('g.' + constants.containerClassName) .data(menuData.length > 0 ? [0] : []); @@ -97,6 +97,9 @@ module.exports = function draw(gd) { // remove exiting header, remove dropped buttons and reset margins if(headerGroups.enter().size()) { + // make sure gButton is on top of all headers + gButton.node().parentNode.appendChild(gButton.node()); + gButton .call(removeAllButtons) .attr(constants.menuIndexAttrName, '-1'); @@ -135,13 +138,12 @@ module.exports = function draw(gd) { }); }; +/** + * get only visible menus for display + */ function makeMenuData(fullLayout) { - var contOpts = fullLayout[constants.name], - menuData = []; - - // Filter visible dropdowns and attach '_index' to each - // fullLayout options object to be used for 'object constancy' - // in the data join key function. + var contOpts = fullLayout[constants.name]; + var menuData = []; for(var i = 0; i < contOpts.length; i++) { var item = contOpts[i]; @@ -154,7 +156,7 @@ function makeMenuData(fullLayout) { // Note that '_index' is set at the default step, // it corresponds to the menu index in the user layout update menu container. -// Because a menu can b set invisible, +// Because a menu can be set invisible, // this is a more 'consistent' field than the index in the menuData. function keyFunction(menuOpts) { return menuOpts._index; diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 75f6b092529..e4a1e83d9bb 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -2830,25 +2830,25 @@ function makePlotFramework(gd) { // single geo layer for the whole plot fullLayout._geolayer = fullLayout._paper.append('g').classed('geolayer', true); - // upper shape layer - // (only for shapes to be drawn above the whole plot, including subplots) - var layerAbove = fullLayout._paper.append('g') - .classed('layer-above', true); - fullLayout._imageUpperLayer = layerAbove.append('g') - .classed('imagelayer', true); - fullLayout._shapeUpperLayer = layerAbove.append('g') - .classed('shapelayer', true); - // single pie layer for the whole plot fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true); // fill in image server scrape-svg fullLayout._glimages = fullLayout._paper.append('g').classed('glimages', true); - // lastly info (legend, annotations) and hover layers go on top + // lastly upper shapes, info (legend, annotations) and hover layers go on top // these are in a different svg element normally, but get collapsed into a single // svg when exporting (after inserting 3D) + // upper shapes/images are only those drawn above the whole plot, including subplots + var layerAbove = fullLayout._toppaper.append('g') + .classed('layer-above', true); + fullLayout._imageUpperLayer = layerAbove.append('g') + .classed('imagelayer', true); + fullLayout._shapeUpperLayer = layerAbove.append('g') + .classed('shapelayer', true); + fullLayout._infolayer = fullLayout._toppaper.append('g').classed('infolayer', true); + fullLayout._menulayer = fullLayout._toppaper.append('g').classed('menulayer', true); fullLayout._zoomlayer = fullLayout._toppaper.append('g').classed('zoomlayer', true); fullLayout._hoverlayer = fullLayout._toppaper.append('g').classed('hoverlayer', true); diff --git a/test/image/baselines/pie_style.png b/test/image/baselines/pie_style.png index a0ff83a138a..14a7aca811d 100644 Binary files a/test/image/baselines/pie_style.png and b/test/image/baselines/pie_style.png differ diff --git a/test/image/baselines/updatemenus.png b/test/image/baselines/updatemenus.png index 616f19ebe79..4cd63cf3296 100644 Binary files a/test/image/baselines/updatemenus.png and b/test/image/baselines/updatemenus.png differ diff --git a/test/image/mocks/pie_style.json b/test/image/mocks/pie_style.json index d27a8b61f4b..e88a658322f 100644 --- a/test/image/mocks/pie_style.json +++ b/test/image/mocks/pie_style.json @@ -30,6 +30,29 @@ "height": 400, "width": 500, "paper_bgcolor": "#ddd", - "showlegend": false + "showlegend": false, + "shapes": [{ + "type": "rect", + "xref": "paper", + "yref": "paper", + "x0": 0, + "y0": 0.4, + "x1": 1, + "y1": 0.6, + "fillcolor": "rgba(128, 0, 0, 0.5)", + "line": {"width": 0}, + "layer": "below" + }, { + "type": "rect", + "xref": "paper", + "yref": "paper", + "x0": 0.4, + "y0": 0, + "x1": 0.6, + "y1": 1, + "fillcolor": "rgba(0, 0, 128, 0.5)", + "line": {"width": 0}, + "layer": "above" + }] } } diff --git a/test/image/mocks/updatemenus.json b/test/image/mocks/updatemenus.json index 32cd7e55e7d..7cfb9ca9ed9 100644 --- a/test/image/mocks/updatemenus.json +++ b/test/image/mocks/updatemenus.json @@ -79,6 +79,16 @@ }, "visible": false, "name": "Data set 3" + }, + { + "x": [2, 3, 4], + "y": [0.4, 0.6, 0.8], + "z": [[1, 2], [3, 4]], + "type": "heatmap", + "colorbar": { + "x": -0.2, + "y": 0.6 + } } ], "layout": { @@ -123,7 +133,8 @@ true, false, false, - false + false, + true ] ], "label": "Data set 0" @@ -136,7 +147,8 @@ false, true, false, - false + false, + true ] ], "label": "Data set 1" @@ -149,7 +161,8 @@ false, false, true, - false + false, + true ] ], "label": "Data set 2" @@ -162,6 +175,7 @@ false, false, false, + true, true ] ], diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index 523a2d6f5e4..4e90579475d 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -671,6 +671,10 @@ describe('update menus interactions', function() { // fold up buttons whenever new menus are added assertMenus([0, 0]); + // dropdown buttons container should still be on top of headers (and non-dropdown buttons) + var gButton = d3.select('.updatemenu-dropdown-button-group'); + expect(gButton.node().nextSibling).toBe(null); + return Plotly.relayout(gd, { 'updatemenus[0].bgcolor': null, 'paper_bgcolor': 'black' @@ -826,7 +830,7 @@ describe('update menus interaction with other components:', function() { afterEach(destroyGraphDiv); - it('buttons show be drawn above sliders', function(done) { + it('draws buttons above sliders', function(done) { Plotly.plot(createGraphDiv(), [{ x: [1, 2, 3], @@ -869,19 +873,12 @@ describe('update menus interaction with other components:', function() { }) .then(function() { var infoLayer = d3.select('g.infolayer'); - var containerClassNames = ['slider-container', 'updatemenu-container']; - var list = []; - - infoLayer.selectAll('*').each(function() { - var className = d3.select(this).attr('class'); - - if(containerClassNames.indexOf(className) !== -1) { - list.push(className); - } - }); - - expect(list).toEqual(containerClassNames); + var menuLayer = d3.select('g.menulayer'); + expect(infoLayer.selectAll('.slider-container').size()).toBe(1); + expect(menuLayer.selectAll('.updatemenu-container').size()).toBe(1); + expect(infoLayer.node().nextSibling).toBe(menuLayer.node()); }) + .catch(fail) .then(done); }); });