From 2204f08dddc8906959286d49b55ece65c9df09db Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Fri, 12 Feb 2021 15:56:36 -0500 Subject: [PATCH 1/6] Follows updated keyboard interaction rules --- src/mapml.css | 6 +++--- src/mapml/handlers/QueryHandler.js | 6 +++++- src/mapml/layers/Crosshair.js | 34 +++++++++++++++--------------- src/mapml/layers/MapLayer.js | 30 ++++++++++++++++++++------ 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/mapml.css b/src/mapml.css index 37fada4c1..230d591a4 100644 --- a/src/mapml.css +++ b/src/mapml.css @@ -391,9 +391,9 @@ summary { } .mapml-crosshair { - margin: -18px 0 0 -18px; - width: 36px; - height: 36px; + margin: -36px 0 0 -36px; + width: 72px; + height: 72px; left: 50%; top: 50%; content: ''; diff --git a/src/mapml/handlers/QueryHandler.js b/src/mapml/handlers/QueryHandler.js index cbf14e012..b40456115 100644 --- a/src/mapml/handlers/QueryHandler.js +++ b/src/mapml/handlers/QueryHandler.js @@ -22,13 +22,17 @@ export var QueryHandler = L.Handler.extend({ } }, _queryTopLayerAtMapCenter: function (event) { - if (event.originalEvent.key === " ") { + setTimeout(() => { + if (this._map.isFocused && !this._map._popupClosed && (event.originalEvent.key === " " || +event.originalEvent.keyCode === 13)) { this._map.fire('click', { latlng: this._map.getCenter(), layerPoint: this._map.latLngToLayerPoint(this._map.getCenter()), containerPoint: this._map.latLngToContainerPoint(this._map.getCenter()) }); + } else { + delete this._map._popupClosed; } + }, 0); }, _queryTopLayer: function(event) { var layer = this._getTopQueryableLayer(); diff --git a/src/mapml/layers/Crosshair.js b/src/mapml/layers/Crosshair.js index ad622adb1..4021ee00f 100644 --- a/src/mapml/layers/Crosshair.js +++ b/src/mapml/layers/Crosshair.js @@ -30,16 +30,22 @@ export var Crosshair = L.Layer.extend({ this._container = L.DomUtil.create("div", "mapml-crosshair", map._container); this._container.innerHTML = svgInnerHTML; - this._mapFocused = false; + map.isFocused = false; this._isQueryable = false; map.on("layerchange layeradd layerremove overlayremove", this._toggleEvents, this); - L.DomEvent.on(map._container, "keydown keyup mousedown", this._onKey, this); - + map.on("popupopen", this._isMapFocused, this); + L.DomEvent.on(map._container, "keydown keyup mousedown", this._isMapFocused, this); this._addOrRemoveCrosshair(); }, + onRemove: function (map) { + map.off("layerchange layeradd layerremove overlayremove", this._toggleEvents); + map.off("popupopen", this._isMapFocused); + L.DomEvent.off(map._container, "keydown keyup mousedown", this._isMapFocused); + }, + _toggleEvents: function () { if (this._hasQueryableLayer()) { this._map.on("viewreset move moveend", this._addOrRemoveCrosshair, this); @@ -59,7 +65,7 @@ export var Crosshair = L.Layer.extend({ _hasQueryableLayer: function () { let layers = this._map.options.mapEl.layers; - if (this._mapFocused) { + if (this._map.isFocused) { for (let layer of layers) { if (layer.checked && layer._layer.queryable) { return true; @@ -69,20 +75,14 @@ export var Crosshair = L.Layer.extend({ return false; }, - _onKey: function (e) { - //set mapFocused = true if arrow buttons are used - if (["keydown", "keyup"].includes(e.type) && e.target.classList.contains("leaflet-container") && [32, 37, 38, 39, 40, 187, 189].includes(+e.keyCode)) { - this._mapFocused = true; - //set mapFocused = true if map is focued using tab - } else if (e.type === "keyup" && e.target.classList.contains("leaflet-container") && +e.keyCode === 9) { - this._mapFocused = true; - // set mapFocused = false and close all popups if tab or escape is used - } else if((e.type === "keyup" && e.target.classList.contains("leaflet-interactive") && +e.keyCode === 9) || +e.keyCode === 27){ - this._mapFocused = false; - this._map.closePopup(); - // set mapFocused = false if any other key is pressed + _isMapFocused: function (e) { + //set this._map.isFocused = true if arrow buttons are used + if (this._map._container.parentNode.activeElement.classList.contains("leaflet-container") && ["keydown"].includes(e.type) && (e.shiftKey && e.keyCode === 9)) { + this._map.isFocused = false; + } else if (this._map._container.parentNode.activeElement.classList.contains("leaflet-container") && ["keyup", "keydown"].includes(e.type)) { + this._map.isFocused = true; } else { - this._mapFocused = false; + this._map.isFocused = false; } this._addOrRemoveCrosshair(); }, diff --git a/src/mapml/layers/MapLayer.js b/src/mapml/layers/MapLayer.js index 97968e32d..6bf0c7e70 100644 --- a/src/mapml/layers/MapLayer.js +++ b/src/mapml/layers/MapLayer.js @@ -1162,8 +1162,7 @@ export var MapMLLayer = L.Layer.extend({ content = popup._container.getElementsByClassName("mapml-popup-content")[0]; content.setAttribute("tabindex", "-1"); - content.focus(); - popup._count = 0; + popup._count = 0; // used for feature pagination if(popup._source._eventParents){ // check if the popup is for a feature or query layer = popup._source._eventParents[Object.keys(popup._source._eventParents)[0]]; // get first parent of feature, there should only be one @@ -1232,7 +1231,11 @@ export var MapMLLayer = L.Layer.extend({ L.DomEvent.on(controlFocusButton, 'click', L.DomEvent.stop); L.DomEvent.on(controlFocusButton, 'click', (e) => { map.closePopup(); - map._controlContainer.focus(); + if(map._controlContainer.firstElementChild.firstElementChild.firstElementChild){ + map._controlContainer.firstElementChild.firstElementChild.firstElementChild.focus(); + } else { + map._controlContainer.focus(); + } }, popup); let divider = L.DomUtil.create("hr"); @@ -1241,19 +1244,23 @@ export var MapMLLayer = L.Layer.extend({ popup._navigationBar = div; popup._content.appendChild(divider); popup._content.appendChild(div); - + + nextButton.focus(); if(path) { // e.target = this._map // Looks for keydown, more specifically tab and shift tab map.on("keydown", focusFeature); - // if popup closes then the focusFeature handler can be removed - map.on("popupclose", removeHandlers); + } else { + map.on("keydown", focusMap); } + // if popup closes then the focusFeature handler can be removed + map.once("popupclose", removeHandlers); // When popup is open, what gets focused with tab needs to be done using JS as the DOM order is not in an accessibility friendly manner function focusFeature(focusEvent){ if(focusEvent.originalEvent.path[0].title==="Focus Controls" && +focusEvent.originalEvent.keyCode === 9){ L.DomEvent.stop(focusEvent); + map.closePopup(popup); path.focus(); } else if(focusEvent.originalEvent.shiftKey && +focusEvent.originalEvent.keyCode === 9){ map.closePopup(popup); @@ -1262,10 +1269,19 @@ export var MapMLLayer = L.Layer.extend({ } } + function focusMap(focusEvent){ + if((focusEvent.originalEvent.keyCode === 13 && focusEvent.originalEvent.path[0].classList.contains("leaflet-popup-close-button")) || focusEvent.originalEvent.keyCode === 27 ){ + L.DomEvent.stopPropagation(focusEvent); + map._container.focus(); + map.closePopup(); + if(focusEvent.originalEvent.keyCode !== 27)map._popupClosed = true; + } + } + function removeHandlers(removeEvent){ if (removeEvent.popup === popup){ map.off("keydown", focusFeature); - map.off("popupclose", removeHandlers); + map.off("keydown", focusMap); } } }, From 9d5c0115a3467fbaec1f76af6b9bb7c0fa93a598 Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Fri, 12 Feb 2021 16:42:23 -0500 Subject: [PATCH 2/6] Test updates --- src/mapml/layers/MapLayer.js | 8 ++-- test/e2e/core/keyboardInteraction.test.js | 52 +++++++++-------------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/mapml/layers/MapLayer.js b/src/mapml/layers/MapLayer.js index 6bf0c7e70..c5d833f95 100644 --- a/src/mapml/layers/MapLayer.js +++ b/src/mapml/layers/MapLayer.js @@ -1258,14 +1258,12 @@ export var MapMLLayer = L.Layer.extend({ map.once("popupclose", removeHandlers); // When popup is open, what gets focused with tab needs to be done using JS as the DOM order is not in an accessibility friendly manner function focusFeature(focusEvent){ - if(focusEvent.originalEvent.path[0].title==="Focus Controls" && +focusEvent.originalEvent.keyCode === 9){ + if((focusEvent.originalEvent.path[0].title==="Focus Controls" && focusEvent.originalEvent.keyCode === 9 && !focusEvent.originalEvent.shiftKey) || + (focusEvent.originalEvent.path[0].title==="Focus Map" && focusEvent.originalEvent.keyCode === 9 && focusEvent.originalEvent.shiftKey) || + focusEvent.originalEvent.keyCode === 27){ L.DomEvent.stop(focusEvent); map.closePopup(popup); path.focus(); - } else if(focusEvent.originalEvent.shiftKey && +focusEvent.originalEvent.keyCode === 9){ - map.closePopup(popup); - L.DomEvent.stop(focusEvent); - path.focus(); } } diff --git a/test/e2e/core/keyboardInteraction.test.js b/test/e2e/core/keyboardInteraction.test.js index 9866c958f..1c969caa9 100644 --- a/test/e2e/core/keyboardInteraction.test.js +++ b/test/e2e/core/keyboardInteraction.test.js @@ -7,7 +7,7 @@ jest.setTimeout(50000); () => { beforeAll(async () => { browser = await playwright[browserType].launch({ - headless: ISHEADLESS, + headless: false,//ISHEADLESS, slowMo: 50, }); context = await browser.newContext(); @@ -30,7 +30,7 @@ jest.setTimeout(50000); expect(afterTab).toEqual(""); }); - test("[" + browserType + "]" + " Crosshair remains on map move with arrow keys + space", async () => { + test("[" + browserType + "]" + " Crosshair remains on map move with arrow keys", async () => { await page.keyboard.press("ArrowUp"); await page.waitForTimeout(500); await page.keyboard.press("ArrowDown"); @@ -39,13 +39,11 @@ jest.setTimeout(50000); await page.waitForTimeout(500); await page.keyboard.press("ArrowRight"); await page.waitForTimeout(500); - await page.keyboard.press(" ") - await page.waitForTimeout(500); const afterMove = await page.$eval("div > div.mapml-crosshair", (div) => div.style.visibility); expect(afterMove).toEqual(""); }); - test("[" + browserType + "]" + " Crosshair hidden on esc + tab out", async () => { + test("[" + browserType + "]" + " Crosshair shows on esc but hidden on tab out", async () => { await page.keyboard.press("Escape"); const afterEsc = await page.$eval("div > div.mapml-crosshair", (div) => div.style.visibility); await page.click("body"); @@ -55,7 +53,7 @@ jest.setTimeout(50000); await page.keyboard.press("Tab"); const afterTab = await page.$eval("div > div.mapml-crosshair", (div) => div.style.visibility); - expect(afterEsc).toEqual("hidden"); + expect(afterEsc).toEqual(""); expect(afterTab).toEqual("hidden"); }); @@ -132,47 +130,37 @@ jest.setTimeout(50000); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); const rh = await page.evaluateHandle(root => root.activeElement, nh); - const f = await (await page.evaluateHandle(elem => elem.className, rh)).jsonValue(); + const f = await (await page.evaluateHandle(elem => elem.title, rh)).jsonValue(); await page.keyboard.press("Tab"); const h2 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh2 = await page.evaluateHandle(doc => doc.shadowRoot, h2); const rh2 = await page.evaluateHandle(root => root.activeElement, nh2); - const f2 = await (await page.evaluateHandle(elem => elem.tagName, rh2)).jsonValue(); + const f2 = await (await page.evaluateHandle(elem => elem.title, rh2)).jsonValue(); - await page.keyboard.press("Tab"); + await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Shift+Tab"); const h3 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh3 = await page.evaluateHandle(doc => doc.shadowRoot, h3); const rh3 = await page.evaluateHandle(root => root.activeElement, nh3); const f3 = await (await page.evaluateHandle(elem => elem.title, rh3)).jsonValue(); - await page.keyboard.press("Tab"); + await page.keyboard.press("Shift+Tab"); const h4 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh4 = await page.evaluateHandle(doc => doc.shadowRoot, h4); const rh4 = await page.evaluateHandle(root => root.activeElement, nh4); const f4 = await (await page.evaluateHandle(elem => elem.title, rh4)).jsonValue(); - await page.keyboard.press("Tab"); - const h5 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); - const nh5 = await page.evaluateHandle(doc => doc.shadowRoot, h5); - const rh5 = await page.evaluateHandle(root => root.activeElement, nh5); - const f5 = await (await page.evaluateHandle(elem => elem.title, rh5)).jsonValue(); - - await page.keyboard.press("Tab"); - const h6 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); - const nh6 = await page.evaluateHandle(doc => doc.shadowRoot, h6); - const rh6 = await page.evaluateHandle(root => root.activeElement, nh6); - const f6 = await (await page.evaluateHandle(elem => elem.title, rh6)).jsonValue(); - - expect(f).toEqual("mapml-popup-content"); - expect(f2).toEqual("A"); - expect(f3).toEqual("Focus Map"); - expect(f4).toEqual("Previous Feature"); - expect(f5).toEqual("Next Feature"); - expect(f6).toEqual("Focus Controls"); + expect(f).toEqual("Next Feature"); + expect(f2).toEqual("Focus Controls"); + expect(f3).toEqual("Previous Feature"); + expect(f4).toEqual("Focus Map"); }); test("[" + browserType + "]" + " Tab to next feature after tabbing out of popup", async () => { + await page.keyboard.press("Tab"); + await page.keyboard.press("Tab"); + await page.keyboard.press("Tab"); await page.keyboard.press("Tab"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); @@ -185,6 +173,8 @@ jest.setTimeout(50000); test("[" + browserType + "]" + " Shift + Tab to previous feature while popup open", async () => { await page.keyboard.press("Enter"); await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Shift+Tab"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); const rh = await page.evaluateHandle(root => root.activeElement, nh); @@ -196,8 +186,7 @@ jest.setTimeout(50000); test("[" + browserType + "]" + " Previous feature button focuses previous feature", async () => { await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); - await page.keyboard.press("Tab"); - await page.keyboard.press("Tab"); + await page.keyboard.press("Shift+Tab"); await page.keyboard.press("Enter"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); @@ -210,9 +199,6 @@ jest.setTimeout(50000); test("[" + browserType + "]" + " Next feature button focuses next feature", async () => { await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); - await page.keyboard.press("Tab"); - await page.keyboard.press("Tab"); - await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); From 6869d7a94e9d0005bd35d65357017c2d579dd43c Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Fri, 12 Feb 2021 16:47:39 -0500 Subject: [PATCH 3/6] Change to headless test --- test/e2e/core/keyboardInteraction.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/core/keyboardInteraction.test.js b/test/e2e/core/keyboardInteraction.test.js index 1c969caa9..d24d742bb 100644 --- a/test/e2e/core/keyboardInteraction.test.js +++ b/test/e2e/core/keyboardInteraction.test.js @@ -7,7 +7,7 @@ jest.setTimeout(50000); () => { beforeAll(async () => { browser = await playwright[browserType].launch({ - headless: false,//ISHEADLESS, + headless: ISHEADLESS, slowMo: 50, }); context = await browser.newContext(); From 9ba063143bb6d2f358945a90fb0a3320a3b20e1a Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Mon, 15 Feb 2021 11:00:41 -0500 Subject: [PATCH 4/6] Open feature popup on space --- src/mapml/layers/FeatureLayer.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mapml/layers/FeatureLayer.js b/src/mapml/layers/FeatureLayer.js index d90321683..2c5c81ce4 100644 --- a/src/mapml/layers/FeatureLayer.js +++ b/src/mapml/layers/FeatureLayer.js @@ -281,6 +281,10 @@ export var MapMLFeatures = L.FeatureGroup.extend({ if (options.onEachFeature) { options.onEachFeature(layer.properties, layer); + layer._events.keypress.push({ + "ctx": layer, + "fn": this._onSpacePress, + }); } if(this._staticFeature){ let featureZoom = mapml.getAttribute('zoom') || nativeZoom; @@ -324,6 +328,11 @@ export var MapMLFeatures = L.FeatureGroup.extend({ for(let i = 0; i < toDelete.length;i++){ this._container.removeChild(toDelete[i]); } + }, + _onSpacePress: function(e){ + if(e.originalEvent.keyCode === 32){ + this._openPopup(e); + } }, geometryToLayer: function (mapml, pointToLayer, coordsToLatLng, vectorOptions, nativeCS, zoom) { var geometry = mapml.tagName.toUpperCase() === 'FEATURE' ? mapml.getElementsByTagName('geometry')[0] : mapml, From b397851cf90deab8f003cd0450112183b1e87177 Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Tue, 16 Feb 2021 10:49:52 -0500 Subject: [PATCH 5/6] New interactions --- src/mapml/layers/MapLayer.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/mapml/layers/MapLayer.js b/src/mapml/layers/MapLayer.js index adfba2c00..941722a7f 100644 --- a/src/mapml/layers/MapLayer.js +++ b/src/mapml/layers/MapLayer.js @@ -1245,7 +1245,7 @@ export var MapMLLayer = L.Layer.extend({ popup._content.appendChild(divider); popup._content.appendChild(div); - nextButton.focus(); + content.focus(); if(path) { // e.target = this._map @@ -1254,16 +1254,20 @@ export var MapMLLayer = L.Layer.extend({ } else { map.on("keydown", focusMap); } - // if popup closes then the focusFeature handler can be removed - map.once("popupclose", removeHandlers); // When popup is open, what gets focused with tab needs to be done using JS as the DOM order is not in an accessibility friendly manner function focusFeature(focusEvent){ - if((focusEvent.originalEvent.path[0].title==="Focus Controls" && focusEvent.originalEvent.keyCode === 9 && !focusEvent.originalEvent.shiftKey) || - (focusEvent.originalEvent.path[0].title==="Focus Map" && focusEvent.originalEvent.keyCode === 9 && focusEvent.originalEvent.shiftKey) || - focusEvent.originalEvent.keyCode === 27){ + let isTab = focusEvent.originalEvent.keyCode === 9, + shiftPressed = focusEvent.originalEvent.shiftKey; + if((focusEvent.originalEvent.path[0].title==="Focus Controls" && isTab && !shiftPressed) || focusEvent.originalEvent.keyCode === 27){ L.DomEvent.stop(focusEvent); map.closePopup(popup); path.focus(); + } else if ((focusEvent.originalEvent.path[0].title==="Focus Map" || focusEvent.originalEvent.path[0].classList.contains("mapml-popup-content")) && isTab && shiftPressed){ + setTimeout(() => { //timeout needed so focus of the feature is done even after the keypressup event occurs + L.DomEvent.stop(focusEvent); + map.closePopup(popup); + path.focus(); + }, 0); } } @@ -1276,10 +1280,13 @@ export var MapMLLayer = L.Layer.extend({ } } + // if popup closes then the focusFeature handler can be removed + map.on("popupclose", removeHandlers); function removeHandlers(removeEvent){ if (removeEvent.popup === popup){ map.off("keydown", focusFeature); map.off("keydown", focusMap); + map.off('popupclose', removeHandlers); } } }, From 89df5fec062db6609236649d773704cfe04c0919 Mon Sep 17 00:00:00 2001 From: Ahmad Ayubi Date: Tue, 16 Feb 2021 14:58:39 -0500 Subject: [PATCH 6/6] Adds tests and new keyboard interaction --- src/mapml/layers/MapLayer.js | 19 ++++++-- test/e2e/core/keyboardInteraction.test.js | 56 +++++++++++++++-------- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/mapml/layers/MapLayer.js b/src/mapml/layers/MapLayer.js index 941722a7f..404738d8e 100644 --- a/src/mapml/layers/MapLayer.js +++ b/src/mapml/layers/MapLayer.js @@ -95,7 +95,7 @@ export var MapMLLayer = L.Layer.extend({ var c = document.createElement('div'); c.classList.add("mapml-popup-content"); c.insertAdjacentHTML('afterbegin', properties.innerHTML); - geometry.bindPopup(c, {autoPan:false, closeButton: false, minWidth: 108}); + geometry.bindPopup(c, {autoPan:false, minWidth: 108}); } } }); @@ -125,7 +125,7 @@ export var MapMLLayer = L.Layer.extend({ var c = document.createElement('div'); c.classList.add("mapml-popup-content"); c.insertAdjacentHTML('afterbegin', properties.innerHTML); - geometry.bindPopup(c, {autoPan:false, closeButton: false, minWidth: 108}); + geometry.bindPopup(c, {autoPan:false, minWidth: 108}); } } }).addTo(map); @@ -1258,7 +1258,7 @@ export var MapMLLayer = L.Layer.extend({ function focusFeature(focusEvent){ let isTab = focusEvent.originalEvent.keyCode === 9, shiftPressed = focusEvent.originalEvent.shiftKey; - if((focusEvent.originalEvent.path[0].title==="Focus Controls" && isTab && !shiftPressed) || focusEvent.originalEvent.keyCode === 27){ + if((focusEvent.originalEvent.path[0].classList.contains("leaflet-popup-close-button") && isTab && !shiftPressed) || focusEvent.originalEvent.keyCode === 27){ L.DomEvent.stop(focusEvent); map.closePopup(popup); path.focus(); @@ -1272,11 +1272,22 @@ export var MapMLLayer = L.Layer.extend({ } function focusMap(focusEvent){ + let isTab = focusEvent.originalEvent.keyCode === 9, + shiftPressed = focusEvent.originalEvent.shiftKey; + if((focusEvent.originalEvent.keyCode === 13 && focusEvent.originalEvent.path[0].classList.contains("leaflet-popup-close-button")) || focusEvent.originalEvent.keyCode === 27 ){ L.DomEvent.stopPropagation(focusEvent); map._container.focus(); - map.closePopup(); + map.closePopup(popup); if(focusEvent.originalEvent.keyCode !== 27)map._popupClosed = true; + } else if (isTab && focusEvent.originalEvent.path[0].classList.contains("leaflet-popup-close-button")){ + map.closePopup(popup); + } else if ((focusEvent.originalEvent.path[0].title==="Focus Map" || focusEvent.originalEvent.path[0].classList.contains("mapml-popup-content")) && isTab && shiftPressed){ + setTimeout(() => { //timeout needed so focus of the feature is done even after the keypressup event occurs + L.DomEvent.stop(focusEvent); + map.closePopup(popup); + map._container.focus(); + }, 0); } } diff --git a/test/e2e/core/keyboardInteraction.test.js b/test/e2e/core/keyboardInteraction.test.js index d24d742bb..e85b60e9e 100644 --- a/test/e2e/core/keyboardInteraction.test.js +++ b/test/e2e/core/keyboardInteraction.test.js @@ -130,38 +130,56 @@ jest.setTimeout(50000); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); const rh = await page.evaluateHandle(root => root.activeElement, nh); - const f = await (await page.evaluateHandle(elem => elem.title, rh)).jsonValue(); + const f = await (await page.evaluateHandle(elem => elem.className, rh)).jsonValue(); await page.keyboard.press("Tab"); const h2 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh2 = await page.evaluateHandle(doc => doc.shadowRoot, h2); const rh2 = await page.evaluateHandle(root => root.activeElement, nh2); - const f2 = await (await page.evaluateHandle(elem => elem.title, rh2)).jsonValue(); + const f2 = await (await page.evaluateHandle(elem => elem.tagName, rh2)).jsonValue(); - await page.keyboard.press("Shift+Tab"); - await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Tab"); const h3 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh3 = await page.evaluateHandle(doc => doc.shadowRoot, h3); const rh3 = await page.evaluateHandle(root => root.activeElement, nh3); const f3 = await (await page.evaluateHandle(elem => elem.title, rh3)).jsonValue(); - await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Tab"); const h4 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh4 = await page.evaluateHandle(doc => doc.shadowRoot, h4); const rh4 = await page.evaluateHandle(root => root.activeElement, nh4); const f4 = await (await page.evaluateHandle(elem => elem.title, rh4)).jsonValue(); - expect(f).toEqual("Next Feature"); - expect(f2).toEqual("Focus Controls"); - expect(f3).toEqual("Previous Feature"); - expect(f4).toEqual("Focus Map"); - }); - - test("[" + browserType + "]" + " Tab to next feature after tabbing out of popup", async () => { await page.keyboard.press("Tab"); + const h5 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); + const nh5 = await page.evaluateHandle(doc => doc.shadowRoot, h5); + const rh5 = await page.evaluateHandle(root => root.activeElement, nh5); + const f5 = await (await page.evaluateHandle(elem => elem.title, rh5)).jsonValue(); + await page.keyboard.press("Tab"); + const h6 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); + const nh6 = await page.evaluateHandle(doc => doc.shadowRoot, h6); + const rh6 = await page.evaluateHandle(root => root.activeElement, nh6); + const f6 = await (await page.evaluateHandle(elem => elem.title, rh6)).jsonValue(); + await page.keyboard.press("Tab"); + const h7 = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); + const nh7 = await page.evaluateHandle(doc => doc.shadowRoot, h7); + const rh7 = await page.evaluateHandle(root => root.activeElement, nh7); + const f7 = await (await page.evaluateHandle(elem => elem.className, rh7)).jsonValue(); + + expect(f).toEqual("mapml-popup-content"); + expect(f2.toUpperCase()).toEqual("A"); + expect(f3).toEqual("Focus Map"); + expect(f4).toEqual("Previous Feature"); + expect(f5).toEqual("Next Feature"); + expect(f6).toEqual("Focus Controls"); + expect(f7).toEqual("leaflet-popup-close-button"); + }); + + test("[" + browserType + "]" + " Tab to next feature after tabbing out of popup", async () => { await page.keyboard.press("Tab"); + const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); const rh = await page.evaluateHandle(root => root.activeElement, nh); @@ -170,23 +188,22 @@ jest.setTimeout(50000); expect(f).toEqual("M-53 451L153 508L113 146L-53 191z"); }); - test("[" + browserType + "]" + " Shift + Tab to previous feature while popup open", async () => { + test("[" + browserType + "]" + " Shift + Tab to current feature while popup open", async () => { await page.keyboard.press("Enter"); await page.keyboard.press("Shift+Tab"); - await page.keyboard.press("Shift+Tab"); - await page.keyboard.press("Shift+Tab"); + const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); const rh = await page.evaluateHandle(root => root.activeElement, nh); const f = await (await page.evaluateHandle(elem => elem.getAttribute("d"), rh)).jsonValue(); - expect(f).toEqual("M330 83L553 83L553 339L330 339z"); + expect(f).toEqual("M-53 451L153 508L113 146L-53 191z"); }); test("[" + browserType + "]" + " Previous feature button focuses previous feature", async () => { - await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); - await page.keyboard.press("Shift+Tab"); + await page.keyboard.press("Tab"); + await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h); @@ -199,6 +216,9 @@ jest.setTimeout(50000); test("[" + browserType + "]" + " Next feature button focuses next feature", async () => { await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); + await page.keyboard.press("Tab"); + await page.keyboard.press("Tab"); + await page.keyboard.press("Tab"); await page.keyboard.press("Enter"); const h = await page.evaluateHandle(() => document.querySelector("mapml-viewer")); const nh = await page.evaluateHandle(doc => doc.shadowRoot, h);