refactor: use events for control-layers layer add/remove instead of DOM traversal

Replace the #map getter (which used closest("leaflet-map") + leafletObject)
with two new custom events: leaflet-add-layer and leaflet-remove-layer.
The map listens for them and delegates to map.addLayer/removeLayer.

This removes the coupling between leaflet-control-layers and the map
element, aligning with the existing leaflet-register event protocol.
main
Buddy 3 months ago
parent eba6b2e6ad
commit f85e67547d

@ -25,8 +25,11 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
if (!checked) uncheckedLayers.push(layer); if (!checked) uncheckedLayers.push(layer);
} }
const map = this.#map; for (const layer of uncheckedLayers) {
for (const layer of uncheckedLayers) map?.removeLayer(layer); this.dispatchEvent(
new CustomEvent('leaflet-remove-layer', { bubbles: true, detail: { layer } }),
);
}
this.#obj = new Control.Layers(baseLayers, overlays, { this.#obj = new Control.Layers(baseLayers, overlays, {
position: this.getAttribute('position') as ControlPosition | undefined, position: this.getAttribute('position') as ControlPosition | undefined,
@ -57,24 +60,6 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
return this.#obj; return this.#obj;
} }
get #map():
| {
removeLayer(l: Layer): unknown;
addLayer(l: Layer): unknown;
}
| undefined {
const mapEl = this.closest('leaflet-map');
if (!mapEl) return undefined;
return (
mapEl as unknown as {
leafletObject?: {
removeLayer(l: Layer): unknown;
addLayer(l: Layer): unknown;
};
}
).leafletObject;
}
#onChildRegister = (e: LeafletRegisterEvent) => { #onChildRegister = (e: LeafletRegisterEvent) => {
e.stopPropagation(); e.stopPropagation();
const el = e.detail.element; const el = e.detail.element;
@ -85,7 +70,11 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
const checked = el.hasAttribute('checked'); const checked = el.hasAttribute('checked');
if (base) this.#obj!.addBaseLayer(layer, name); if (base) this.#obj!.addBaseLayer(layer, name);
else this.#obj!.addOverlay(layer, name); else this.#obj!.addOverlay(layer, name);
if (checked) this.#map?.addLayer(layer); if (checked) {
this.dispatchEvent(
new CustomEvent('leaflet-add-layer', { bubbles: true, detail: { layer } }),
);
}
}; };
} }

@ -1,4 +1,4 @@
import { Icon, Map as LMap, MapOptions } from 'leaflet'; import { Icon, Layer, Map as LMap, MapOptions } from 'leaflet';
import { defineProps, num, off, on, type NumProp, type PropDef } from '../core/props.ts'; import { defineProps, num, off, on, type NumProp, type PropDef } from '../core/props.ts';
import { LeafletRegisterEvent } from '../core/register.ts'; import { LeafletRegisterEvent } from '../core/register.ts';
@ -205,6 +205,8 @@ export class LeafletMap extends TypedBase {
'leaflet-register', 'leaflet-register',
this.#handleLeafletRegister as EventListenerOrEventListenerObject, this.#handleLeafletRegister as EventListenerOrEventListenerObject,
); );
this.addEventListener('leaflet-add-layer', this.#onAddLayer);
this.addEventListener('leaflet-remove-layer', this.#onRemoveLayer);
} }
disconnectedCallback() { disconnectedCallback() {
@ -214,6 +216,8 @@ export class LeafletMap extends TypedBase {
'leaflet-register', 'leaflet-register',
this.#handleLeafletRegister as EventListenerOrEventListenerObject, this.#handleLeafletRegister as EventListenerOrEventListenerObject,
); );
this.removeEventListener('leaflet-add-layer', this.#onAddLayer);
this.removeEventListener('leaflet-remove-layer', this.#onRemoveLayer);
if (!this.#map) return; if (!this.#map) return;
for (const [event, handler] of this.#mapEventHandlers) { for (const [event, handler] of this.#mapEventHandlers) {
this.#map.off(event, handler); this.#map.off(event, handler);
@ -309,6 +313,14 @@ export class LeafletMap extends TypedBase {
} }
}; };
#onAddLayer = (e: Event) => {
this.#map?.addLayer((e as CustomEvent<{ layer: Layer }>).detail.layer);
};
#onRemoveLayer = (e: Event) => {
this.#map?.removeLayer((e as CustomEvent<{ layer: Layer }>).detail.layer);
};
get leafletObject() { get leafletObject() {
return this.#map; return this.#map;
} }

@ -9,9 +9,13 @@ export type LeafletRegisterEvent = CustomEvent<{
element: HTMLElement; element: HTMLElement;
}>; }>;
export type LeafletLayerEvent = CustomEvent<{ layer: Layer }>;
declare global { declare global {
interface HTMLElementEventMap { interface HTMLElementEventMap {
'leaflet-register': LeafletRegisterEvent; 'leaflet-register': LeafletRegisterEvent;
'leaflet-add-layer': LeafletLayerEvent;
'leaflet-remove-layer': LeafletLayerEvent;
} }
} }

Loading…
Cancel
Save