Skip to content

Commit

Permalink
Update mapml-viewer to be shadow host-compatible (#950)
Browse files Browse the repository at this point in the history
* Update mapml-viewer to be shadow host-compatible

* Update ci-testing.yml

Focus on getting flaky tests to pass
  • Loading branch information
prushforth authored Apr 1, 2024
1 parent 18ba67e commit 2379925
Show file tree
Hide file tree
Showing 26 changed files with 734 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- run: npx playwright install --with-deps
- run: npm install -g grunt-cli
- run: grunt default
- run: xvfb-run --auto-servernum -- npx playwright test --workers=1 --retries=3
- run: xvfb-run --auto-servernum -- npx playwright test tab menu --workers=1 --retries=3
# - run: xvfb-run --auto-servernum -- npm run jest
env:
CI: true
9 changes: 3 additions & 6 deletions src/map-extent.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,12 @@ export class MapExtent extends HTMLElement {
animate: false
});
}

getMapEl() {
return this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host.closest('mapml-viewer,map[is=web-map]')
: this.closest('mapml-viewer,map[is=web-map]');
return M.getClosest(this, 'mapml-viewer,map[is=web-map]');
}
getLayerEl() {
return this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host
: this.closest('layer-');
return M.getClosest(this, 'layer-');
}
attributeChangedCallback(name, oldValue, newValue) {
if (this.#hasConnected /* jshint ignore:line */) {
Expand Down
36 changes: 4 additions & 32 deletions src/map-feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,39 +128,11 @@ export class MapFeature extends HTMLElement {
return this._getFeatureExtent();
}
}
getLayerEl() {
let layerEl;
if (this.getRootNode() instanceof ShadowRoot) {
if (this.getRootNode().host.getRootNode() instanceof ShadowRoot) {
// layer- src
// > sd
// map-extent
// map-link
// > sd
// map-feature (1)
layerEl = this.getRootNode().host.getRootNode().host;
} else if (this.getRootNode().host.nodeName === 'MAP-LINK') {
// layer-
// map-extent
// map-link
// > sd
// map-feature (4)
layerEl = this.getRootNode().host.closest('layer-');
} else {
// layer- src
// > sd
// map-feature (2)
layerEl = this.getRootNode().host;
}
} else {
// layer-
// map-feature (3)
layerEl = this.closest('layer-');
}
return layerEl;
}
getMapEl() {
return this.getLayerEl().closest('mapml-viewer,map[is=web-map]');
return M.getClosest(this, 'mapml-viewer,map[is=web-map]');
}
getLayerEl() {
return M.getClosest(this, 'layer-');
}

attributeChangedCallback(name, oldValue, newValue) {
Expand Down
7 changes: 4 additions & 3 deletions src/map-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,11 @@ export class MapInput extends HTMLElement {
this.setAttribute('step', val);
}
}
getMapEl() {
return M.getClosest(this, 'mapml-viewer,map[is=web-map]');
}
getLayerEl() {
return this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host
: this.closest('layer-');
return M.getClosest(this, 'layer-');
}
attributeChangedCallback(name, oldValue, newValue) {
this.whenReady()
Expand Down
8 changes: 2 additions & 6 deletions src/map-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,10 @@ export class MapLink extends HTMLElement {
});
}
getMapEl() {
return this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host.closest('mapml-viewer,map[is=web-map]')
: this.closest('mapml-viewer,map[is=web-map]');
return M.getClosest(this, 'mapml-viewer,map[is=web-map]');
}
getLayerEl() {
return this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host
: this.closest('layer-');
return M.getClosest(this, 'layer-');
}

attributeChangedCallback(name, oldValue, newValue) {
Expand Down
8 changes: 6 additions & 2 deletions src/mapml-viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,11 @@ export class MapViewer extends HTMLElement {
false
);

this.parentElement.addEventListener('keyup', function (e) {
let host =
this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host
: this.parentElement;
host.addEventListener('keyup', function (e) {
if (
e.keyCode === 9 &&
document.activeElement.nodeName === 'MAPML-VIEWER'
Expand All @@ -661,7 +665,7 @@ export class MapViewer extends HTMLElement {
this._map.fire('keypress', { originalEvent: e });
}
});
this.parentElement.addEventListener('mousedown', function (e) {
host.addEventListener('mousedown', function (e) {
if (document.activeElement.nodeName === 'MAPML-VIEWER') {
document.activeElement.dispatchEvent(
new CustomEvent('mapfocused', { detail: { target: this } })
Expand Down
13 changes: 6 additions & 7 deletions src/mapml.css
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ button.mapml-contextmenu-item:disabled {
}

/*
* Fullscreen control.
* Fullscreen control. Image contains the on and off images, toggled via
* the background-position property
*/

.leaflet-control-fullscreen a {
Expand All @@ -238,7 +239,10 @@ button.mapml-contextmenu-item:disabled {
background-position: 3px 3px;
}

:host(.mapml-fullscreen-on) .leaflet-control-fullscreen a {
/*
* See: https://developer.mozilla.org/en-US/docs/Web/CSS/:host_function
and: https://developer.mozilla.org/en-US/docs/Web/CSS/:fullscreen */
:host(:fullscreen) .leaflet-control-fullscreen a {
background-position: 3px -35px;
}

Expand All @@ -247,11 +251,6 @@ button.mapml-contextmenu-item:disabled {
height: 100%!important;
}

:host(.mapml-fullscreen-on) {
width: 100%!important;
height: 100%!important;
}

:host(.leaflet-pseudo-fullscreen) {
position: fixed!important;
width: 100%!important;
Expand Down
46 changes: 21 additions & 25 deletions src/mapml/control/FullscreenButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@ L.Map.include({
toggleFullscreen: function (options) {
// the <map> element can't contain a shadow root, so we used a child <div>
// <mapml-viewer> can contain a shadow root, so return it directly
var mapEl = this.getContainer().getRootNode().host,
container = mapEl.nodeName === 'DIV' ? mapEl.parentElement : mapEl;
var mapEl = M.getClosest(this.getContainer(), 'mapml-viewer,[is=web-map]');
if (this.isFullscreen()) {
if (options && options.pseudoFullscreen) {
this._disablePseudoFullscreen(container);
this._disablePseudoFullscreen(mapEl);
} else if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
Expand All @@ -67,21 +66,21 @@ L.Map.include({
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else {
this._disablePseudoFullscreen(container);
this._disablePseudoFullscreen(mapEl);
}
} else {
if (options && options.pseudoFullscreen) {
this._enablePseudoFullscreen(container);
} else if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.mozRequestFullScreen) {
container.mozRequestFullScreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (container.msRequestFullscreen) {
container.msRequestFullscreen();
this._enablePseudoFullscreen(mapEl);
} else if (mapEl.requestFullscreen) {
mapEl.requestFullscreen();
} else if (mapEl.mozRequestFullScreen) {
mapEl.mozRequestFullScreen();
} else if (mapEl.webkitRequestFullscreen) {
mapEl.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (mapEl.msRequestFullscreen) {
mapEl.msRequestFullscreen();
} else {
this._enablePseudoFullscreen(container);
this._enablePseudoFullscreen(mapEl);
}
}
this.getContainer().focus();
Expand All @@ -101,7 +100,10 @@ L.Map.include({

_setFullscreen: function (fullscreen) {
this._isFullscreen = fullscreen;
var container = this.getContainer().getRootNode().host;
var container = M.getClosest(
this.getContainer(),
'mapml-viewer,[is=web-map]'
);
if (fullscreen) {
L.DomUtil.addClass(container, 'mapml-fullscreen-on');
} else {
Expand All @@ -111,18 +113,12 @@ L.Map.include({
},

_onFullscreenChange: function (e) {
var fullscreenElement =
document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement,
mapEl = this.getContainer().getRootNode().host,
container = mapEl.nodeName === 'DIV' ? mapEl.parentElement : mapEl;

if (fullscreenElement === container && !this._isFullscreen) {
var fullscreenElement = M.getClosest(this.getContainer(), ':fullscreen'),
mapEl = M.getClosest(this.getContainer(), 'mapml-viewer,[is=web-map]');
if (fullscreenElement === mapEl && !this._isFullscreen) {
this._setFullscreen(true);
this.fire('fullscreenchange');
} else if (fullscreenElement !== container && this._isFullscreen) {
} else if (fullscreenElement !== mapEl && this._isFullscreen) {
this._setFullscreen(false);
this.fire('fullscreenchange');
}
Expand Down
1 change: 1 addition & 0 deletions src/mapml/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ import { DOMTokenList } from './utils/DOMTokenList';
M.getZoomBoundsFromMeta = Util.getZoomBoundsFromMeta;
M.getZoomBounds = Util.getZoomBounds;
M.getNativeVariables = Util.getNativeVariables;
M.getClosest = Util.getClosest;

M.QueryHandler = QueryHandler;
M.ContextMenu = ContextMenu;
Expand Down
18 changes: 18 additions & 0 deletions src/mapml/utils/Util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1519,5 +1519,23 @@ export var Util = {
)
newZoom--;
return newZoom;
},
getClosest(node, selector) {
if (!node) {
return null;
}
if (node instanceof ShadowRoot) {
return M.getClosest(node.host, selector);
}

if (node instanceof HTMLElement) {
if (node.matches(selector)) {
return node;
} else {
return M.getClosest(node.parentNode, selector);
}
}

return M.getClosest(node.parentNode, selector);
}
};
22 changes: 16 additions & 6 deletions src/web-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export class WebMap extends HTMLMapElement {

// Set default styles for the map element.
let mapDefaultCSS = document.createElement('style');
mapDefaultCSS.id = 'web-map-default-style';
mapDefaultCSS.innerHTML =
`[is="web-map"] {` +
`all: initial;` + // Reset properties inheritable from html/body, as some inherited styles may cause unexpected issues with the map element's components (https://github.com/Maps4HTML/Web-Map-Custom-Element/issues/140).
Expand Down Expand Up @@ -281,7 +282,13 @@ export class WebMap extends HTMLMapElement {
shadowRoot.appendChild(tmpl.content.cloneNode(true));
shadowRoot.appendChild(this._container);
this.appendChild(rootDiv);
document.head.insertAdjacentElement('afterbegin', mapDefaultCSS);
if (this.getRootNode() instanceof ShadowRoot) {
if (!this.getRootNode().getElementById(mapDefaultCSS.id))
this.getRootNode().prepend(mapDefaultCSS);
} else {
if (!document.getElementById(mapDefaultCSS.id))
document.head.insertAdjacentElement('afterbegin', mapDefaultCSS);
}
}
_createMap() {
if (!this._map) {
Expand Down Expand Up @@ -684,14 +691,17 @@ export class WebMap extends HTMLMapElement {
false
);

let mapEl = this;
this.parentElement.addEventListener('keyup', function (e) {
let host =
this.getRootNode() instanceof ShadowRoot
? this.getRootNode().host
: this.parentElement;
host.addEventListener('keyup', function (e) {
if (
e.keyCode === 9 &&
document.activeElement.className === 'mapml-web-map'
) {
// document.activeElement is div.mapml-web-map, not <map>
mapEl.dispatchEvent(
document.activeElement.dispatchEvent(
new CustomEvent('mapfocused', { detail: { target: this } })
);
}
Expand All @@ -711,9 +721,9 @@ export class WebMap extends HTMLMapElement {
this._map.fire('keypress', { originalEvent: e });
}
});
this.parentElement.addEventListener('mousedown', function (e) {
host.addEventListener('mousedown', function (e) {
if (document.activeElement.className === 'mapml-web-map') {
mapEl.dispatchEvent(
document.activeElement.dispatchEvent(
new CustomEvent('mapfocused', { detail: { target: this } })
);
}
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/data/restaurants/african.mapml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<map-meta name="extent" content="top-left-easting=1509080.1964270622,top-left-northing=-169400.558801122,bottom-right-easting=1512094.3357886747,bottom-right-northing=-172702.5654051304" ></map-meta>
</map-head>
<map-body>
<map-feature id="restaurant_map-point.9" class="restaurant_map-point">
<map-feature data-testid="hareg" id="restaurant_map-point.9" class="restaurant_map-point">
<map-featurecaption>Hareg Cafe &amp; Variety</map-featurecaption>
<map-geometry>
<map-point>
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/data/tiles/cbmt/cbmt.mapml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
<map-body>
<map-extent units="CBMTILE" checked="checked" hidden="hidden">
<map-input name="z" type="zoom" value="17" min="0" max="17" ></map-input>
<map-input name="y" type="location" units="tilematrix" axis="row" min="29750" max="34475" ></map-input>
<map-input data-testid="test-input" name="y" type="location" units="tilematrix" axis="row" min="29750" max="34475" ></map-input>
<map-input name="x" type="location" units="tilematrix" axis="column" min="26484" max="32463" ></map-input>
<map-link rel="tile" tref="cbmt/{z}/c{x}_r{y}.png" ></map-link>
<map-link data-testid="test-link" rel="tile" tref="cbmt/{z}/c{x}_r{y}.png" ></map-link>
</map-extent>
</map-body>
</mapml->
44 changes: 44 additions & 0 deletions test/e2e/elements/map-extent/map-extent-in-shadow-root.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>mapml-viewer in shadow root test</title>
<meta charset="UTF-8">
<script type="module" src="mapml-viewer.js"></script>
<style>
html {
height: 100%
}

body {
height: inherit
}

* {
margin: 0;
padding: 0;
}
/* styles in here don't affect shadow dom contents */
mapml-viewer:defined {
/* Responsive map. */
max-width: 100%;

/* Full viewport. */
width: 100%;
height: 100%;

/* Remove default (native-like) border. */
border: none;

vertical-align: middle;
} </style>
</head>
<body>
<host-element>
<template shadowrootmode="open">
<mapml-viewer data-testid="viewer" style="height: 500px;width:500px;" zoom="2" lat="63" lon="-87" controls projection="CBMTILE">
<layer- data-testid="test-layer" label="Remote content" src="data/cbmt.mapml" checked></layer->
</mapml-viewer>
</template>
</host-element>
</body>
</html>
Loading

0 comments on commit 2379925

Please sign in to comment.