From adc7a59db568a6e3610660110adb44a203a610f3 Mon Sep 17 00:00:00 2001 From: yhy0217 Date: Fri, 27 Jan 2023 17:33:54 -0400 Subject: [PATCH 1/5] fix contextmenu wrapping and submenu displaying bugs --- src/mapml.css | 5 ++++- src/mapml/handlers/ContextMenu.js | 17 +++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/mapml.css b/src/mapml.css index e098d13db..3f747e39d 100644 --- a/src/mapml.css +++ b/src/mapml.css @@ -258,7 +258,8 @@ background-color: #fff; cursor: default; position: absolute; - width: 160px; + width: fit-content; + display: inline-block; z-index: 10001; } @@ -272,6 +273,7 @@ border-bottom: 1px solid transparent; cursor: default; width: 100%; + display: block; } .mapml-contextmenu button.mapml-contextmenu-item.over { @@ -288,6 +290,7 @@ .mapml-contextmenu.mapml-submenu { width: 80px; margin-bottom: -2rem; + width: fit-content; } @supports (contain: layout) { diff --git a/src/mapml/handlers/ContextMenu.js b/src/mapml/handlers/ContextMenu.js index c3fa3cac4..6b27f7e37 100644 --- a/src/mapml/handlers/ContextMenu.js +++ b/src/mapml/handlers/ContextMenu.js @@ -442,6 +442,8 @@ export var ContextMenu = L.Handler.extend({ _show: function (e) { if(this._mapMenuVisible) this._hide(); + // the 'hidden' attribute must be removed before any attempt to get the size of container + else this._container.removeAttribute('hidden'); this._clickEvent = e; let elem = e.originalEvent.target; if(elem.closest("fieldset")){ @@ -646,17 +648,19 @@ export var ContextMenu = L.Handler.extend({ copyEl.setAttribute("aria-expanded","true"); menu.removeAttribute('hidden'); - if (click.containerPoint.x + 160 + 80 > mapSize.x) { + const menuWidth = this._container.offsetWidth, + submenuWidth = menu.offsetWidth; + if (click.containerPoint.x + menuWidth + submenuWidth > mapSize.x) { menu.style.left = 'auto'; - menu.style.right = 160 + 'px'; + menu.style.right = menuWidth + 'px'; } else { - menu.style.left = 160 + 'px'; + menu.style.left = menuWidth + 'px'; menu.style.right = 'auto'; } if (click.containerPoint.y + 160 > mapSize.y) { menu.style.top = 'auto'; - menu.style.bottom = 20 + 'px'; + menu.style.bottom = 32 + 'px'; // to make submenu show completely when clicking at the bottom of the map } else { menu.style.top = 100 + 'px'; menu.style.bottom = 'auto'; @@ -665,8 +669,9 @@ export var ContextMenu = L.Handler.extend({ }, _hideCoordMenu: function(e){ - if(e.srcElement.parentElement.classList.contains("mapml-submenu") || - e.srcElement.innerText === (M.options.locale.cmCopyCoords + " (C)"))return; + if(!e.relatedTarget || !e.relatedTarget.parentElement || + e.relatedTarget.parentElement.classList.contains("mapml-submenu") || + e.relatedTarget.classList.contains("mapml-submenu"))return; let menu = this._coordMenu, copyEl = this._items[5].el.el; copyEl.setAttribute("aria-expanded","false"); menu.setAttribute('hidden', ''); From 4d2e92f7823b76729e2759a6fee6601e432d1c23 Mon Sep 17 00:00:00 2001 From: yhy0217 Date: Sun, 29 Jan 2023 20:57:05 -0400 Subject: [PATCH 2/5] add a test in mapContextMenu.test.js --- test/e2e/core/mapContextMenu.test.js | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/e2e/core/mapContextMenu.test.js b/test/e2e/core/mapContextMenu.test.js index d849f486f..fa88f8463 100644 --- a/test/e2e/core/mapContextMenu.test.js +++ b/test/e2e/core/mapContextMenu.test.js @@ -305,4 +305,37 @@ test.describe("Playwright Map Context Menu Tests", () => { ); expect(layerCount).toEqual(5); }); + + test("Context menu, click at margin and move mouse out when submenu is visible", async () => { + // click at the right-bottom margin of map + await page.mouse.wheel(0, 200); + await page.waitForTimeout(200); + await page.click("body > map", { + button: 'right', + position: {x: 495, y: 580} + }); + const contextMenu = await page.locator('div > div.mapml-contextmenu').first(); + expect(await contextMenu.isVisible()).toBeTruthy(); + const mapSize = await page.$eval( + "body > map", + (map) => { return {x: map.width, y: map.height} } + ); + const contextMenuSize = await page.$eval( + "div > div.mapml-contextmenu", + (menu) => { + return { + x: menu.offsetWidth + menu.getBoundingClientRect().left, + y: menu.offsetHeight + menu.getBoundingClientRect().top + } + } + ); + expect(contextMenuSize.x <= mapSize.x && contextMenuSize.y <= mapSize.y).toBeTruthy(); + + // move the mouse from "copy" to another button in the main contextmenu + await contextMenu.hover(); + const submenu = await page.locator('div > div#mapml-copy-submenu').first(); + expect(await submenu.isVisible()).toBeTruthy(); + await page.hover("div > div.mapml-contextmenu > button:nth-child(5)"); + expect(await submenu.isHidden()).toBeTruthy(); + }); }); \ No newline at end of file From 417e3701a30ef0b664eddc1dc1234c53bebaa68f Mon Sep 17 00:00:00 2001 From: yhy0217 Date: Mon, 30 Jan 2023 15:37:56 -0500 Subject: [PATCH 3/5] stop layermenu and contextmenu from showing up at the same time --- src/mapml/handlers/ContextMenu.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mapml/handlers/ContextMenu.js b/src/mapml/handlers/ContextMenu.js index 6b27f7e37..2b4a88875 100644 --- a/src/mapml/handlers/ContextMenu.js +++ b/src/mapml/handlers/ContextMenu.js @@ -442,8 +442,6 @@ export var ContextMenu = L.Handler.extend({ _show: function (e) { if(this._mapMenuVisible) this._hide(); - // the 'hidden' attribute must be removed before any attempt to get the size of container - else this._container.removeAttribute('hidden'); this._clickEvent = e; let elem = e.originalEvent.target; if(elem.closest("fieldset")){ @@ -451,10 +449,13 @@ export var ContextMenu = L.Handler.extend({ elem = (elem.className === "mapml-layer-extent") ? elem.closest("fieldset").parentNode.parentNode.parentNode.querySelector("span") : elem.querySelector("span"); if(!elem.layer.validProjection) return; this._layerClicked = elem; + this._layerMenu.removeAttribute('hidden'); this._showAtPoint(e.containerPoint, e, this._layerMenu); } else if(elem.classList.contains("leaflet-container") || elem.classList.contains("mapml-debug-extent") || - elem.tagName === "path") { + elem.tagName === "path") { this._layerClicked = undefined; + // the 'hidden' attribute must be removed before any attempt to get the size of container + this._container.removeAttribute('hidden'); this._showAtPoint(e.containerPoint, e, this._container); } if(e.originalEvent.button === 0 || e.originalEvent.button === -1){ From 20629c107109b999e140c6701ad81e9bd3a79f05 Mon Sep 17 00:00:00 2001 From: yhy0217 Date: Tue, 31 Jan 2023 10:26:31 -0500 Subject: [PATCH 4/5] fix submenu cut off --- src/mapml/handlers/ContextMenu.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/mapml/handlers/ContextMenu.js b/src/mapml/handlers/ContextMenu.js index 2b4a88875..39121a2e9 100644 --- a/src/mapml/handlers/ContextMenu.js +++ b/src/mapml/handlers/ContextMenu.js @@ -119,22 +119,22 @@ export var ContextMenu = L.Handler.extend({ for (let i = 0; i < 6; i++) { this._items[i].el = this._createItem(this._container, this._items[i]); } - + this._coordMenu = L.DomUtil.create("div", "mapml-contextmenu mapml-submenu", this._container); this._coordMenu.id = "mapml-copy-submenu"; this._coordMenu.setAttribute('hidden', ''); - + this._clickEvent = null; - + for(let i =0;i mapSize.x) { menu.style.left = 'auto'; menu.style.right = menuWidth + 'px'; @@ -659,9 +660,10 @@ export var ContextMenu = L.Handler.extend({ menu.style.right = 'auto'; } - if (click.containerPoint.y + 160 > mapSize.y) { + if (click.containerPoint.y + menuHeight + 73 > mapSize.y) { menu.style.top = 'auto'; - menu.style.bottom = 32 + 'px'; // to make submenu show completely when clicking at the bottom of the map + // to make submenu show completely when clicking at the bottom of the map + menu.style.bottom = 32 + 'px'; } else { menu.style.top = 100 + 'px'; menu.style.bottom = 'auto'; From e18a06c022b23fc64a9a91f8235c44bdc8940c95 Mon Sep 17 00:00:00 2001 From: yhy0217 Date: Tue, 31 Jan 2023 12:52:00 -0500 Subject: [PATCH 5/5] change number to variable for easier understanding --- src/mapml/handlers/ContextMenu.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mapml/handlers/ContextMenu.js b/src/mapml/handlers/ContextMenu.js index 39121a2e9..9ad2868b4 100644 --- a/src/mapml/handlers/ContextMenu.js +++ b/src/mapml/handlers/ContextMenu.js @@ -660,7 +660,9 @@ export var ContextMenu = L.Handler.extend({ menu.style.right = 'auto'; } - if (click.containerPoint.y + menuHeight + 73 > mapSize.y) { + // height difference between the main contextmenu and submenu + const heightDiff = 73; + if (click.containerPoint.y + menuHeight + heightDiff > mapSize.y) { menu.style.top = 'auto'; // to make submenu show completely when clicking at the bottom of the map menu.style.bottom = 32 + 'px';