Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit df49def

Browse files
Peter Rushforthprushforth
authored andcommitted
Add map-tile element
layer.js - no longer tests to see if the bounds have been previously calculated, updates the _layer.bounds field whenever extent getter executes - MapMLLayer usage refactored to use MapLayer per the element name association - _validateDisabled method updated to account for replacement of StaticTileLayer by MapTileLayer - replaced reliance of _validateDisabled on presence of properties such as MapLayer['_staticTileLayer'] by using the array ['_staticTileLayer','_mapmlvectors','_extentLayer'] only as a driver of the loop used to validate that each child layer of the LayerGroup's extent is enabled or not. the _mapmlvectors step is not completely worked out, will get done in subsequent work tbc... map-extent.js - applied name refactoring required by renaming ExtentLayer.js to MapExtentLayer.js map-feature.js - changed addFeature a bit. changes look ok tbd, but the whole dependence of map-feature.js on MapFeatureLayer.createGeometry as a factory method for creating the geometry as a Leaflet layer should be revisited and hopefully simplified. Why not just construct a geometry via new Geometry? - for the use case of a <map-feature> loaded via a <map-link>, created a group of new methods, patterned after/ copied from <map-tile>: - _createOrGetFeatureLayer - runs conditional on the feature being loaded as part of <map-link> processing. Called during connectedCallback - isFirst - determines if this element is the first such element in a sequence of elements named the same i.e. map-feature. If it is, used by _createOrGetFeatureLayer to construct a FeatureLayeer constructed as a holder for features that are constructed and removed with each map movement. - getPrevious - returns the previous sibling element of the <map-feature> with no checks as to what kind of element it is. The notion is that it's only called when isFirst returns false, so the returned sibling element is guaranteed to be a map-feature (well, isFirst tests the name such that it must be equal to the name of this node, which in this case is map-feature). map-link.js - imports and constructs the newly refactored TemplatedFeaturesOrTilesLayer instead of only TemplatedFeaturesLayer map-select.js - changed a comment that mentioned MapMLLayer map-tile.js - new. mapml-viewer.js - imports and defines the map-tile element and HTMLTileElement interface LayerControl.js - udpated a comment that referred to MapMLLayer AnnounceMovement.js updated a comment that referred to MapMLLayer index.js - imports and defines the map-tile element and HTMLTileElement interface from mapml-viewer.js ExtentLayer.js - renamed to MapExtentLayer.js FeatureLayer.js - updated a comment that referred to MapMLLayer MapFeatureLayer.js - new. not used yet MapLayer.js - refactoring of MapMLLayer.js: - adds getContainer public method - in onAdd, removes addition of static tile layer to LayerGroup - removes the use of MapMLLayer['_staticTileLayer'], replaces with using the string '_staticTileLayer' as a key to determine action to be taken in the bounds calculation loop - removes the processTiles construction method MapTileLayer.js - new. Replaces StaticTileLayer. TemplatedFeaturesOrTilesLayer.js - new. replaces TemplatedFeaturesLayer, since we now support <map-tile> in template processing response documents. TemplatedTileLayer.js - updated to support vector tiles that contain <map-tile> elements. map-bounding-box.test.js - add waitForTimeout to overcome flakiness. drag.test.js - replace detection of class that was renamed / removed when StaticTileLayer was eliminated missingMetaParameters.html - add comment to clarify intent to future me map-link-media.html - remove use of external resource, replace with content from test data featureLayer.test.js - udpate comment mentioning MapMLLayer to MapLayer multipleExtents.test.js, multipleExtents.html - update to support new classes used by features or tiles support in templated link. Modernize the test a bit to make it more readable. Still an ugly large test. staticTileLayer.test.js - update templatedPMTilesCBMTILETest.html - added map-link for stylesheet module. Not sure why this test was working previously, maybe I misunderstood, but I think it was a cut and paste error. templatedPMTilesMVTLayer.test.js - changed expectation that layer will not be disabled to expect that layer WILL be disabled, because the particular layer didn't have a stylesheet and so could never be enabled, despite multiple projections available customTCRS.test.js - one test was using static tiles, updated to continue working playwright.config.js - added global directive to ignore https errors. These were causing intermittent problems with tests on work network. See if we can get ci testing to pass...
1 parent aee7323 commit df49def

35 files changed

+1864
-1194
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
/test-results/
1212
.idea/
1313
*.iml
14-
test.html
14+
test.html

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

playwright.config.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default defineConfig({
1111
use: {
1212
headless: true,
1313
browserName: 'chromium',
14-
baseURL: 'http://localhost:30001/'
14+
baseURL: 'http://localhost:30001/',
15+
ignoreHTTPSErrors: true
1516
}
16-
});
17+
});

src/layer.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { setOptions, DomUtil, bounds, point } from 'leaflet';
22

33
import { Util } from './mapml/utils/Util.js';
4-
import { MapMLLayer, mapMLLayer } from './mapml/layers/MapMLLayer.js';
4+
import { MapLayer, mapLayer } from './mapml/layers/MapLayer.js';
5+
import { MapTileLayer } from './mapml/layers/MapTileLayer.js';
56
import { createLayerControlHTML } from './mapml/elementSupport/layers/createLayerControlForLayer.js';
67

78
export class BaseLayerElement extends HTMLElement {
@@ -72,7 +73,7 @@ export class BaseLayerElement extends HTMLElement {
7273

7374
get extent() {
7475
// calculate the bounds of all content, return it.
75-
if (this._layer && !this._layer.bounds) {
76+
if (this._layer) {
7677
this._layer._calculateBounds();
7778
}
7879
return this._layer
@@ -296,7 +297,7 @@ export class BaseLayerElement extends HTMLElement {
296297
this.selectAlternateOrChangeProjection();
297298
})
298299
.then(() => {
299-
this._layer = mapMLLayer(new URL(this.src, base).href, this, {
300+
this._layer = mapLayer(new URL(this.src, base).href, this, {
300301
projection: this.getProjection(),
301302
opacity: this.opacity
302303
});
@@ -333,7 +334,7 @@ export class BaseLayerElement extends HTMLElement {
333334
this.selectAlternateOrChangeProjection();
334335
})
335336
.then(() => {
336-
this._layer = mapMLLayer(null, this, {
337+
this._layer = mapLayer(null, this, {
337338
projection: this.getProjection(),
338339
opacity: this.opacity
339340
});
@@ -467,7 +468,7 @@ export class BaseLayerElement extends HTMLElement {
467468
* Runs the effects of the mutation observer, which is to add map-features' and
468469
* map-extents' leaflet layer implementations to the appropriate container in
469470
* the map-layer._layer: either as a sub-layer directly in the LayerGroup
470-
* (MapMLLayer._layer) or as a sub-layer in the MapMLLayer._mapmlvectors
471+
* (MapLayer._layer) or as a sub-layer in the MapLayer._mapmlvectors
471472
* FeatureGroup
472473
*/
473474
_runMutationObserver(elementsGroup) {
@@ -633,6 +634,19 @@ export class BaseLayerElement extends HTMLElement {
633634
}
634635

635636
_validateDisabled() {
637+
const countTileLayers = () => {
638+
let totalCount = 0;
639+
let disabledCount = 0;
640+
641+
this._layer.eachLayer((layer) => {
642+
if (layer instanceof MapTileLayer) {
643+
totalCount++;
644+
if (!layer.isVisible()) disabledCount++;
645+
}
646+
});
647+
648+
return { totalCount, disabledCount };
649+
};
636650
// setTimeout is necessary to make the validateDisabled happen later than the moveend operations etc.,
637651
// to ensure that the validated result is correct
638652
setTimeout(() => {
@@ -671,10 +685,15 @@ export class BaseLayerElement extends HTMLElement {
671685
if (mapExtents[i]._validateDisabled())
672686
disabledExtentCount++;
673687
}
674-
} else if (layer[type]) {
675-
// not a templated layer
688+
} else if (type === '_mapmlvectors') {
689+
// inline / static features
676690
totalExtentCount++;
677691
if (!layer[type].isVisible()) disabledExtentCount++;
692+
} else {
693+
// inline tiles
694+
const tileLayerCounts = countTileLayers();
695+
totalExtentCount += tileLayerCounts.totalCount;
696+
disabledExtentCount += tileLayerCounts.disabledCount;
678697
}
679698
}
680699
}

src/map-extent.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { bounds as Lbounds, point as Lpoint } from 'leaflet';
22

33
import { Util } from './mapml/utils/Util.js';
4-
import { extentLayer } from './mapml/layers/ExtentLayer.js';
4+
import { mapExtentLayer } from './mapml/layers/MapExtentLayer.js';
55
import { createLayerControlExtentHTML } from './mapml/elementSupport/extents/createLayerControlForExtent.js';
66

77
/* global M */
@@ -251,7 +251,7 @@ export class HTMLExtentElement extends HTMLElement {
251251
// when projection is changed, the parent map-layer._layer is created (so whenReady is fulfilled) but then removed,
252252
// then the map-extent disconnectedCallback will be triggered by map-layer._onRemove() (clear the shadowRoot)
253253
// even before connectedCallback is finished
254-
// in this case, the microtasks triggered by the fulfillment of the removed MapMLLayer should be stopped as well
254+
// in this case, the microtasks triggered by the fulfillment of the removed MapLayer should be stopped as well
255255
// !this.isConnected <=> the disconnectedCallback has run before
256256
if (!this.isConnected) return;
257257
/* jshint ignore:start */
@@ -263,7 +263,7 @@ export class HTMLExtentElement extends HTMLElement {
263263
// this._opacity is used to record the current opacity value (with or without updates),
264264
// the initial value of this._opacity should be set as opacity attribute value, if exists, or the default value 1.0
265265
this._opacity = this.opacity || 1.0;
266-
this._extentLayer = extentLayer({
266+
this._extentLayer = mapExtentLayer({
267267
opacity: this.opacity,
268268
crs: M[this.units],
269269
extentZIndex: Array.from(
@@ -432,7 +432,7 @@ export class HTMLExtentElement extends HTMLElement {
432432
_handleChange() {
433433
// add _extentLayer to map if map-extent is checked, otherwise remove it
434434
if (this.checked && !this.disabled && this.parentLayer._layer) {
435-
// can be added to mapmllayer layerGroup no matter map-layer is checked or not
435+
// can be added to MapLayer LayerGroup no matter map-layer is checked or not
436436
this._extentLayer.addTo(this.parentLayer._layer);
437437
this._extentLayer.setZIndex(
438438
Array.from(

src/map-feature.js

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { bounds, point } from 'leaflet';
1+
import { bounds, point, extend } from 'leaflet';
22

3+
import { featureLayer } from './mapml/layers/FeatureLayer.js';
4+
import { featureRenderer } from './mapml/features/featureRenderer.js';
35
import { Util } from './mapml/utils/Util.js';
46
import proj4 from 'proj4';
57

@@ -180,6 +182,9 @@ export class HTMLFeatureElement extends HTMLElement {
180182
this._parentEl.parentElement?.hasAttribute('data-moving')
181183
)
182184
return;
185+
if (this._parentEl.nodeName === 'MAP-LINK') {
186+
this._createOrGetFeatureLayer();
187+
}
183188
// use observer to monitor the changes in mapFeature's subtree
184189
// (i.e. map-properties, map-featurecaption, map-coordinates)
185190
this._observer = new MutationObserver((mutationList) => {
@@ -256,17 +261,97 @@ export class HTMLFeatureElement extends HTMLElement {
256261

257262
addFeature(layerToAddTo) {
258263
this._featureLayer = layerToAddTo;
259-
let parentLayer = this.getLayerEl();
260264
// "synchronize" the event handlers between map-feature and <g>
261265
if (!this.querySelector('map-geometry')) return;
262266
let fallbackCS = this._getFallbackCS();
263-
let content = parentLayer.src ? parentLayer.shadowRoot : parentLayer;
264267
this._geometry = layerToAddTo.createGeometry(this, fallbackCS); // side effect: extends `this` with this._groupEl if successful, points to svg g element that renders to map SD
265268
if (!this._geometry) return;
269+
this._geometry._layerEl = this.getLayerEl();
266270
layerToAddTo.addLayer(this._geometry);
267271
this._setUpEvents();
268272
}
273+
isFirst() {
274+
// Get the previous element sibling
275+
const prevSibling = this.previousElementSibling;
276+
277+
// If there's no previous sibling, return true
278+
if (!prevSibling) {
279+
return true;
280+
}
281+
282+
// Compare the node names (tag names) - return true if they're different
283+
return this.nodeName !== prevSibling.nodeName;
284+
}
285+
getPrevious() {
286+
// Check if this is the first element of a sequence
287+
if (this.isFirst()) {
288+
return null; // No previous element available
289+
}
290+
291+
// Since we know it's not the first, we can safely return the previous element sibling
292+
return this.previousElementSibling;
293+
}
294+
_createOrGetFeatureLayer() {
295+
if (this.isFirst() && this._parentEl._templatedLayer) {
296+
const parentElement = this._parentEl;
269297

298+
let map = parentElement.getMapEl()._map;
299+
300+
// Create a new FeatureLayer
301+
this._featureLayer = featureLayer(null, {
302+
// pass the vector layer a renderer of its own, otherwise leaflet
303+
// puts everything into the overlayPane
304+
renderer: featureRenderer(),
305+
// pass the vector layer the container for the parent into which
306+
// it will append its own container for rendering into
307+
pane: parentElement._templatedLayer.getContainer(),
308+
// the bounds will be static, fixed, constant for the lifetime of the layer
309+
layerBounds: parentElement.getBounds(),
310+
zoomBounds: this._getZoomBounds(),
311+
projection: map.options.projection,
312+
mapEl: parentElement.getMapEl(),
313+
onEachFeature: function (properties, geometry) {
314+
if (properties) {
315+
const popupOptions = {
316+
autoClose: false,
317+
autoPan: true,
318+
maxHeight: map.getSize().y * 0.5 - 50,
319+
maxWidth: map.getSize().x * 0.7,
320+
minWidth: 165
321+
};
322+
var c = document.createElement('div');
323+
c.classList.add('mapml-popup-content');
324+
c.insertAdjacentHTML('afterbegin', properties.innerHTML);
325+
geometry.bindPopup(c, popupOptions);
326+
}
327+
}
328+
});
329+
// this is used by DebugOverlay testing "multipleExtents.test.js
330+
// but do we really need or want each feature to have the bounds of the
331+
// map link? tbd
332+
extend(this._featureLayer.options, {
333+
_leafletLayer: Object.assign(this._featureLayer, {
334+
_layerEl: this.getLayerEl()
335+
})
336+
});
337+
338+
this.addFeature(this._featureLayer);
339+
340+
// add featureLayer to TemplatedFeaturesOrTilesLayer of the parentElement
341+
if (
342+
parentElement._templatedLayer &&
343+
parentElement._templatedLayer.addLayer
344+
) {
345+
parentElement._templatedLayer.addLayer(this._featureLayer);
346+
}
347+
} else {
348+
// get the previous feature's layer
349+
this._featureLayer = this.getPrevious()?._featureLayer;
350+
if (this._featureLayer) {
351+
this.addFeature(this._featureLayer);
352+
}
353+
}
354+
}
270355
_setUpEvents() {
271356
['click', 'focus', 'blur', 'keyup', 'keydown'].forEach((name) => {
272357
// when <g> is clicked / focused / blurred

src/map-link.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import { Util } from './mapml/utils/Util.js';
1111
import { templatedImageLayer } from './mapml/layers/TemplatedImageLayer.js';
1212
import { templatedTileLayer } from './mapml/layers/TemplatedTileLayer.js';
13-
import { templatedFeaturesLayer } from './mapml/layers/TemplatedFeaturesLayer.js';
13+
import { templatedFeaturesOrTilesLayer } from './mapml/layers/TemplatedFeaturesOrTilesLayer.js';
1414
import { templatedPMTilesLayer } from './mapml/layers/TemplatedPMTilesLayer.js';
1515
/* global M */
1616

@@ -436,7 +436,8 @@ export class HTMLLinkElement extends HTMLElement {
436436
// be loaded as part of a templated layer processing i.e. on moveend
437437
// and the generated <link> that implements this <map-link> should be located
438438
// in the parent <map-link>._templatedLayer.container root node if
439-
// the _templatedLayer is an instance of TemplatedTileLayer or TemplatedFeaturesLayer
439+
// the _templatedLayer is an instance of TemplatedTileLayer or
440+
// TemplatedFeaturesOrTilesLayer
440441
//
441442
// if the parent node (or the host of the shadow root parent node) is map-layer, the link should be created in the _layer
442443
// container
@@ -551,12 +552,15 @@ export class HTMLLinkElement extends HTMLElement {
551552
if (!this.shadowRoot) {
552553
this.attachShadow({ mode: 'open' });
553554
}
554-
this._templatedLayer = templatedFeaturesLayer(this._templateVars, {
555+
// Use the FeaturesTilesLayerGroup to handle both map-feature and map-tile elements
556+
this._templatedLayer = templatedFeaturesOrTilesLayer(this._templateVars, {
555557
zoomBounds: this.getZoomBounds(),
556558
extentBounds: this.getBounds(),
557559
zIndex: this.zIndex,
558560
pane: this.parentExtent._extentLayer.getContainer(),
559-
linkEl: this
561+
linkEl: this,
562+
projection: this.mapEl._map.options.projection,
563+
renderer: this.mapEl._map.options.renderer
560564
}).addTo(this.parentExtent._extentLayer);
561565
} else if (this.rel === 'query') {
562566
if (!this.shadowRoot) {

src/map-select.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class HTMLSelectElement extends HTMLElement {
3939
this._extentEl = this.parentElement;
4040
// TODO make the layer redraw after map-select change event
4141
// origin of this block was in _initTemplateVars from map-extent, which was
42-
// originally part of MapMLLayer...
42+
// originally part of MapLayer...
4343
//
4444
// use a throwaway div to parse the input from MapML into HTML
4545
this._createLayerControlForSelect();

0 commit comments

Comments
 (0)