Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update mapml-viewer to be shadow host-compatible #950

Merged
merged 3 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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