Skip to content
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
/test-results/
.idea/
*.iml
test.html
test.html
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default defineConfig({
use: {
headless: true,
browserName: 'chromium',
baseURL: 'http://localhost:30001/'
baseURL: 'http://localhost:30001/',
ignoreHTTPSErrors: true
}
});
});
33 changes: 26 additions & 7 deletions src/layer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { setOptions, DomUtil, bounds, point } from 'leaflet';

import { Util } from './mapml/utils/Util.js';
import { MapMLLayer, mapMLLayer } from './mapml/layers/MapMLLayer.js';
import { MapLayer, mapLayer } from './mapml/layers/MapLayer.js';
import { MapTileLayer } from './mapml/layers/MapTileLayer.js';
import { createLayerControlHTML } from './mapml/elementSupport/layers/createLayerControlForLayer.js';

export class BaseLayerElement extends HTMLElement {
Expand Down Expand Up @@ -72,7 +73,7 @@ export class BaseLayerElement extends HTMLElement {

get extent() {
// calculate the bounds of all content, return it.
if (this._layer && !this._layer.bounds) {
if (this._layer) {
this._layer._calculateBounds();
}
return this._layer
Expand Down Expand Up @@ -296,7 +297,7 @@ export class BaseLayerElement extends HTMLElement {
this.selectAlternateOrChangeProjection();
})
.then(() => {
this._layer = mapMLLayer(new URL(this.src, base).href, this, {
this._layer = mapLayer(new URL(this.src, base).href, this, {
projection: this.getProjection(),
opacity: this.opacity
});
Expand Down Expand Up @@ -333,7 +334,7 @@ export class BaseLayerElement extends HTMLElement {
this.selectAlternateOrChangeProjection();
})
.then(() => {
this._layer = mapMLLayer(null, this, {
this._layer = mapLayer(null, this, {
projection: this.getProjection(),
opacity: this.opacity
});
Expand Down Expand Up @@ -467,7 +468,7 @@ export class BaseLayerElement extends HTMLElement {
* Runs the effects of the mutation observer, which is to add map-features' and
* map-extents' leaflet layer implementations to the appropriate container in
* the map-layer._layer: either as a sub-layer directly in the LayerGroup
* (MapMLLayer._layer) or as a sub-layer in the MapMLLayer._mapmlvectors
* (MapLayer._layer) or as a sub-layer in the MapLayer._mapmlvectors
* FeatureGroup
*/
_runMutationObserver(elementsGroup) {
Expand Down Expand Up @@ -633,6 +634,19 @@ export class BaseLayerElement extends HTMLElement {
}

_validateDisabled() {
const countTileLayers = () => {
let totalCount = 0;
let disabledCount = 0;

this._layer.eachLayer((layer) => {
if (layer instanceof MapTileLayer) {
totalCount++;
if (!layer.isVisible()) disabledCount++;
}
});

return { totalCount, disabledCount };
};
// setTimeout is necessary to make the validateDisabled happen later than the moveend operations etc.,
// to ensure that the validated result is correct
setTimeout(() => {
Expand Down Expand Up @@ -671,10 +685,15 @@ export class BaseLayerElement extends HTMLElement {
if (mapExtents[i]._validateDisabled())
disabledExtentCount++;
}
} else if (layer[type]) {
// not a templated layer
} else if (type === '_mapmlvectors') {
// inline / static features
totalExtentCount++;
if (!layer[type].isVisible()) disabledExtentCount++;
} else {
// inline tiles
const tileLayerCounts = countTileLayers();
totalExtentCount += tileLayerCounts.totalCount;
disabledExtentCount += tileLayerCounts.disabledCount;
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/map-extent.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { bounds as Lbounds, point as Lpoint } from 'leaflet';

import { Util } from './mapml/utils/Util.js';
import { extentLayer } from './mapml/layers/ExtentLayer.js';
import { mapExtentLayer } from './mapml/layers/MapExtentLayer.js';
import { createLayerControlExtentHTML } from './mapml/elementSupport/extents/createLayerControlForExtent.js';

/* global M */
Expand Down Expand Up @@ -251,7 +251,7 @@ export class HTMLExtentElement extends HTMLElement {
// when projection is changed, the parent map-layer._layer is created (so whenReady is fulfilled) but then removed,
// then the map-extent disconnectedCallback will be triggered by map-layer._onRemove() (clear the shadowRoot)
// even before connectedCallback is finished
// in this case, the microtasks triggered by the fulfillment of the removed MapMLLayer should be stopped as well
// in this case, the microtasks triggered by the fulfillment of the removed MapLayer should be stopped as well
// !this.isConnected <=> the disconnectedCallback has run before
if (!this.isConnected) return;
/* jshint ignore:start */
Expand All @@ -263,7 +263,7 @@ export class HTMLExtentElement extends HTMLElement {
// this._opacity is used to record the current opacity value (with or without updates),
// the initial value of this._opacity should be set as opacity attribute value, if exists, or the default value 1.0
this._opacity = this.opacity || 1.0;
this._extentLayer = extentLayer({
this._extentLayer = mapExtentLayer({
opacity: this.opacity,
crs: M[this.units],
extentZIndex: Array.from(
Expand Down Expand Up @@ -432,7 +432,7 @@ export class HTMLExtentElement extends HTMLElement {
_handleChange() {
// add _extentLayer to map if map-extent is checked, otherwise remove it
if (this.checked && !this.disabled && this.parentLayer._layer) {
// can be added to mapmllayer layerGroup no matter map-layer is checked or not
// can be added to MapLayer LayerGroup no matter map-layer is checked or not
this._extentLayer.addTo(this.parentLayer._layer);
this._extentLayer.setZIndex(
Array.from(
Expand Down
91 changes: 88 additions & 3 deletions src/map-feature.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { bounds, point } from 'leaflet';
import { bounds, point, extend } from 'leaflet';

import { featureLayer } from './mapml/layers/FeatureLayer.js';
import { featureRenderer } from './mapml/features/featureRenderer.js';
import { Util } from './mapml/utils/Util.js';
import proj4 from 'proj4';

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

addFeature(layerToAddTo) {
this._featureLayer = layerToAddTo;
let parentLayer = this.getLayerEl();
// "synchronize" the event handlers between map-feature and <g>
if (!this.querySelector('map-geometry')) return;
let fallbackCS = this._getFallbackCS();
let content = parentLayer.src ? parentLayer.shadowRoot : parentLayer;
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
if (!this._geometry) return;
this._geometry._layerEl = this.getLayerEl();
layerToAddTo.addLayer(this._geometry);
this._setUpEvents();
}
isFirst() {
// Get the previous element sibling
const prevSibling = this.previousElementSibling;

// If there's no previous sibling, return true
if (!prevSibling) {
return true;
}

// Compare the node names (tag names) - return true if they're different
return this.nodeName !== prevSibling.nodeName;
}
getPrevious() {
// Check if this is the first element of a sequence
if (this.isFirst()) {
return null; // No previous element available
}

// Since we know it's not the first, we can safely return the previous element sibling
return this.previousElementSibling;
}
_createOrGetFeatureLayer() {
if (this.isFirst() && this._parentEl._templatedLayer) {
const parentElement = this._parentEl;

let map = parentElement.getMapEl()._map;

// Create a new FeatureLayer
this._featureLayer = featureLayer(null, {
// pass the vector layer a renderer of its own, otherwise leaflet
// puts everything into the overlayPane
renderer: featureRenderer(),
// pass the vector layer the container for the parent into which
// it will append its own container for rendering into
pane: parentElement._templatedLayer.getContainer(),
// the bounds will be static, fixed, constant for the lifetime of the layer
layerBounds: parentElement.getBounds(),
zoomBounds: this._getZoomBounds(),
projection: map.options.projection,
mapEl: parentElement.getMapEl(),
onEachFeature: function (properties, geometry) {
if (properties) {
const popupOptions = {
autoClose: false,
autoPan: true,
maxHeight: map.getSize().y * 0.5 - 50,
maxWidth: map.getSize().x * 0.7,
minWidth: 165
};
var c = document.createElement('div');
c.classList.add('mapml-popup-content');
c.insertAdjacentHTML('afterbegin', properties.innerHTML);
geometry.bindPopup(c, popupOptions);
}
}
});
// this is used by DebugOverlay testing "multipleExtents.test.js
// but do we really need or want each feature to have the bounds of the
// map link? tbd
extend(this._featureLayer.options, {
_leafletLayer: Object.assign(this._featureLayer, {
_layerEl: this.getLayerEl()
})
});

this.addFeature(this._featureLayer);

// add featureLayer to TemplatedFeaturesOrTilesLayer of the parentElement
if (
parentElement._templatedLayer &&
parentElement._templatedLayer.addLayer
) {
parentElement._templatedLayer.addLayer(this._featureLayer);
}
} else {
// get the previous feature's layer
this._featureLayer = this.getPrevious()?._featureLayer;
if (this._featureLayer) {
this.addFeature(this._featureLayer);
}
}
}
_setUpEvents() {
['click', 'focus', 'blur', 'keyup', 'keydown'].forEach((name) => {
// when <g> is clicked / focused / blurred
Expand Down
12 changes: 8 additions & 4 deletions src/map-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { Util } from './mapml/utils/Util.js';
import { templatedImageLayer } from './mapml/layers/TemplatedImageLayer.js';
import { templatedTileLayer } from './mapml/layers/TemplatedTileLayer.js';
import { templatedFeaturesLayer } from './mapml/layers/TemplatedFeaturesLayer.js';
import { templatedFeaturesOrTilesLayer } from './mapml/layers/TemplatedFeaturesOrTilesLayer.js';
import { templatedPMTilesLayer } from './mapml/layers/TemplatedPMTilesLayer.js';
/* global M */

Expand Down Expand Up @@ -436,7 +436,8 @@ export class HTMLLinkElement extends HTMLElement {
// be loaded as part of a templated layer processing i.e. on moveend
// and the generated <link> that implements this <map-link> should be located
// in the parent <map-link>._templatedLayer.container root node if
// the _templatedLayer is an instance of TemplatedTileLayer or TemplatedFeaturesLayer
// the _templatedLayer is an instance of TemplatedTileLayer or
// TemplatedFeaturesOrTilesLayer
//
// if the parent node (or the host of the shadow root parent node) is map-layer, the link should be created in the _layer
// container
Expand Down Expand Up @@ -551,12 +552,15 @@ export class HTMLLinkElement extends HTMLElement {
if (!this.shadowRoot) {
this.attachShadow({ mode: 'open' });
}
this._templatedLayer = templatedFeaturesLayer(this._templateVars, {
// Use the FeaturesTilesLayerGroup to handle both map-feature and map-tile elements
this._templatedLayer = templatedFeaturesOrTilesLayer(this._templateVars, {
zoomBounds: this.getZoomBounds(),
extentBounds: this.getBounds(),
zIndex: this.zIndex,
pane: this.parentExtent._extentLayer.getContainer(),
linkEl: this
linkEl: this,
projection: this.mapEl._map.options.projection,
renderer: this.mapEl._map.options.renderer
}).addTo(this.parentExtent._extentLayer);
} else if (this.rel === 'query') {
if (!this.shadowRoot) {
Expand Down
2 changes: 1 addition & 1 deletion src/map-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class HTMLSelectElement extends HTMLElement {
this._extentEl = this.parentElement;
// TODO make the layer redraw after map-select change event
// origin of this block was in _initTemplateVars from map-extent, which was
// originally part of MapMLLayer...
// originally part of MapLayer...
//
// use a throwaway div to parse the input from MapML into HTML
this._createLayerControlForSelect();
Expand Down
Loading