Skip to content

Commit 2a6296e

Browse files
authored
observe and deal with map-style mutations (#951)
1 parent a76c816 commit 2a6296e

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

src/map-style.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ export class MapStyle extends HTMLElement {
4040
target.setAttribute(attribute.nodeName, attribute.nodeValue);
4141
});
4242
}
43+
44+
// use observer to monitor the changes in mapStyle textContent
45+
this._observer = new MutationObserver(() => {
46+
this.styleElement.textContent = this.textContent;
47+
});
48+
this._observer.observe(this, {
49+
childList: true,
50+
subtree: true,
51+
characterData: true
52+
});
4353
}
4454
disconnectedCallback() {
4555
if (this._stylesheetHost) {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width,initial-scale=1">
6+
<title>map-style tests</title>
7+
<script type="module" src="mapml-viewer.js"></script>
8+
<style>
9+
html,
10+
body {
11+
height: 100%;
12+
}
13+
* {
14+
margin: 0;
15+
padding: 0;
16+
}
17+
18+
/* Specifying the `:defined` selector is recommended to style the map
19+
element, such that styles don't apply when fallback content is in use
20+
(e.g. when scripting is disabled or when custom/built-in elements isn't
21+
supported in the browser). */
22+
mapml-viewer:defined {
23+
/* Responsive map. */
24+
max-width: 100%;
25+
26+
/* Full viewport. */
27+
width: 100%;
28+
height: 100%;
29+
30+
/* Remove default (native-like) border. */
31+
border: none;
32+
33+
vertical-align: middle;
34+
}
35+
36+
/* Pre-style to avoid FOUC of inline layer- and fallback content. */
37+
mapml-viewer:not(:defined) > * {
38+
display: none;
39+
}
40+
41+
/* Pre-style to avoid Layout Shift. */
42+
mapml-viewer:not(:defined) {
43+
display: inline-block;
44+
contain: size;
45+
contain-intrinsic-size: 304px 154px;
46+
}
47+
48+
/* Ensure inline layer content is hidden if custom/built-in elements isn't
49+
supported, or if javascript is disabled. This needs to be defined separately
50+
from the above, because the `:not(:defined)` selector invalidates the entire
51+
declaration in browsers that do not support it. */
52+
layer- {
53+
display: none;
54+
}
55+
</style>
56+
<noscript>
57+
<style>
58+
/* Ensure fallback content (children of the map element) is displayed if
59+
custom/built-in elements is supported but javascript is disabled. */
60+
mapml-viewer:not(:defined) > :not(layer-) {
61+
display: initial;
62+
}
63+
64+
/* "Reset" the properties used to pre-style (to avoid Layout Shift) if
65+
custom/built-in elements is supported but javascript is disabled. */
66+
mapml-viewer:not(:defined) {
67+
display: initial;
68+
contain: initial;
69+
contain-intrinsic-size: initial;
70+
}
71+
</style>
72+
</noscript>
73+
</head>
74+
<body>
75+
76+
<mapml-viewer projection="OSMTILE" zoom="3" lat="45.406314" lon="-75.6883335" controls>
77+
<layer- label="Layer" checked="">
78+
<map-meta name="extent" content="top-left-longitude=-108.18295690328578, top-left-latitude=50.014258109371525, bottom-right-longitude=-80.36884559227745,bottom-right-latitude=56.408480743634385"></map-meta>
79+
<map-meta name="projection" content="OSMTILE"></map-meta>
80+
<map-meta name="cs" content="gcrs"></map-meta>
81+
<!----------------------- Element being tested ----------------------->
82+
<map-style>.poly {stroke: black; fill:black}</map-style>
83+
<!----------------------- Element being tested ----------------------->
84+
<map-feature class="poly"><map-featurecaption>Layer</map-featurecaption><map-geometry><map-polygon><map-coordinates>-100.50664854831412 56.0571475247103 -108.18295690328578 55.57677707477441 -106.44464507203479 51.99763924555603 -91.90173251505614 50.014258109371525 -80.36884559227745 50.0637759718567 -92.5284724652151 56.408480743634385 -100.50664854831412 56.0571475247103 </map-coordinates></map-polygon></map-geometry><map-properties>Styled Polygon</map-properties></map-feature>
85+
</layer->
86+
</mapml-viewer>
87+
</body>
88+
</html>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { test, expect, chromium } from '@playwright/test';
2+
3+
test.describe('map-style element tests', () => {
4+
let page;
5+
let context;
6+
test.beforeAll(async () => {
7+
context = await chromium.launchPersistentContext('');
8+
page =
9+
context.pages().find((page) => page.url() === 'about:blank') ||
10+
(await context.newPage());
11+
await page.goto('map-style.html');
12+
});
13+
14+
test.afterAll(async function () {
15+
await context.close();
16+
});
17+
18+
test(`mutation observer - style changes when map-style gets updated`, async () => {
19+
let mapStyle = await page.locator('map-style');
20+
let styleTextContentMatch = await mapStyle.evaluate((mapStyle) => {
21+
return mapStyle.styleElement.textContent === mapStyle.textContent;
22+
});
23+
24+
expect(styleTextContentMatch).toEqual(true);
25+
expect(mapStyle).toHaveText('.poly {stroke: black; fill:black}');
26+
27+
// Change the map-style element to red
28+
await mapStyle.evaluate((mapStyle) => {
29+
mapStyle.textContent = '.poly {stroke: red; fill:red}';
30+
});
31+
32+
// the style element and the map style should now be red
33+
mapStyle = await page.locator('map-style');
34+
styleTextContentMatch = await mapStyle.evaluate((mapStyle) => {
35+
return mapStyle.styleElement.textContent === mapStyle.textContent;
36+
});
37+
expect(styleTextContentMatch).toEqual(true);
38+
let styleTextContent = await mapStyle.evaluate((mapStyle) => {
39+
return mapStyle.styleElement.textContent;
40+
});
41+
expect(styleTextContent).toEqual('.poly {stroke: red; fill:red}');
42+
});
43+
});

test/server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ app.use(express.static(path.join(__dirname, 'e2e/elements/map')));
1212
app.use(express.static(path.join(__dirname, 'e2e/elements/map-feature')));
1313
app.use(express.static(path.join(__dirname, 'e2e/elements/map-input')));
1414
app.use(express.static(path.join(__dirname, 'e2e/elements/map-link')));
15+
app.use(express.static(path.join(__dirname, 'e2e/elements/map-style')));
1516
app.use(express.static(path.join(__dirname, 'e2e/elements/layer-')));
1617
app.use(express.static(path.join(__dirname, 'e2e/api')));
1718
app.use(express.static(path.join(__dirname, 'e2e/data')));

0 commit comments

Comments
 (0)