diff --git a/src/mapml-viewer.js b/src/mapml-viewer.js index 9c4df41cf..1eb5a0a18 100644 --- a/src/mapml-viewer.js +++ b/src/mapml-viewer.js @@ -537,6 +537,20 @@ export class MapViewer extends HTMLElement { }; this._historyIndex++; this._history.splice(this._historyIndex, 0, location); + // Remove future history and overwrite it when map pan/zoom while inside history + if (this._historyIndex + 1 !== this._history.length) { + this._history.length = this._historyIndex + 1; + } + if (this._historyIndex === 0) { + // when at initial state of map, disable back, forward, and reload items + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + } else { + this._map.contextMenu._items[0].el.el.disabled = false; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = false; // reload contextmenu item + } } /** @@ -547,8 +561,14 @@ export class MapViewer extends HTMLElement { let curr = history[this._historyIndex]; if(this._historyIndex > 0){ + this._map.contextMenu._items[1].el.el.disabled = false; // forward contextmenu item this._historyIndex--; let prev = history[this._historyIndex]; + // Disable back, reload contextmenu item when at the end of history + if (this._historyIndex === 0) { + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + } if(prev.zoom !== curr.zoom){ this._traversalCall = 2; // allows the next 2 moveends to be ignored from history @@ -574,8 +594,14 @@ export class MapViewer extends HTMLElement { let history = this._history; let curr = history[this._historyIndex]; if(this._historyIndex < history.length - 1){ + this._map.contextMenu._items[0].el.el.disabled = false; // back contextmenu item + this._map.contextMenu._items[2].el.el.disabled = false; // reload contextmenu item this._historyIndex++; let next = history[this._historyIndex]; + // disable forward contextmenu item, when at the end of forward history + if (this._historyIndex + 1 === this._history.length) { + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + } if(next.zoom !== curr.zoom){ this._traversalCall = 2; // allows the next 2 moveends to be ignored from history @@ -606,6 +632,10 @@ export class MapViewer extends HTMLElement { y:mapLocation.y, }; + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + this._history = [initialLocation]; this._historyIndex = 0; diff --git a/src/mapml/handlers/ContextMenu.js b/src/mapml/handlers/ContextMenu.js index 9ad2868b4..fcbc3e9b3 100644 --- a/src/mapml/handlers/ContextMenu.js +++ b/src/mapml/handlers/ContextMenu.js @@ -466,7 +466,7 @@ export var ContextMenu = L.Handler.extend({ this._layerMenuTabs = 1; this._layerMenu.firstChild.focus(); } else { - this._container.firstChild.focus(); + this._container.querySelectorAll("button:not([disabled])")[0].focus(); } } diff --git a/src/web-map.js b/src/web-map.js index ae1fa5605..9fb682af0 100644 --- a/src/web-map.js +++ b/src/web-map.js @@ -578,6 +578,20 @@ export class WebMap extends HTMLMapElement { }; this._historyIndex++; this._history.splice(this._historyIndex, 0, location); + // Remove future history and overwrite it when map pan/zoom while inside history + if (this._historyIndex + 1 !== this._history.length) { + this._history.length = this._historyIndex + 1; + } + if (this._historyIndex === 0) { + // when at initial state of map, disable back, forward, and reload items + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + } else { + this._map.contextMenu._items[0].el.el.disabled = false; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = false; // reload contextmenu item + } } /** @@ -588,8 +602,14 @@ export class WebMap extends HTMLMapElement { let curr = history[this._historyIndex]; if(this._historyIndex > 0){ + this._map.contextMenu._items[1].el.el.disabled = false; // forward contextmenu item this._historyIndex--; let prev = history[this._historyIndex]; + // Disable back, reload contextmenu item when at the end of history + if (this._historyIndex === 0) { + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + } if(prev.zoom !== curr.zoom){ this._traversalCall = 2; // allows the next 2 moveends to be ignored from history @@ -615,8 +635,14 @@ export class WebMap extends HTMLMapElement { let history = this._history; let curr = history[this._historyIndex]; if(this._historyIndex < history.length - 1){ + this._map.contextMenu._items[0].el.el.disabled = false; // back contextmenu item + this._map.contextMenu._items[2].el.el.disabled = false; // reload contextmenu item this._historyIndex++; let next = history[this._historyIndex]; + // disable forward contextmenu item, when at the end of forward history + if (this._historyIndex + 1 === this._history.length) { + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + } if(next.zoom !== curr.zoom){ this._traversalCall = 2; // allows the next 2 moveends to be ignored from history @@ -647,6 +673,10 @@ export class WebMap extends HTMLMapElement { y:mapLocation.y, }; + this._map.contextMenu._items[0].el.el.disabled = true; // back contextmenu item + this._map.contextMenu._items[1].el.el.disabled = true; // forward contextmenu item + this._map.contextMenu._items[2].el.el.disabled = true; // reload contextmenu item + this._history = [initialLocation]; this._historyIndex = 0; diff --git a/test/e2e/core/mapContextMenu.test.js b/test/e2e/core/mapContextMenu.test.js index fa88f8463..945d4fab3 100644 --- a/test/e2e/core/mapContextMenu.test.js +++ b/test/e2e/core/mapContextMenu.test.js @@ -46,7 +46,7 @@ test.describe("Playwright Map Context Menu Tests", () => { const nameHandle = await page.evaluateHandle(name => name.outerText, resultHandle); let name = await nameHandle.jsonValue(); await nameHandle.dispose(); - expect(name).toEqual("Back (B)"); + expect(name).toEqual("Toggle Controls (T)"); }); test("Context menu tab goes to next item", async () => { @@ -57,7 +57,7 @@ test.describe("Playwright Map Context Menu Tests", () => { const nameHandle = await page.evaluateHandle(name => name.outerText, resultHandle); let name = await nameHandle.jsonValue(); await nameHandle.dispose(); - expect(name).toEqual("Forward (F)"); + expect(name).toEqual("Copy Coordinates (C)"); }); test("Submenu opens on C with focus on first item", async () => { @@ -100,21 +100,24 @@ test.describe("Playwright Map Context Menu Tests", () => { expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[0]); expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[0]); }); - test("Context menu, back item at intial location", async () => { + test("Context menu, back and reload item at initial location disabled", async () => { await page.click("body > map", { button: "right" }); - await page.click("div > div.mapml-contextmenu > button:nth-child(1)"); - await page.waitForTimeout(1000); - const extent = await page.$eval( - "body > map", - (map) => map.extent + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled ); - expect(extent.projection).toEqual("CBMTILE"); - expect(extent.zoom).toEqual({ minZoom: 0, maxZoom: 25 }); - expect(extent.topLeft.pcrs).toEqual(expectedPCRS[0]); - expect(extent.topLeft.gcrs).toEqual(expectedGCRS[0]); - expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[0]); - expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[0]); + expect(backBtn).toEqual(true); + expect(fwdBtn).toEqual(false); + expect(reloadBtn).toEqual(true); }); test("Context menu, forward item", async () => { await page.click("body > map", { button: "right" }); @@ -131,20 +134,24 @@ test.describe("Playwright Map Context Menu Tests", () => { expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[1]); expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[1]); }); - test("Context menu, forward item at most recent location", async () => { + test("Context menu, forward item at most recent location disabled", async () => { await page.click("body > map", { button: "right" }); - await page.click("div > div.mapml-contextmenu > button:nth-child(2)"); - await page.waitForTimeout(1000); - const extent = await page.$eval( - "body > map", - (map) => map.extent + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled ); - expect(extent.zoom).toEqual({ minZoom: 0, maxZoom: 25 }); - expect(extent.topLeft.pcrs).toEqual(expectedPCRS[1]); - expect(extent.topLeft.gcrs).toEqual(expectedGCRS[1]); - expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[1]); - expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[1]); + expect(backBtn).toEqual(false); + expect(fwdBtn).toEqual(true); + expect(reloadBtn).toEqual(false); }); test.describe("Context Menu, Toggle Controls ", () => { @@ -218,7 +225,7 @@ test.describe("Playwright Map Context Menu Tests", () => { await page.click("body > map"); await page.keyboard.press("Shift+F10"); - for (let i = 0; i < 4; i++) + for (let i = 0; i < 3; i++) await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); @@ -338,4 +345,37 @@ test.describe("Playwright Map Context Menu Tests", () => { await page.hover("div > div.mapml-contextmenu > button:nth-child(5)"); expect(await submenu.isHidden()).toBeTruthy(); }); + + test("Context menu, All buttons enabled when fwd and back history present", async () => { + await page.click("body > map"); + await page.$eval( + "body > map", + (map) => map.zoomTo(81, -63, 3) + ); + await page.waitForTimeout(1000); + await page.$eval( + "body > map", + (map) => map.zoomTo(81, -63, 5) + ); + await page.waitForTimeout(1000); + await page.click("body > map", { button: "right" }); + await page.click("div > div.mapml-contextmenu > button:nth-child(1)"); + await page.click("body > map", { button: "right" }); + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled + ); + + expect(backBtn).toEqual(false); + expect(fwdBtn).toEqual(false); + expect(reloadBtn).toEqual(false); + }); }); \ No newline at end of file diff --git a/test/e2e/mapml-viewer/mapml-viewer.test.js b/test/e2e/mapml-viewer/mapml-viewer.test.js index e02b0746f..30b4baacc 100644 --- a/test/e2e/mapml-viewer/mapml-viewer.test.js +++ b/test/e2e/mapml-viewer/mapml-viewer.test.js @@ -170,7 +170,7 @@ test.describe("Playwright mapml-viewer Element Tests", () => { await page.click("body > mapml-viewer"); await page.keyboard.press('Control+v'); - await page.waitForTimeout(500); + await page.waitForTimeout(1000); const layerCount = await page.$eval( "body > mapml-viewer", (map) => map.layers.length diff --git a/test/e2e/mapml-viewer/viewerContextMenu.test.js b/test/e2e/mapml-viewer/viewerContextMenu.test.js index 108dd9f87..409573a86 100644 --- a/test/e2e/mapml-viewer/viewerContextMenu.test.js +++ b/test/e2e/mapml-viewer/viewerContextMenu.test.js @@ -38,7 +38,7 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { const nameHandle = await page.evaluateHandle(name => name.outerText, resultHandle); let name = await nameHandle.jsonValue(); await nameHandle.dispose(); - expect(name).toEqual("Back (B)"); + expect(name).toEqual("Toggle Controls (T)"); }); test("Context menu tab goes to next item", async () => { @@ -49,7 +49,7 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { const nameHandle = await page.evaluateHandle(name => name.outerText, resultHandle); let name = await nameHandle.jsonValue(); await nameHandle.dispose(); - expect(name).toEqual("Forward (F)"); + expect(name).toEqual("Copy Coordinates (C)"); }); @@ -61,7 +61,7 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { const nameHandle = await page.evaluateHandle(name => name.outerText, resultHandle); let name = await nameHandle.jsonValue(); await nameHandle.dispose(); - expect(name).toEqual("Back (B)"); + expect(name).toEqual("Toggle Controls (T)"); }); test("Submenu opens on C with focus on first item", async () => { @@ -104,21 +104,24 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[0]); expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[0]); }); - test("Context menu, back item at intial location", async () => { + test("Context menu, back and reload item at initial location disabled", async () => { await page.click("body > mapml-viewer", { button: "right" }); - await page.click("div > div.mapml-contextmenu > button:nth-child(1)"); - await page.waitForTimeout(1000); - const extent = await page.$eval( - "body > mapml-viewer", - (map) => map.extent + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled ); - expect(extent.projection).toEqual("CBMTILE"); - expect(extent.zoom).toEqual({ minZoom: 0, maxZoom: 25 }); - expect(extent.topLeft.pcrs).toEqual(expectedPCRS[0]); - expect(extent.topLeft.gcrs).toEqual(expectedGCRS[0]); - expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[0]); - expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[0]); + expect(backBtn).toEqual(true); + expect(fwdBtn).toEqual(false); + expect(reloadBtn).toEqual(true); }); test("Context menu, forward item", async () => { await page.click("body > mapml-viewer", { button: "right" }); @@ -135,20 +138,24 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[1]); expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[1]); }); - test("Context menu, forward item at most recent location", async () => { + test("Context menu, forward item at most recent location disabled", async () => { await page.click("body > mapml-viewer", { button: "right" }); - await page.click("div > div.mapml-contextmenu > button:nth-child(2)"); - await page.waitForTimeout(1000); - const extent = await page.$eval( - "body > mapml-viewer", - (map) => map.extent + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled ); - expect(extent.zoom).toEqual({ minZoom: 0, maxZoom: 25 }); - expect(extent.topLeft.pcrs).toEqual(expectedPCRS[1]); - expect(extent.topLeft.gcrs).toEqual(expectedGCRS[1]); - expect(extent.topLeft.tilematrix[0]).toEqual(expectedFirstTileMatrix[1]); - expect(extent.topLeft.tcrs[0]).toEqual(expectedFirstTCRS[1]); + expect(backBtn).toEqual(false); + expect(fwdBtn).toEqual(true); + expect(reloadBtn).toEqual(false); }); test.describe("Context Menu, Toggle Controls ", () => { @@ -222,7 +229,7 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { test("Submenu, copy all coordinate systems using tab + enter to access", async () => { await page.click("body > mapml-viewer"); await page.keyboard.press("Shift+F10"); - for (let i = 0; i < 4; i++) + for (let i = 0; i < 3; i++) await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); @@ -271,4 +278,37 @@ test.describe("Playwright mapml-viewer Context Menu (and api) Tests", () => { expect(copyValue).toEqual(expected); }); + + test("Context menu, All buttons enabled when fwd and back history present", async () => { + await page.click("body > mapml-viewer"); + await page.$eval( + "body > mapml-viewer", + (map) => map.zoomTo(81, -63, 3) + ); + await page.waitForTimeout(1000); + await page.$eval( + "body > mapml-viewer", + (map) => map.zoomTo(81, -63, 5) + ); + await page.waitForTimeout(1000); + await page.click("body > mapml-viewer", { button: "right" }); + await page.click("div > div.mapml-contextmenu > button:nth-child(1)"); + await page.click("body > mapml-viewer", { button: "right" }); + const backBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(1)", + (btn) => btn.disabled + ); + const fwdBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(2)", + (btn) => btn.disabled + ); + const reloadBtn = await page.$eval( + "div > div.mapml-contextmenu > button:nth-child(3)", + (btn) => btn.disabled + ); + + expect(backBtn).toEqual(false); + expect(fwdBtn).toEqual(false); + expect(reloadBtn).toEqual(false); + }); }); \ No newline at end of file