@prushforth/map 1.0.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +89 -0
- package/demo/index.html +78 -0
- package/dist/cjs/AttributionButton-DgbgLHy4.js +106 -0
- package/dist/cjs/MapTileLayer-D4vp8bR4.js +454 -0
- package/dist/cjs/app-globals-DY--Q2Nl.js +775 -0
- package/dist/cjs/calculatePosition-CDcdNl7C.js +92 -0
- package/dist/cjs/gcds-ext-map.cjs.js +47 -0
- package/dist/cjs/gcds-ext-map_2.cjs.entry.js +8081 -0
- package/dist/cjs/index-CW_WOSnc.js +32697 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/loader.cjs.js +14 -0
- package/dist/cjs/locale-_4nEyxeO.js +153 -0
- package/dist/cjs/map-a.cjs.entry.js +16 -0
- package/dist/cjs/map-caption.cjs.entry.js +55 -0
- package/dist/cjs/map-extent.cjs.entry.js +993 -0
- package/dist/cjs/map-feature.cjs.entry.js +636 -0
- package/dist/cjs/map-featurecaption.cjs.entry.js +14 -0
- package/dist/cjs/map-geometry.cjs.entry.js +36 -0
- package/dist/cjs/map-input.cjs.entry.js +348 -0
- package/dist/cjs/map-link.cjs.entry.js +6055 -0
- package/dist/cjs/map-meta.cjs.entry.js +40 -0
- package/dist/cjs/map-properties.cjs.entry.js +14 -0
- package/dist/cjs/map-select.cjs.entry.js +100 -0
- package/dist/cjs/map-span.cjs.entry.js +14 -0
- package/dist/cjs/map-style.cjs.entry.js +127 -0
- package/dist/cjs/map-tile.cjs.entry.js +274 -0
- package/dist/cjs/renderStyles-yOMXvf12.js +59 -0
- package/dist/collection/assets/canada.json +1 -0
- package/dist/collection/assets/images/w3community.ico +0 -0
- package/dist/collection/assets/mapml/en/apstile/arctic +18 -0
- package/dist/collection/assets/mapml/en/cbmtile/canvec +22 -0
- package/dist/collection/assets/mapml/en/cbmtile/cbmt +24 -0
- package/dist/collection/assets/mapml/en/cbmtile/cbmtgeom +20 -0
- package/dist/collection/assets/mapml/en/cbmtile/cbmtsimple +20 -0
- package/dist/collection/assets/mapml/en/cbmtile/current_conditions +33 -0
- package/dist/collection/assets/mapml/en/cbmtile/toporama +25 -0
- package/dist/collection/assets/mapml/en/custom/arcticsdi.mapml +18 -0
- package/dist/collection/assets/mapml/en/osmtile/cbmt +24 -0
- package/dist/collection/assets/mapml/en/osmtile/current_conditions +32 -0
- package/dist/collection/assets/mapml/en/osmtile/dark.mapml +19 -0
- package/dist/collection/assets/mapml/en/osmtile/light.mapml +19 -0
- package/dist/collection/assets/mapml/en/osmtile/osm +19 -0
- package/dist/collection/assets/mapml/en/osmtile/toporama +25 -0
- package/dist/collection/assets/mapml/fr/apstile/arctic +19 -0
- package/dist/collection/assets/mapml/fr/cbmtile/canvec +22 -0
- package/dist/collection/assets/mapml/fr/cbmtile/cbmt +24 -0
- package/dist/collection/assets/mapml/fr/cbmtile/cbmtgeom +20 -0
- package/dist/collection/assets/mapml/fr/cbmtile/cbmtsimple +20 -0
- package/dist/collection/assets/mapml/fr/cbmtile/current_conditions +25 -0
- package/dist/collection/assets/mapml/fr/cbmtile/toporama +25 -0
- package/dist/collection/assets/mapml/fr/osmtile/cbmt +24 -0
- package/dist/collection/assets/mapml/fr/osmtile/current_conditions +24 -0
- package/dist/collection/assets/mapml/fr/osmtile/dark.mapml +19 -0
- package/dist/collection/assets/mapml/fr/osmtile/light.mapml +19 -0
- package/dist/collection/assets/mapml/fr/osmtile/osm +19 -0
- package/dist/collection/assets/mapml/fr/osmtile/toporama +25 -0
- package/dist/collection/assets/pmtiles/darkTheme.js +19 -0
- package/dist/collection/assets/pmtiles/lightTheme.js +19 -0
- package/dist/collection/collection-manifest.json +28 -0
- package/dist/collection/components/gcds-ext-map/assets/pmtiles/darkTheme.js +19 -0
- package/dist/collection/components/gcds-ext-map/assets/pmtiles/lightTheme.js +19 -0
- package/dist/collection/components/gcds-ext-map/gcds-ext-map.css +2138 -0
- package/dist/collection/components/gcds-ext-map/gcds-ext-map.js +1517 -0
- package/dist/collection/components/gcds-ext-map/stories/gcds-ext-map.stories.js +367 -0
- package/dist/collection/components/map-a/map-a.js +89 -0
- package/dist/collection/components/map-caption/map-caption.js +52 -0
- package/dist/collection/components/map-extent/map-extent.js +809 -0
- package/dist/collection/components/map-feature/map-feature.js +724 -0
- package/dist/collection/components/map-featurecaption/map-featurecaption.js +6 -0
- package/dist/collection/components/map-geometry/map-geometry.js +57 -0
- package/dist/collection/components/map-input/map-input.js +355 -0
- package/dist/collection/components/map-layer/map-layer.js +1245 -0
- package/dist/collection/components/map-layer/stories/map-layer.stories.js +101 -0
- package/dist/collection/components/map-link/map-link.js +1149 -0
- package/dist/collection/components/map-meta/map-meta.js +82 -0
- package/dist/collection/components/map-properties/map-properties.js +7 -0
- package/dist/collection/components/map-select/map-select.js +145 -0
- package/dist/collection/components/map-span/map-span.js +7 -0
- package/dist/collection/components/map-style/map-style.js +144 -0
- package/dist/collection/components/map-tile/map-tile.js +370 -0
- package/dist/collection/components/utils/mapml/DOMTokenList.js +123 -0
- package/dist/collection/components/utils/mapml/DefaultMapOptions.js +11 -0
- package/dist/collection/components/utils/mapml/Util.js +1601 -0
- package/dist/collection/components/utils/mapml/control/AttributionButton.js +101 -0
- package/dist/collection/components/utils/mapml/control/FullscreenButton.js +181 -0
- package/dist/collection/components/utils/mapml/control/GeolocationButton.js +70 -0
- package/dist/collection/components/utils/mapml/control/LayerControl.js +212 -0
- package/dist/collection/components/utils/mapml/control/ReloadButton.js +75 -0
- package/dist/collection/components/utils/mapml/control/ScaleBar.js +108 -0
- package/dist/collection/components/utils/mapml/control/SearchButton.js +565 -0
- package/dist/collection/components/utils/mapml/elementSupport/extents/createLayerControlForExtent.js +259 -0
- package/dist/collection/components/utils/mapml/elementSupport/inputs/heightInput.js +18 -0
- package/dist/collection/components/utils/mapml/elementSupport/inputs/hiddenInput.js +19 -0
- package/dist/collection/components/utils/mapml/elementSupport/inputs/locationInput.js +127 -0
- package/dist/collection/components/utils/mapml/elementSupport/inputs/widthInput.js +18 -0
- package/dist/collection/components/utils/mapml/elementSupport/inputs/zoomInput.js +30 -0
- package/dist/collection/components/utils/mapml/elementSupport/layers/calculatePosition.js +88 -0
- package/dist/collection/components/utils/mapml/elementSupport/layers/createLayerControlForLayer.js +326 -0
- package/dist/collection/components/utils/mapml/elementSupport/layers/renderStyles.js +55 -0
- package/dist/collection/components/utils/mapml/elementSupport/viewers/matchMedia.js +251 -0
- package/dist/collection/components/utils/mapml/features/featureRenderer.js +342 -0
- package/dist/collection/components/utils/mapml/features/geometry.js +268 -0
- package/dist/collection/components/utils/mapml/features/path.js +485 -0
- package/dist/collection/components/utils/mapml/handlers/AnnounceMovement.js +154 -0
- package/dist/collection/components/utils/mapml/handlers/ContextMenu.js +1436 -0
- package/dist/collection/components/utils/mapml/handlers/FeatureIndex.js +116 -0
- package/dist/collection/components/utils/mapml/handlers/QueryHandler.js +476 -0
- package/dist/collection/components/utils/mapml/handlers/keyboard.js +60 -0
- package/dist/collection/components/utils/mapml/layers/Crosshair.js +108 -0
- package/dist/collection/components/utils/mapml/layers/DebugOverlay.js +357 -0
- package/dist/collection/components/utils/mapml/layers/FeatureIndexOverlay.js +239 -0
- package/dist/collection/components/utils/mapml/layers/ImageLayer.js +136 -0
- package/dist/collection/components/utils/mapml/layers/MapExtentLayer.js +114 -0
- package/dist/collection/components/utils/mapml/layers/MapFeatureLayer.js +623 -0
- package/dist/collection/components/utils/mapml/layers/MapLayer.js +640 -0
- package/dist/collection/components/utils/mapml/layers/MapTileLayer.js +450 -0
- package/dist/collection/components/utils/mapml/layers/TemplatedFeaturesOrTilesLayer.js +346 -0
- package/dist/collection/components/utils/mapml/layers/TemplatedImageLayer.js +276 -0
- package/dist/collection/components/utils/mapml/layers/TemplatedPMTilesLayer.js +135 -0
- package/dist/collection/components/utils/mapml/layers/TemplatedTileLayer.js +664 -0
- package/dist/collection/components/utils/utils.js +26 -0
- package/dist/collection/fonts/icons/LICENSE.txt +92 -0
- package/dist/collection/fonts/icons/README.md +543 -0
- package/dist/collection/fonts/icons/gcds-icons.css +110 -0
- package/dist/collection/fonts/icons/gcds-icons.eot +0 -0
- package/dist/collection/fonts/icons/gcds-icons.svg +82 -0
- package/dist/collection/fonts/icons/gcds-icons.ttf +0 -0
- package/dist/collection/fonts/icons/gcds-icons.woff +0 -0
- package/dist/collection/fonts/lato/LICENSE.txt +48 -0
- package/dist/collection/fonts/lato/README.md +195 -0
- package/dist/collection/fonts/lato/gcds-lato-italic.woff +0 -0
- package/dist/collection/fonts/lato/gcds-lato-italic.woff2 +0 -0
- package/dist/collection/fonts/lato/gcds-lato.css +30 -0
- package/dist/collection/fonts/lato/gcds-lato.woff +0 -0
- package/dist/collection/fonts/lato/gcds-lato.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/LICENSE.txt +43 -0
- package/dist/collection/fonts/noto-sans/README.md +423 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-bold-italic.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-bold-italic.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-bold.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-bold.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-light-italic.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-light-italic.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-light.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-light.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-medium-italic.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-medium-italic.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-medium.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-medium.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-regular-italic.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-regular-italic.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-regular.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-regular.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-semibold-italic.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-semibold-italic.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-semibold.woff +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans-semibold.woff2 +0 -0
- package/dist/collection/fonts/noto-sans/gcds-noto-sans.css +89 -0
- package/dist/collection/fonts/noto-sans-mono/LICENSE.txt +93 -0
- package/dist/collection/fonts/noto-sans-mono/README.md +135 -0
- package/dist/collection/fonts/noto-sans-mono/gcds-noto-sans-mono.css +17 -0
- package/dist/collection/fonts/noto-sans-mono/gcds-noto-sans-mono.woff +0 -0
- package/dist/collection/fonts/noto-sans-mono/gcds-noto-sans-mono.woff2 +0 -0
- package/dist/collection/generated/locale.js +148 -0
- package/dist/collection/global/mapml-globals.js +916 -0
- package/dist/collection/index.js +1 -0
- package/dist/collection/leaflet-src.esm.js +14419 -0
- package/dist/components/gcds-ext-map.d.ts +11 -0
- package/dist/components/gcds-ext-map.js +10 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/map-a.d.ts +11 -0
- package/dist/components/map-a.js +1 -0
- package/dist/components/map-caption.d.ts +11 -0
- package/dist/components/map-caption.js +1 -0
- package/dist/components/map-extent.d.ts +11 -0
- package/dist/components/map-extent.js +1 -0
- package/dist/components/map-feature.d.ts +11 -0
- package/dist/components/map-feature.js +1 -0
- package/dist/components/map-featurecaption.d.ts +11 -0
- package/dist/components/map-featurecaption.js +1 -0
- package/dist/components/map-geometry.d.ts +11 -0
- package/dist/components/map-geometry.js +1 -0
- package/dist/components/map-input.d.ts +11 -0
- package/dist/components/map-input.js +1 -0
- package/dist/components/map-layer.d.ts +11 -0
- package/dist/components/map-layer.js +1 -0
- package/dist/components/map-link.d.ts +11 -0
- package/dist/components/map-link.js +1 -0
- package/dist/components/map-meta.d.ts +11 -0
- package/dist/components/map-meta.js +1 -0
- package/dist/components/map-properties.d.ts +11 -0
- package/dist/components/map-properties.js +1 -0
- package/dist/components/map-select.d.ts +11 -0
- package/dist/components/map-select.js +1 -0
- package/dist/components/map-span.d.ts +11 -0
- package/dist/components/map-span.js +1 -0
- package/dist/components/map-style.d.ts +11 -0
- package/dist/components/map-style.js +1 -0
- package/dist/components/map-tile.d.ts +11 -0
- package/dist/components/map-tile.js +1 -0
- package/dist/components/p-B4YLD_Og.js +1 -0
- package/dist/components/p-BE41zrui.js +1 -0
- package/dist/components/p-Bpv_U_Lb.js +1 -0
- package/dist/components/p-CwRxGZga.js +5 -0
- package/dist/components/p-EYVT9Efh.js +1 -0
- package/dist/components/p-gwC_yeRa.js +1 -0
- package/dist/esm/AttributionButton-CfaoSLCu.js +103 -0
- package/dist/esm/MapTileLayer-DvC_iOIS.js +451 -0
- package/dist/esm/app-globals-De5ze2BD.js +773 -0
- package/dist/esm/calculatePosition-B4YLD_Og.js +90 -0
- package/dist/esm/gcds-ext-map.js +43 -0
- package/dist/esm/gcds-ext-map_2.entry.js +8078 -0
- package/dist/esm/index-BUsJ7i5g.js +32656 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/loader.js +12 -0
- package/dist/esm/locale-Bpv_U_Lb.js +150 -0
- package/dist/esm/map-a.entry.js +14 -0
- package/dist/esm/map-caption.entry.js +53 -0
- package/dist/esm/map-extent.entry.js +991 -0
- package/dist/esm/map-feature.entry.js +634 -0
- package/dist/esm/map-featurecaption.entry.js +12 -0
- package/dist/esm/map-geometry.entry.js +34 -0
- package/dist/esm/map-input.entry.js +346 -0
- package/dist/esm/map-link.entry.js +6035 -0
- package/dist/esm/map-meta.entry.js +38 -0
- package/dist/esm/map-properties.entry.js +12 -0
- package/dist/esm/map-select.entry.js +98 -0
- package/dist/esm/map-span.entry.js +12 -0
- package/dist/esm/map-style.entry.js +125 -0
- package/dist/esm/map-tile.entry.js +272 -0
- package/dist/esm/renderStyles-EYVT9Efh.js +57 -0
- package/dist/gcds-ext-map/assets/canada.json +1 -0
- package/dist/gcds-ext-map/assets/images/w3community.ico +0 -0
- package/dist/gcds-ext-map/assets/mapml/en/apstile/arctic +18 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/canvec +22 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/cbmt +24 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/cbmtgeom +20 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/cbmtsimple +20 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/current_conditions +33 -0
- package/dist/gcds-ext-map/assets/mapml/en/cbmtile/toporama +25 -0
- package/dist/gcds-ext-map/assets/mapml/en/custom/arcticsdi.mapml +18 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/cbmt +24 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/current_conditions +32 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/dark.mapml +19 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/light.mapml +19 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/osm +19 -0
- package/dist/gcds-ext-map/assets/mapml/en/osmtile/toporama +25 -0
- package/dist/gcds-ext-map/assets/mapml/fr/apstile/arctic +19 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/canvec +22 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/cbmt +24 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/cbmtgeom +20 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/cbmtsimple +20 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/current_conditions +25 -0
- package/dist/gcds-ext-map/assets/mapml/fr/cbmtile/toporama +25 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/cbmt +24 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/current_conditions +24 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/dark.mapml +19 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/light.mapml +19 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/osm +19 -0
- package/dist/gcds-ext-map/assets/mapml/fr/osmtile/toporama +25 -0
- package/dist/gcds-ext-map/assets/pmtiles/darkTheme.js +19 -0
- package/dist/gcds-ext-map/assets/pmtiles/lightTheme.js +19 -0
- package/dist/gcds-ext-map/fonts/icons/LICENSE.txt +92 -0
- package/dist/gcds-ext-map/fonts/icons/README.md +543 -0
- package/dist/gcds-ext-map/fonts/icons/gcds-icons.css +110 -0
- package/dist/gcds-ext-map/fonts/icons/gcds-icons.eot +0 -0
- package/dist/gcds-ext-map/fonts/icons/gcds-icons.svg +82 -0
- package/dist/gcds-ext-map/fonts/icons/gcds-icons.ttf +0 -0
- package/dist/gcds-ext-map/fonts/icons/gcds-icons.woff +0 -0
- package/dist/gcds-ext-map/fonts/lato/LICENSE.txt +48 -0
- package/dist/gcds-ext-map/fonts/lato/README.md +195 -0
- package/dist/gcds-ext-map/fonts/lato/gcds-lato-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/lato/gcds-lato-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/lato/gcds-lato.css +30 -0
- package/dist/gcds-ext-map/fonts/lato/gcds-lato.woff +0 -0
- package/dist/gcds-ext-map/fonts/lato/gcds-lato.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/LICENSE.txt +43 -0
- package/dist/gcds-ext-map/fonts/noto-sans/README.md +423 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-bold-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-bold-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-bold.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-bold.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-light-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-light-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-light.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-light.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-medium-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-medium-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-medium.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-medium.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-regular-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-regular-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-regular.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-regular.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-semibold-italic.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-semibold-italic.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-semibold.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans-semibold.woff2 +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans/gcds-noto-sans.css +89 -0
- package/dist/gcds-ext-map/fonts/noto-sans-mono/LICENSE.txt +93 -0
- package/dist/gcds-ext-map/fonts/noto-sans-mono/README.md +135 -0
- package/dist/gcds-ext-map/fonts/noto-sans-mono/gcds-noto-sans-mono.css +17 -0
- package/dist/gcds-ext-map/fonts/noto-sans-mono/gcds-noto-sans-mono.woff +0 -0
- package/dist/gcds-ext-map/fonts/noto-sans-mono/gcds-noto-sans-mono.woff2 +0 -0
- package/dist/gcds-ext-map/gcds-ext-map.esm.js +1 -0
- package/dist/gcds-ext-map/index.esm.js +0 -0
- package/dist/gcds-ext-map/leaflet-src.esm.js +14419 -0
- package/dist/gcds-ext-map/p-1b22f774.entry.js +1 -0
- package/dist/gcds-ext-map/p-29b4ba34.entry.js +1 -0
- package/dist/gcds-ext-map/p-2dd09d44.entry.js +1 -0
- package/dist/gcds-ext-map/p-3fef47e5.entry.js +1 -0
- package/dist/gcds-ext-map/p-4e324a1d.entry.js +1 -0
- package/dist/gcds-ext-map/p-4f4a6873.entry.js +1 -0
- package/dist/gcds-ext-map/p-9cc5ad37.entry.js +1 -0
- package/dist/gcds-ext-map/p-9edfea7d.entry.js +1 -0
- package/dist/gcds-ext-map/p-B4YLD_Og.js +1 -0
- package/dist/gcds-ext-map/p-B8Id5Ptd.js +1 -0
- package/dist/gcds-ext-map/p-BUsJ7i5g.js +6 -0
- package/dist/gcds-ext-map/p-Bpv_U_Lb.js +1 -0
- package/dist/gcds-ext-map/p-CtOuMgy9.js +1 -0
- package/dist/gcds-ext-map/p-Dd474fsL.js +1 -0
- package/dist/gcds-ext-map/p-EYVT9Efh.js +1 -0
- package/dist/gcds-ext-map/p-a67d721d.entry.js +1 -0
- package/dist/gcds-ext-map/p-b16e862b.entry.js +1 -0
- package/dist/gcds-ext-map/p-b9cbf1e0.entry.js +10 -0
- package/dist/gcds-ext-map/p-cab5246e.entry.js +1 -0
- package/dist/gcds-ext-map/p-d58d409b.entry.js +1 -0
- package/dist/gcds-ext-map/p-dfa21368.entry.js +1 -0
- package/dist/gcds-ext-map/p-f211048a.entry.js +1 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/components/gcds-ext-map/gcds-ext-map.d.ts +125 -0
- package/dist/types/components/gcds-ext-map/stories/gcds-ext-map.stories.d.ts +230 -0
- package/dist/types/components/map-a/map-a.d.ts +7 -0
- package/dist/types/components/map-caption/map-caption.d.ts +7 -0
- package/dist/types/components/map-extent/map-extent.d.ts +53 -0
- package/dist/types/components/map-feature/map-feature.d.ts +50 -0
- package/dist/types/components/map-featurecaption/map-featurecaption.d.ts +3 -0
- package/dist/types/components/map-geometry/map-geometry.d.ts +7 -0
- package/dist/types/components/map-input/map-input.d.ts +24 -0
- package/dist/types/components/map-layer/map-layer.d.ts +85 -0
- package/dist/types/components/map-layer/stories/map-layer.stories.d.ts +96 -0
- package/dist/types/components/map-link/map-link.d.ts +66 -0
- package/dist/types/components/map-meta/map-meta.d.ts +11 -0
- package/dist/types/components/map-properties/map-properties.d.ts +3 -0
- package/dist/types/components/map-select/map-select.d.ts +13 -0
- package/dist/types/components/map-span/map-span.d.ts +5 -0
- package/dist/types/components/map-style/map-style.d.ts +17 -0
- package/dist/types/components/map-tile/map-tile.d.ts +32 -0
- package/dist/types/components/utils/mapml/DOMTokenList.d.ts +30 -0
- package/dist/types/components/utils/mapml/elementSupport/inputs/heightInput.d.ts +7 -0
- package/dist/types/components/utils/mapml/elementSupport/inputs/hiddenInput.d.ts +7 -0
- package/dist/types/components/utils/mapml/elementSupport/inputs/locationInput.d.ts +14 -0
- package/dist/types/components/utils/mapml/elementSupport/inputs/widthInput.d.ts +7 -0
- package/dist/types/components/utils/mapml/elementSupport/inputs/zoomInput.d.ts +11 -0
- package/dist/types/components/utils/mapml/layers/MapLayer.d.ts +69 -0
- package/dist/types/components/utils/utils.d.ts +2 -0
- package/dist/types/components.d.ts +521 -0
- package/dist/types/gcds-ext-map.d.ts +17 -0
- package/dist/types/generated/locale.d.ts +146 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +1861 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1517 @@
|
|
|
1
|
+
import { map, LatLng, latLngBounds, control } from "leaflet";
|
|
2
|
+
import { Util } from "../utils/mapml/Util.js";
|
|
3
|
+
import { DOMTokenList } from "../utils/mapml/DOMTokenList.js";
|
|
4
|
+
import { locale, localeFr } from "../../generated/locale.js";
|
|
5
|
+
import { matchMedia } from "../utils/mapml/elementSupport/viewers/matchMedia.js";
|
|
6
|
+
// TODO: Import Stencil component versions when created
|
|
7
|
+
// import { HTMLLayerElement } from '../map-layer/map-layer.js';
|
|
8
|
+
// import { LayerDashElement } from '../layer-/layer-.js';
|
|
9
|
+
// import { HTMLMapCaptionElement } from '../map-caption/map-caption.js';
|
|
10
|
+
// import { HTMLFeatureElement } from '../map-feature/map-feature.js';
|
|
11
|
+
// import { HTMLExtentElement } from '../map-extent/map-extent.js';
|
|
12
|
+
// import { HTMLInputElement } from '../map-input/map-input.js';
|
|
13
|
+
// import { HTMLSelectElement } from '../map-select/map-select.js';
|
|
14
|
+
// import { HTMLLinkElement } from '../map-link/map-link.js';
|
|
15
|
+
// import { HTMLStyleElement } from '../map-style/map-style.js';
|
|
16
|
+
// import { HTMLWebMapElement } from '../web-map/web-map.js';
|
|
17
|
+
// import { HTMLMapAreaElement } from '../map-area/map-area.js';
|
|
18
|
+
import { layerControl } from "../utils/mapml/control/LayerControl.js";
|
|
19
|
+
// due to Stencil bundling shenanigans, the import here doesn't happen
|
|
20
|
+
// (maybe because it's not actually called anywhere - the attribution control
|
|
21
|
+
// was auto-added and the
|
|
22
|
+
// attribution control doesn't get auto-added
|
|
23
|
+
// Auto-added via Map.addInitHook
|
|
24
|
+
// import { attributionButton } from '../../utils/mapml/control/AttributionButton.js';
|
|
25
|
+
import { reloadButton } from "../utils/mapml/control/ReloadButton.js";
|
|
26
|
+
import { scaleBar } from "../utils/mapml/control/ScaleBar.js";
|
|
27
|
+
import { geolocationButton } from "../utils/mapml/control/GeolocationButton.js";
|
|
28
|
+
import { fullscreenButton } from "../utils/mapml/control/FullscreenButton.js";
|
|
29
|
+
import { searchButton } from "../utils/mapml/control/SearchButton.js";
|
|
30
|
+
import { debugOverlay } from "../utils/mapml/layers/DebugOverlay.js";
|
|
31
|
+
import { crosshair } from "../utils/mapml/layers/Crosshair.js";
|
|
32
|
+
import { featureIndexOverlay } from "../utils/mapml/layers/FeatureIndexOverlay.js";
|
|
33
|
+
export class GcdsExtMap {
|
|
34
|
+
el;
|
|
35
|
+
// Mirror the observedAttributes as Stencil props
|
|
36
|
+
lat = 0;
|
|
37
|
+
lon = 0;
|
|
38
|
+
zoom = 0;
|
|
39
|
+
projection = 'OSMTILE';
|
|
40
|
+
// Note: width/height are NOT Stencil props - they're managed via custom properties and MutationObserver
|
|
41
|
+
// @Prop() width?: string;
|
|
42
|
+
// @Prop() height?: string;
|
|
43
|
+
controls = false;
|
|
44
|
+
static = false;
|
|
45
|
+
_controlslist;
|
|
46
|
+
locale;
|
|
47
|
+
_controlsList;
|
|
48
|
+
_source;
|
|
49
|
+
_history = [];
|
|
50
|
+
_historyIndex = -1;
|
|
51
|
+
_traversalCall = false;
|
|
52
|
+
// Private properties that mirror the original (will be set in componentDidLoad)
|
|
53
|
+
_map;
|
|
54
|
+
// private locale: any; // TODO: Use when implementing locale support
|
|
55
|
+
_container;
|
|
56
|
+
mapCaptionObserver;
|
|
57
|
+
// @ts-ignore - Stored for potential cleanup, removed when map is deleted
|
|
58
|
+
_featureIndexOverlay;
|
|
59
|
+
_zoomControl;
|
|
60
|
+
_layerControl;
|
|
61
|
+
_reloadButton;
|
|
62
|
+
_fullScreenControl;
|
|
63
|
+
_geolocationButton;
|
|
64
|
+
_scaleBar;
|
|
65
|
+
_searchButton;
|
|
66
|
+
_isInitialized = false;
|
|
67
|
+
_debug;
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
_crosshair;
|
|
70
|
+
_boundDropHandler;
|
|
71
|
+
_boundDragoverHandler;
|
|
72
|
+
// see comments below regarding attributeChangedCallback vs. getter/setter
|
|
73
|
+
// usage. Effectively, the user of the element must use the property, not
|
|
74
|
+
// the getAttribute/setAttribute/removeAttribute DOM API, because the latter
|
|
75
|
+
// calls don't result in the getter/setter being called (so you have to use
|
|
76
|
+
// the getter/setter directly)
|
|
77
|
+
controlsChanged(newValue) {
|
|
78
|
+
// Mirror original controls setter logic
|
|
79
|
+
if (this._map) {
|
|
80
|
+
if (newValue) {
|
|
81
|
+
this._showControls();
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this._hideControls();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
controlsListChanged(newValue) {
|
|
89
|
+
if (this._controlsList) {
|
|
90
|
+
this._controlsList.value = newValue;
|
|
91
|
+
// Re-toggle controls to apply the new controlslist filtering
|
|
92
|
+
if (this._map) {
|
|
93
|
+
this._toggleControls();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
get controlsList() {
|
|
98
|
+
return this._controlsList;
|
|
99
|
+
}
|
|
100
|
+
set controlsList(value) {
|
|
101
|
+
if (this._controlsList && (typeof value === 'string' || value === null)) {
|
|
102
|
+
if (value) {
|
|
103
|
+
this.el.setAttribute('controlslist', value);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this.el.removeAttribute('controlslist');
|
|
107
|
+
}
|
|
108
|
+
// DOMTokenList automatically reflects the attribute change
|
|
109
|
+
// Re-toggle controls based on new attribute value
|
|
110
|
+
if (this._map) {
|
|
111
|
+
this._toggleControls();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Note: width/height watchers removed - handled via MutationObserver instead
|
|
116
|
+
// since they're not Stencil @Prop() anymore
|
|
117
|
+
// Note: lat, lon, and zoom are NOT watched because in mapml-viewer, changing these
|
|
118
|
+
// attributes does not change the map position/zoom. These attributes are only
|
|
119
|
+
// updated by map events to reflect the current state for external observers.
|
|
120
|
+
async projectionChanged(newValue, oldValue) {
|
|
121
|
+
if (newValue && this._map && this._map.options.projection !== newValue) {
|
|
122
|
+
const reconnectLayers = () => {
|
|
123
|
+
// save map location and zoom
|
|
124
|
+
let lat = this.lat;
|
|
125
|
+
let lon = this.lon;
|
|
126
|
+
let zoom = this.zoom;
|
|
127
|
+
// saving the lat, lon and zoom is necessary because Leaflet seems
|
|
128
|
+
// to try to compensate for the change in the scales for each zoom
|
|
129
|
+
// level in the crs by changing the zoom level of the map when
|
|
130
|
+
// you set the map crs. So, we save the current view for use below
|
|
131
|
+
// when all the layers' reconnections have settled.
|
|
132
|
+
// leaflet doesn't like this: https://github.com/Leaflet/Leaflet/issues/2553
|
|
133
|
+
this._map.options.crs = window.M[newValue];
|
|
134
|
+
this._map.options.projection = newValue;
|
|
135
|
+
let layersReady = [];
|
|
136
|
+
this._map.announceMovement?.disable();
|
|
137
|
+
// Get all map-layer and layer- elements and reconnect them
|
|
138
|
+
const layers = this.el.querySelectorAll('map-layer,layer-');
|
|
139
|
+
for (let layer of Array.from(layers)) {
|
|
140
|
+
layer.removeAttribute('disabled');
|
|
141
|
+
let reAttach = this.el.removeChild(layer);
|
|
142
|
+
this.el.appendChild(reAttach);
|
|
143
|
+
if (reAttach.whenReady) {
|
|
144
|
+
layersReady.push(reAttach.whenReady());
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return Promise.allSettled(layersReady).then(() => {
|
|
148
|
+
// use the saved map location to ensure it is correct after
|
|
149
|
+
// changing the map CRS. Specifically affects projection
|
|
150
|
+
// upgrades, e.g. https://maps4html.org/experiments/custom-projections/BNG/
|
|
151
|
+
// see leaflet bug: https://github.com/Leaflet/Leaflet/issues/2553
|
|
152
|
+
// Skip restoration if there's only one layer - link traversal case where layer.zoomTo() should control zoom
|
|
153
|
+
const layers = this.el.layers;
|
|
154
|
+
if (layers.length === 1) {
|
|
155
|
+
const layer = layers[0];
|
|
156
|
+
if (layer.extent) {
|
|
157
|
+
this._map.setMinZoom(layer.extent.zoom.minZoom);
|
|
158
|
+
this._map.setMaxZoom(layer.extent.zoom.maxZoom);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
this.zoomTo(lat, lon, zoom);
|
|
162
|
+
if (window.M.options.announceMovement)
|
|
163
|
+
this._map.announceMovement?.enable();
|
|
164
|
+
// required to delay until map-extent.disabled is correctly set
|
|
165
|
+
// which happens as a result of map-layer._validateDisabled()
|
|
166
|
+
// which happens so much we have to delay until the calls are
|
|
167
|
+
// completed
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
this.el.dispatchEvent(new CustomEvent('map-projectionchange'));
|
|
170
|
+
}, 0);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
const connect = reconnectLayers.bind(this);
|
|
174
|
+
try {
|
|
175
|
+
await this.whenProjectionDefined(newValue);
|
|
176
|
+
await connect();
|
|
177
|
+
if (this._map && this._map.options.projection !== oldValue) {
|
|
178
|
+
// this doesn't completely work either
|
|
179
|
+
this._resetHistory();
|
|
180
|
+
}
|
|
181
|
+
if (this._debug) {
|
|
182
|
+
// Toggle debug twice to refresh it with new projection
|
|
183
|
+
for (let i = 0; i < 2; i++)
|
|
184
|
+
this.toggleDebug();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
throw new Error('Undefined projection: ' + newValue);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Note: zoom is NOT watched because in mapml-viewer, changing the zoom attribute
|
|
193
|
+
// does not change the map zoom. The zoom attribute is only updated by map events
|
|
194
|
+
// to reflect the current state for external observers.
|
|
195
|
+
// Note: instead of layers getter here, gcds-ext-map.layers property is exposed via Object.defineProperty in componentDidLoad
|
|
196
|
+
get extent() {
|
|
197
|
+
let map = this._map, pcrsBounds = Util.pixelToPCRSBounds(map.getPixelBounds(), map.getZoom(), map.options.projection);
|
|
198
|
+
let formattedExtent = Util._convertAndFormatPCRS(pcrsBounds, map.options.crs, this.projection);
|
|
199
|
+
// get min/max zoom from layers at this moment
|
|
200
|
+
let minZoom = Infinity, maxZoom = -Infinity;
|
|
201
|
+
const layers = this.el.layers;
|
|
202
|
+
for (let i = 0; i < layers.length; i++) {
|
|
203
|
+
if (layers[i].extent) {
|
|
204
|
+
if (layers[i].extent.zoom.minZoom < minZoom)
|
|
205
|
+
minZoom = layers[i].extent.zoom.minZoom;
|
|
206
|
+
if (layers[i].extent.zoom.maxZoom > maxZoom)
|
|
207
|
+
maxZoom = layers[i].extent.zoom.maxZoom;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
formattedExtent.zoom = {
|
|
211
|
+
minZoom: minZoom !== Infinity ? minZoom : map.getMinZoom(),
|
|
212
|
+
maxZoom: maxZoom !== -Infinity ? maxZoom : map.getMaxZoom()
|
|
213
|
+
};
|
|
214
|
+
return formattedExtent;
|
|
215
|
+
}
|
|
216
|
+
// Width and height getters return computed CSS values (not attribute values)
|
|
217
|
+
// This allows CSS to dominate over HTML attributes, matching mapml-viewer behavior
|
|
218
|
+
getWidth() {
|
|
219
|
+
return +window.getComputedStyle(this.el).width.replace('px', '');
|
|
220
|
+
}
|
|
221
|
+
getHeight() {
|
|
222
|
+
return +window.getComputedStyle(this.el).height.replace('px', '');
|
|
223
|
+
}
|
|
224
|
+
staticChanged() {
|
|
225
|
+
if (this._map) {
|
|
226
|
+
this._toggleStatic();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Note: Stencil handles constructor automatically, but we can use componentWillLoad for initialization
|
|
230
|
+
componentWillLoad() {
|
|
231
|
+
// Mirror the original constructor logic
|
|
232
|
+
this._source = this.el.outerHTML;
|
|
233
|
+
// create an array to track the history of the map and the current index
|
|
234
|
+
this._history = [];
|
|
235
|
+
this._historyIndex = -1;
|
|
236
|
+
this._traversalCall = false;
|
|
237
|
+
}
|
|
238
|
+
// Mirror the connectedCallback logic in componentDidLoad
|
|
239
|
+
async connectedCallback() {
|
|
240
|
+
try {
|
|
241
|
+
// Sync initial history state to element for MapML controls
|
|
242
|
+
this.el._history = this._history;
|
|
243
|
+
this.el._historyIndex = this._historyIndex;
|
|
244
|
+
// Publish width/height getters/setters to match mapml-viewer API
|
|
245
|
+
// These return computed style (CSS wins over attributes)
|
|
246
|
+
Object.defineProperty(this.el, 'width', {
|
|
247
|
+
get: () => {
|
|
248
|
+
return +window.getComputedStyle(this.el).width.replace('px', '');
|
|
249
|
+
},
|
|
250
|
+
set: (val) => {
|
|
251
|
+
// Set attribute only, don't override CSS with inline styles
|
|
252
|
+
this.el.setAttribute('width', val);
|
|
253
|
+
},
|
|
254
|
+
enumerable: true,
|
|
255
|
+
configurable: true
|
|
256
|
+
});
|
|
257
|
+
Object.defineProperty(this.el, 'height', {
|
|
258
|
+
get: () => {
|
|
259
|
+
return +window.getComputedStyle(this.el).height.replace('px', '');
|
|
260
|
+
},
|
|
261
|
+
set: (val) => {
|
|
262
|
+
// Set attribute only, don't override CSS with inline styles
|
|
263
|
+
this.el.setAttribute('height', val);
|
|
264
|
+
},
|
|
265
|
+
enumerable: true,
|
|
266
|
+
configurable: true
|
|
267
|
+
});
|
|
268
|
+
// Ensure MapML controls are loaded and their init hooks are registered
|
|
269
|
+
// BEFORE creating any maps. This is critical for proper attribution control.
|
|
270
|
+
await this._ensureControlsLoaded();
|
|
271
|
+
await this.whenProjectionDefined(this.projection);
|
|
272
|
+
this._setLocale();
|
|
273
|
+
this._initShadowRoot();
|
|
274
|
+
this._controlsList = new DOMTokenList(this.el.getAttribute('controlslist'), this.el, 'controlslist', [
|
|
275
|
+
'noreload',
|
|
276
|
+
'nofullscreen',
|
|
277
|
+
'nozoom',
|
|
278
|
+
'nolayer',
|
|
279
|
+
'noscale',
|
|
280
|
+
'geolocation',
|
|
281
|
+
'search'
|
|
282
|
+
]);
|
|
283
|
+
// Defer map creation until element is laid out with valid dimensions
|
|
284
|
+
// WebKit can return percentage values from getComputedStyle before layout
|
|
285
|
+
const initMapWhenLayoutComplete = () => {
|
|
286
|
+
var s = window.getComputedStyle(this.el), wpx = s.width, hpx = s.height;
|
|
287
|
+
// Wait until we have valid pixel dimensions
|
|
288
|
+
if (!wpx.endsWith('px') || !hpx.endsWith('px')) {
|
|
289
|
+
requestAnimationFrame(initMapWhenLayoutComplete);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
var w = this.el.hasAttribute('width')
|
|
293
|
+
? this.el.getAttribute('width')
|
|
294
|
+
: parseInt(wpx.replace('px', '')), h = this.el.hasAttribute('height')
|
|
295
|
+
? this.el.getAttribute('height')
|
|
296
|
+
: parseInt(hpx.replace('px', ''));
|
|
297
|
+
this._changeWidth(w);
|
|
298
|
+
this._changeHeight(h);
|
|
299
|
+
this._createMap();
|
|
300
|
+
// Mark as initialized so watchers can now run
|
|
301
|
+
this._isInitialized = true;
|
|
302
|
+
// Watch for attribute changes to width/height after initialization
|
|
303
|
+
// This handles setAttribute() calls which don't trigger custom property setters
|
|
304
|
+
const attributeObserver = new MutationObserver((mutations) => {
|
|
305
|
+
mutations.forEach((mutation) => {
|
|
306
|
+
if (mutation.type === 'attributes' && mutation.attributeName) {
|
|
307
|
+
const newValue = this.el.getAttribute(mutation.attributeName);
|
|
308
|
+
if (mutation.attributeName === 'width' && newValue) {
|
|
309
|
+
this._changeWidth(newValue);
|
|
310
|
+
}
|
|
311
|
+
else if (mutation.attributeName === 'height' && newValue) {
|
|
312
|
+
this._changeHeight(newValue);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
attributeObserver.observe(this.el, {
|
|
318
|
+
attributes: true,
|
|
319
|
+
attributeFilter: ['width', 'height']
|
|
320
|
+
});
|
|
321
|
+
// Store observer for cleanup
|
|
322
|
+
this.el._attributeObserver = attributeObserver;
|
|
323
|
+
// https://github.com/Maps4HTML/MapML.js/issues/274
|
|
324
|
+
this.el.setAttribute('role', 'application');
|
|
325
|
+
this._toggleStatic();
|
|
326
|
+
/*
|
|
327
|
+
1. only deletes aria-label when the last (only remaining) map caption is removed
|
|
328
|
+
2. only deletes aria-label if the aria-label was defined by the map caption element itself
|
|
329
|
+
*/
|
|
330
|
+
let mapcaption = this.el.querySelector('map-caption');
|
|
331
|
+
if (mapcaption !== null) {
|
|
332
|
+
setTimeout(() => {
|
|
333
|
+
let ariaupdate = this.el.getAttribute('aria-label');
|
|
334
|
+
if (ariaupdate === mapcaption.innerHTML) {
|
|
335
|
+
this.mapCaptionObserver = new MutationObserver((_m) => {
|
|
336
|
+
let mapcaptionupdate = this.el.querySelector('map-caption');
|
|
337
|
+
if (mapcaptionupdate !== mapcaption) {
|
|
338
|
+
this.el.removeAttribute('aria-label');
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
this.mapCaptionObserver.observe(this.el, {
|
|
342
|
+
childList: true
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}, 0);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
initMapWhenLayoutComplete();
|
|
349
|
+
}
|
|
350
|
+
catch (e) {
|
|
351
|
+
console.log(e);
|
|
352
|
+
throw new Error('Error: ' + e);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
_setLocale() {
|
|
356
|
+
// Priority order (matching mapml-viewer behavior):
|
|
357
|
+
// 1. :lang(fr) attribute in ancestry (Canadian French context)
|
|
358
|
+
// 2. :lang(en) attribute in ancestry (Canadian English context)
|
|
359
|
+
// 3. <map-options> locale in document head (browser/custom locale)
|
|
360
|
+
if (this.el.closest(':lang(fr)') === this.el) {
|
|
361
|
+
this.locale = localeFr;
|
|
362
|
+
}
|
|
363
|
+
else if (this.el.closest(':lang(en)') === this.el) {
|
|
364
|
+
this.locale = locale;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
// Check if there's a <map-options> element in the document head
|
|
368
|
+
// that was placed there by the browser extension or test harness
|
|
369
|
+
const mapOptions = document.head.querySelector('map-options');
|
|
370
|
+
if (mapOptions && mapOptions.textContent) {
|
|
371
|
+
try {
|
|
372
|
+
const options = JSON.parse(mapOptions.textContent);
|
|
373
|
+
if (options.locale) {
|
|
374
|
+
this.locale = options.locale;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch (e) {
|
|
379
|
+
console.warn('Failed to parse map-options:', e);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Default to English locale if no other locale specified
|
|
383
|
+
this.locale = locale;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
_initShadowRoot() {
|
|
387
|
+
let shadowRoot = this.el.shadowRoot;
|
|
388
|
+
if (shadowRoot.querySelector('[aria-label="Interactive map"]'))
|
|
389
|
+
return;
|
|
390
|
+
// Add default :host styles AFTER Stencil's gcds-ext-map.css loads
|
|
391
|
+
// This ensures proper cascade order and allows _changeWidth/_changeHeight to modify it
|
|
392
|
+
const ensureHostStyle = () => {
|
|
393
|
+
// Wait for Stencil's stylesheet to load first
|
|
394
|
+
if (shadowRoot.styleSheets.length === 0) {
|
|
395
|
+
requestAnimationFrame(ensureHostStyle);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
// Now append our :host defaults AFTER the main gcds-ext-map.css
|
|
399
|
+
let mapDefaultCSS = document.createElement('style');
|
|
400
|
+
mapDefaultCSS.innerHTML =
|
|
401
|
+
`:host {` +
|
|
402
|
+
`all: initial;` +
|
|
403
|
+
`display: inline-block;` +
|
|
404
|
+
`background-color: white;` +
|
|
405
|
+
`height: 150px;` +
|
|
406
|
+
`width: 300px;` +
|
|
407
|
+
`contain: layout size;` +
|
|
408
|
+
`border-width: 2px;` +
|
|
409
|
+
`border-style: inset;` +
|
|
410
|
+
`}`;
|
|
411
|
+
shadowRoot.appendChild(mapDefaultCSS);
|
|
412
|
+
};
|
|
413
|
+
ensureHostStyle();
|
|
414
|
+
this._container = document.createElement('div');
|
|
415
|
+
let output = "<output role='status' aria-live='polite' aria-atomic='true' class='mapml-screen-reader-output'></output>";
|
|
416
|
+
this._container.insertAdjacentHTML('beforeend', output);
|
|
417
|
+
// Make the Leaflet container element programmatically identifiable
|
|
418
|
+
// (https://github.com/Leaflet/Leaflet/issues/7193).
|
|
419
|
+
this._container.setAttribute('role', 'region');
|
|
420
|
+
this._container.setAttribute('aria-label', 'Interactive map');
|
|
421
|
+
shadowRoot.appendChild(this._container);
|
|
422
|
+
// Expose _container on DOM element for test access and MapML compatibility
|
|
423
|
+
this.el._container = this._container;
|
|
424
|
+
// Hide all (light DOM) children of the map element (equivalent to hideElementsCSS)
|
|
425
|
+
let hideElementsCSS = document.createElement('style');
|
|
426
|
+
hideElementsCSS.innerHTML = `gcds-ext-map > * { display: none!important; }`;
|
|
427
|
+
this.el.appendChild(hideElementsCSS);
|
|
428
|
+
}
|
|
429
|
+
_createMap() {
|
|
430
|
+
if (!this._map) {
|
|
431
|
+
this._map = map(this._container, {
|
|
432
|
+
center: new LatLng(this.lat, this.lon),
|
|
433
|
+
minZoom: 0,
|
|
434
|
+
maxZoom: window.M[this.projection].options.resolutions.length - 1,
|
|
435
|
+
projection: this.projection,
|
|
436
|
+
query: true,
|
|
437
|
+
contextMenu: true,
|
|
438
|
+
announceMovement: true,
|
|
439
|
+
featureIndex: true,
|
|
440
|
+
mapEl: this.el,
|
|
441
|
+
crs: window.M[this.projection],
|
|
442
|
+
zoom: this.zoom,
|
|
443
|
+
zoomControl: false
|
|
444
|
+
});
|
|
445
|
+
// Make map accessible for debugging
|
|
446
|
+
this.el._map = this._map;
|
|
447
|
+
window._debugMap = this._map;
|
|
448
|
+
// Expose component history properties on element for MapML control compatibility
|
|
449
|
+
this.el._history = this._history;
|
|
450
|
+
this.el._historyIndex = this._historyIndex;
|
|
451
|
+
// Expose controlsList API on element for MapML control compatibility
|
|
452
|
+
// Follow standard HTML DOMTokenList behavior (like video.controlsList)
|
|
453
|
+
Object.defineProperty(this.el, 'controlsList', {
|
|
454
|
+
get: () => this._controlsList,
|
|
455
|
+
set: (value) => {
|
|
456
|
+
// Standard behavior: property assignment updates DOMTokenList value
|
|
457
|
+
// but does NOT update HTML attribute (unlike component setter)
|
|
458
|
+
if (this._controlsList && (typeof value === 'string' || value === null)) {
|
|
459
|
+
this._controlsList.value = value || '';
|
|
460
|
+
// Trigger control visibility updates without changing HTML attribute
|
|
461
|
+
if (this._map) {
|
|
462
|
+
this._toggleControls();
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
configurable: true,
|
|
467
|
+
enumerable: true
|
|
468
|
+
});
|
|
469
|
+
// Expose layers getter on element for MapML control compatibility
|
|
470
|
+
Object.defineProperty(this.el, 'layers', {
|
|
471
|
+
get: () => this.el.getElementsByTagName('map-layer'),
|
|
472
|
+
configurable: true,
|
|
473
|
+
enumerable: true
|
|
474
|
+
});
|
|
475
|
+
// Expose locale property on element for MapML control compatibility
|
|
476
|
+
Object.defineProperty(this.el, 'locale', {
|
|
477
|
+
get: () => this.locale,
|
|
478
|
+
configurable: true,
|
|
479
|
+
enumerable: true
|
|
480
|
+
});
|
|
481
|
+
// Expose extent property on element for MapML compatibility
|
|
482
|
+
Object.defineProperty(this.el, 'extent', {
|
|
483
|
+
get: () => this.extent,
|
|
484
|
+
configurable: true,
|
|
485
|
+
enumerable: true
|
|
486
|
+
});
|
|
487
|
+
// Expose width/height getters that return computed CSS values (not attributes)
|
|
488
|
+
// This allows CSS to dominate over HTML attributes, matching mapml-viewer behavior
|
|
489
|
+
Object.defineProperty(this.el, 'width', {
|
|
490
|
+
get: () => this.getWidth(),
|
|
491
|
+
set: (val) => {
|
|
492
|
+
// Setter changes the attribute AND applies the change immediately
|
|
493
|
+
this.el.setAttribute('width', val);
|
|
494
|
+
if (this._isInitialized) {
|
|
495
|
+
this._changeWidth(val);
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
configurable: true,
|
|
499
|
+
enumerable: true
|
|
500
|
+
});
|
|
501
|
+
Object.defineProperty(this.el, 'height', {
|
|
502
|
+
get: () => this.getHeight(),
|
|
503
|
+
set: (val) => {
|
|
504
|
+
// Setter changes the attribute AND applies the change immediately
|
|
505
|
+
this.el.setAttribute('height', val);
|
|
506
|
+
if (this._isInitialized) {
|
|
507
|
+
this._changeHeight(val);
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
configurable: true,
|
|
511
|
+
enumerable: true
|
|
512
|
+
});
|
|
513
|
+
// Expose public synchronous methods on element for MapML compatibility
|
|
514
|
+
Object.defineProperty(this.el, 'zoomTo', {
|
|
515
|
+
value: (lat, lon, zoom) => this.zoomTo(lat, lon, zoom),
|
|
516
|
+
writable: true,
|
|
517
|
+
configurable: true
|
|
518
|
+
});
|
|
519
|
+
Object.defineProperty(this.el, 'zoomToExtent', {
|
|
520
|
+
value: (west, south, east, north) => this.zoomToExtent(west, south, east, north),
|
|
521
|
+
writable: true,
|
|
522
|
+
configurable: true
|
|
523
|
+
});
|
|
524
|
+
Object.defineProperty(this.el, 'back', {
|
|
525
|
+
value: () => this.back(),
|
|
526
|
+
writable: true,
|
|
527
|
+
configurable: true
|
|
528
|
+
});
|
|
529
|
+
Object.defineProperty(this.el, 'forward', {
|
|
530
|
+
value: () => this.forward(),
|
|
531
|
+
writable: true,
|
|
532
|
+
configurable: true
|
|
533
|
+
});
|
|
534
|
+
Object.defineProperty(this.el, 'reload', {
|
|
535
|
+
value: () => this.reload(),
|
|
536
|
+
writable: true,
|
|
537
|
+
configurable: true
|
|
538
|
+
});
|
|
539
|
+
Object.defineProperty(this.el, 'toggleDebug', {
|
|
540
|
+
value: () => this.toggleDebug(),
|
|
541
|
+
writable: true,
|
|
542
|
+
configurable: true
|
|
543
|
+
});
|
|
544
|
+
Object.defineProperty(this.el, 'viewSource', {
|
|
545
|
+
value: () => this.viewSource(),
|
|
546
|
+
writable: true,
|
|
547
|
+
configurable: true
|
|
548
|
+
});
|
|
549
|
+
// Expose matchMedia method with proper 'this' binding
|
|
550
|
+
// This ensures 'this' always refers to the custom element when called
|
|
551
|
+
Object.defineProperty(this.el, 'matchMedia', {
|
|
552
|
+
value: (...args) => matchMedia.apply(this.el, args),
|
|
553
|
+
writable: true,
|
|
554
|
+
configurable: true
|
|
555
|
+
});
|
|
556
|
+
// Expose geojson2mapml method
|
|
557
|
+
Object.defineProperty(this.el, 'geojson2mapml', {
|
|
558
|
+
value: (json, options) => this.geojson2mapml(json, options),
|
|
559
|
+
writable: true,
|
|
560
|
+
configurable: true
|
|
561
|
+
});
|
|
562
|
+
Object.defineProperty(this.el, 'defineCustomProjection', {
|
|
563
|
+
value: (jsonTemplate) => this.defineCustomProjection(jsonTemplate),
|
|
564
|
+
writable: true,
|
|
565
|
+
configurable: true
|
|
566
|
+
});
|
|
567
|
+
// Expose internal methods needed by MapML controls and context menu items
|
|
568
|
+
this.el._toggleFullScreen = () => this._toggleFullScreen();
|
|
569
|
+
this.el._toggleControls = () => this._toggleControls();
|
|
570
|
+
this._addToHistory();
|
|
571
|
+
this._createControls();
|
|
572
|
+
this._toggleControls();
|
|
573
|
+
this._crosshair = crosshair().addTo(this._map);
|
|
574
|
+
if (window.M.options.featureIndexOverlayOption)
|
|
575
|
+
this._featureIndexOverlay = featureIndexOverlay().addTo(this._map);
|
|
576
|
+
this._setUpEvents();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
disconnectedCallback() {
|
|
580
|
+
this._removeEvents();
|
|
581
|
+
// Clean up attribute observer
|
|
582
|
+
if (this.el._attributeObserver) {
|
|
583
|
+
this.el._attributeObserver.disconnect();
|
|
584
|
+
delete this.el._attributeObserver;
|
|
585
|
+
}
|
|
586
|
+
delete this._map;
|
|
587
|
+
this._deleteControls();
|
|
588
|
+
}
|
|
589
|
+
// Helper methods that mirror the original
|
|
590
|
+
async _ensureControlsLoaded() {
|
|
591
|
+
// Force MapML control modules to load and register their init hooks
|
|
592
|
+
// This ensures attribution and other controls work properly
|
|
593
|
+
try {
|
|
594
|
+
// needed because attributionButton is auto-added via Map.addInitHook and
|
|
595
|
+
// if it's not referenced by code, the bundler will omit it automatically
|
|
596
|
+
await import('../utils/mapml/control/AttributionButton.js');
|
|
597
|
+
// Load ContextMenu handler to register init hooks
|
|
598
|
+
await import('../utils/mapml/handlers/ContextMenu.js');
|
|
599
|
+
await import('../utils/mapml/handlers/AnnounceMovement.js');
|
|
600
|
+
await import('../utils/mapml/handlers/keyboard.js');
|
|
601
|
+
// Load FeatureIndex handler to register init hooks for keyboard navigation
|
|
602
|
+
await import('../utils/mapml/handlers/FeatureIndex.js');
|
|
603
|
+
// TODO: other controls if needed
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
console.error('Failed to load MapML controls:', error);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// Creates All map controls and adds them to the map, when created.
|
|
610
|
+
_createControls() {
|
|
611
|
+
let mapSize = this._map.getSize().y, totalSize = 0;
|
|
612
|
+
this._layerControl = layerControl(null, {
|
|
613
|
+
collapsed: true,
|
|
614
|
+
mapEl: this.el
|
|
615
|
+
}).addTo(this._map);
|
|
616
|
+
this._map.on('movestart', this._layerControl.collapse, this._layerControl);
|
|
617
|
+
// Expose on element for MapML compatibility
|
|
618
|
+
this.el._layerControl = this._layerControl;
|
|
619
|
+
let scaleValue = window.M.options.announceScale;
|
|
620
|
+
if (scaleValue === 'metric') {
|
|
621
|
+
scaleValue = { metric: true, imperial: false };
|
|
622
|
+
}
|
|
623
|
+
if (scaleValue === 'imperial') {
|
|
624
|
+
scaleValue = { metric: false, imperial: true };
|
|
625
|
+
}
|
|
626
|
+
if (!this._scaleBar) {
|
|
627
|
+
this._scaleBar = scaleBar(scaleValue).addTo(this._map);
|
|
628
|
+
// Expose on element for MapML compatibility
|
|
629
|
+
this.el._scaleBar = this._scaleBar;
|
|
630
|
+
}
|
|
631
|
+
// Only add controls if there is enough top left vertical space
|
|
632
|
+
if (!this._zoomControl && totalSize + 93 <= mapSize) {
|
|
633
|
+
totalSize += 93;
|
|
634
|
+
this._zoomControl = control
|
|
635
|
+
.zoom({
|
|
636
|
+
zoomInTitle: this.locale.btnZoomIn,
|
|
637
|
+
zoomOutTitle: this.locale.btnZoomOut
|
|
638
|
+
})
|
|
639
|
+
.addTo(this._map);
|
|
640
|
+
// Expose on element for MapML compatibility
|
|
641
|
+
this.el._zoomControl = this._zoomControl;
|
|
642
|
+
}
|
|
643
|
+
if (!this._searchButton) {
|
|
644
|
+
// Note: search is opt-in (default hidden) so it occupies no
|
|
645
|
+
// vertical space until enabled by controlslist="search"; do not
|
|
646
|
+
// charge it against the mapSize budget here.
|
|
647
|
+
this._searchButton = searchButton({ mapEl: this.el }).addTo(this._map);
|
|
648
|
+
// Expose on element for MapML compatibility
|
|
649
|
+
this.el._searchButton = this._searchButton;
|
|
650
|
+
}
|
|
651
|
+
if (!this._reloadButton && totalSize + 49 <= mapSize) {
|
|
652
|
+
totalSize += 49;
|
|
653
|
+
this._reloadButton = reloadButton().addTo(this._map);
|
|
654
|
+
// Expose on element for MapML compatibility
|
|
655
|
+
this.el._reloadButton = this._reloadButton;
|
|
656
|
+
}
|
|
657
|
+
if (!this._fullScreenControl && totalSize + 49 <= mapSize) {
|
|
658
|
+
totalSize += 49;
|
|
659
|
+
this._fullScreenControl = fullscreenButton().addTo(this._map);
|
|
660
|
+
// Expose on element for MapML compatibility
|
|
661
|
+
this.el._fullScreenControl = this._fullScreenControl;
|
|
662
|
+
}
|
|
663
|
+
if (!this._geolocationButton) {
|
|
664
|
+
this._geolocationButton = geolocationButton().addTo(this._map);
|
|
665
|
+
// Expose on element for MapML compatibility
|
|
666
|
+
this.el._geolocationButton = this._geolocationButton;
|
|
667
|
+
}
|
|
668
|
+
// Expose locate method on element for MapML compatibility
|
|
669
|
+
this.el.locate = this.locate.bind(this);
|
|
670
|
+
}
|
|
671
|
+
// Sets controls by hiding/unhiding them based on the map attribute
|
|
672
|
+
_toggleControls() {
|
|
673
|
+
if (this.controls === false) {
|
|
674
|
+
this._hideControls();
|
|
675
|
+
this._map.contextMenu.toggleContextMenuItem('Controls', 'disabled');
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
this._showControls();
|
|
679
|
+
this._map.contextMenu.toggleContextMenuItem('Controls', 'enabled');
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
_hideControls() {
|
|
683
|
+
this._setControlsVisibility('search', true);
|
|
684
|
+
this._setControlsVisibility('fullscreen', true);
|
|
685
|
+
this._setControlsVisibility('layercontrol', true);
|
|
686
|
+
this._setControlsVisibility('reload', true);
|
|
687
|
+
this._setControlsVisibility('zoom', true);
|
|
688
|
+
this._setControlsVisibility('geolocation', true);
|
|
689
|
+
this._setControlsVisibility('scale', true);
|
|
690
|
+
}
|
|
691
|
+
_showControls() {
|
|
692
|
+
this._setControlsVisibility('search', true);
|
|
693
|
+
this._setControlsVisibility('fullscreen', false);
|
|
694
|
+
this._setControlsVisibility('layercontrol', false);
|
|
695
|
+
this._setControlsVisibility('reload', false);
|
|
696
|
+
this._setControlsVisibility('zoom', false);
|
|
697
|
+
this._setControlsVisibility('geolocation', true);
|
|
698
|
+
this._setControlsVisibility('scale', false);
|
|
699
|
+
// prune the controls shown if necessary
|
|
700
|
+
// this logic could be embedded in _showControls
|
|
701
|
+
// but would require being able to iterate the domain of supported tokens
|
|
702
|
+
// for the controlslist
|
|
703
|
+
if (this._controlsList) {
|
|
704
|
+
this._controlsList.forEach((value) => {
|
|
705
|
+
switch (value.toLowerCase()) {
|
|
706
|
+
case 'nofullscreen':
|
|
707
|
+
this._setControlsVisibility('fullscreen', true);
|
|
708
|
+
break;
|
|
709
|
+
case 'nolayer':
|
|
710
|
+
this._setControlsVisibility('layercontrol', true);
|
|
711
|
+
break;
|
|
712
|
+
case 'noreload':
|
|
713
|
+
this._setControlsVisibility('reload', true);
|
|
714
|
+
break;
|
|
715
|
+
case 'nozoom':
|
|
716
|
+
this._setControlsVisibility('zoom', true);
|
|
717
|
+
break;
|
|
718
|
+
case 'geolocation':
|
|
719
|
+
this._setControlsVisibility('geolocation', false);
|
|
720
|
+
break;
|
|
721
|
+
case 'search':
|
|
722
|
+
this._setControlsVisibility('search', false);
|
|
723
|
+
break;
|
|
724
|
+
case 'noscale':
|
|
725
|
+
this._setControlsVisibility('scale', true);
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
// Hide layer control if no layers (will be uncommented when layer control is implemented)
|
|
731
|
+
if (this._layerControl && this._layerControl._layers.length === 0) {
|
|
732
|
+
this._layerControl._container.setAttribute('hidden', '');
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
// delete the map controls that are private properties of this custom element
|
|
736
|
+
_deleteControls() {
|
|
737
|
+
delete this._searchButton;
|
|
738
|
+
delete this._layerControl;
|
|
739
|
+
delete this._zoomControl;
|
|
740
|
+
delete this._reloadButton;
|
|
741
|
+
delete this._fullScreenControl;
|
|
742
|
+
delete this._geolocationButton;
|
|
743
|
+
delete this._scaleBar;
|
|
744
|
+
}
|
|
745
|
+
// Sets the control's visibility AND all its childrens visibility,
|
|
746
|
+
// for the control element based on the Boolean hide parameter
|
|
747
|
+
_setControlsVisibility(control, hide) {
|
|
748
|
+
let container;
|
|
749
|
+
switch (control) {
|
|
750
|
+
case 'search':
|
|
751
|
+
if (this._searchButton) {
|
|
752
|
+
container = this._searchButton._container;
|
|
753
|
+
}
|
|
754
|
+
break;
|
|
755
|
+
case 'zoom':
|
|
756
|
+
if (this._zoomControl) {
|
|
757
|
+
container = this._zoomControl._container;
|
|
758
|
+
}
|
|
759
|
+
break;
|
|
760
|
+
case 'reload':
|
|
761
|
+
if (this._reloadButton) {
|
|
762
|
+
container = this._reloadButton._container;
|
|
763
|
+
}
|
|
764
|
+
break;
|
|
765
|
+
case 'fullscreen':
|
|
766
|
+
if (this._fullScreenControl) {
|
|
767
|
+
container = this._fullScreenControl._container;
|
|
768
|
+
}
|
|
769
|
+
break;
|
|
770
|
+
case 'layercontrol':
|
|
771
|
+
if (this._layerControl) {
|
|
772
|
+
container = this._layerControl._container;
|
|
773
|
+
}
|
|
774
|
+
break;
|
|
775
|
+
case 'geolocation':
|
|
776
|
+
if (this._geolocationButton) {
|
|
777
|
+
container = this._geolocationButton._container;
|
|
778
|
+
}
|
|
779
|
+
break;
|
|
780
|
+
case 'scale':
|
|
781
|
+
if (this._scaleBar) {
|
|
782
|
+
container = this._scaleBar._container;
|
|
783
|
+
}
|
|
784
|
+
break;
|
|
785
|
+
}
|
|
786
|
+
if (container) {
|
|
787
|
+
if (hide) {
|
|
788
|
+
// setting the visibility for all the children of the element
|
|
789
|
+
[...container.children].forEach((childEl) => {
|
|
790
|
+
childEl.setAttribute('hidden', '');
|
|
791
|
+
});
|
|
792
|
+
container.setAttribute('hidden', '');
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
// setting the visibility for all the children of the element
|
|
796
|
+
[...container.children].forEach((childEl) => {
|
|
797
|
+
childEl.removeAttribute('hidden');
|
|
798
|
+
});
|
|
799
|
+
container.removeAttribute('hidden');
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
_toggleStatic() {
|
|
804
|
+
// Mirror the original mapml-viewer _toggleStatic behavior
|
|
805
|
+
if (this._map) {
|
|
806
|
+
if (this.static) {
|
|
807
|
+
this._map.dragging.disable();
|
|
808
|
+
this._map.touchZoom.disable();
|
|
809
|
+
this._map.doubleClickZoom.disable();
|
|
810
|
+
this._map.scrollWheelZoom.disable();
|
|
811
|
+
this._map.boxZoom.disable();
|
|
812
|
+
this._map.keyboard.disable();
|
|
813
|
+
this._zoomControl.disable();
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
this._map.dragging.enable();
|
|
817
|
+
this._map.touchZoom.enable();
|
|
818
|
+
this._map.doubleClickZoom.enable();
|
|
819
|
+
this._map.scrollWheelZoom.enable();
|
|
820
|
+
this._map.boxZoom.enable();
|
|
821
|
+
this._map.keyboard.enable();
|
|
822
|
+
this._zoomControl.enable();
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
_removeEvents() {
|
|
827
|
+
if (this._map) {
|
|
828
|
+
this._map.off();
|
|
829
|
+
}
|
|
830
|
+
if (this._boundDropHandler) {
|
|
831
|
+
this.el.removeEventListener('drop', this._boundDropHandler, false);
|
|
832
|
+
}
|
|
833
|
+
if (this._boundDragoverHandler) {
|
|
834
|
+
this.el.removeEventListener('dragover', this._boundDragoverHandler, false);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
_setUpEvents() {
|
|
838
|
+
// Store bound handlers for cleanup
|
|
839
|
+
this._boundDropHandler = this._dropHandler.bind(this);
|
|
840
|
+
this._boundDragoverHandler = this._dragoverHandler.bind(this);
|
|
841
|
+
// Set up drag and drop handlers for layers, geojson, and mapml URLs
|
|
842
|
+
this.el.addEventListener('drop', this._boundDropHandler, false);
|
|
843
|
+
this.el.addEventListener('dragover', this._boundDragoverHandler, false);
|
|
844
|
+
// Set up map event handlers to sync with component props
|
|
845
|
+
this._map.on('moveend', function () {
|
|
846
|
+
this._updateMapCenter();
|
|
847
|
+
this._addToHistory();
|
|
848
|
+
this.el.dispatchEvent(new CustomEvent('map-moveend', { detail: { target: this } }));
|
|
849
|
+
}, this);
|
|
850
|
+
this._map.on('zoom', function () {
|
|
851
|
+
this.el.dispatchEvent(new CustomEvent('map-zoom', { detail: { target: this } }));
|
|
852
|
+
}, this);
|
|
853
|
+
this._map.on('zoomend', function () {
|
|
854
|
+
this._updateMapCenter();
|
|
855
|
+
this.el.dispatchEvent(new CustomEvent('zoomend', { detail: { target: this } }));
|
|
856
|
+
}, this);
|
|
857
|
+
// Forward geolocation events from Leaflet to custom events
|
|
858
|
+
this._map.on('locationfound', function (e) {
|
|
859
|
+
this.el.dispatchEvent(new CustomEvent('maplocationfound', {
|
|
860
|
+
detail: { latlng: e.latlng, accuracy: e.accuracy }
|
|
861
|
+
}));
|
|
862
|
+
}, this);
|
|
863
|
+
this._map.on('locationerror', function (e) {
|
|
864
|
+
this.el.dispatchEvent(new CustomEvent('maplocationerror', {
|
|
865
|
+
detail: { message: e.message, code: e.code }
|
|
866
|
+
}));
|
|
867
|
+
}, this);
|
|
868
|
+
// Set up zoom bounds management based on layer extents
|
|
869
|
+
const setMapMinAndMaxZoom = ((e) => {
|
|
870
|
+
this.whenLayersReady().then(() => {
|
|
871
|
+
if (e && e.layer._layerEl) {
|
|
872
|
+
this._map.setMaxZoom(this.extent.zoom.maxZoom);
|
|
873
|
+
this._map.setMinZoom(this.extent.zoom.minZoom);
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
}).bind(this);
|
|
877
|
+
this.whenLayersReady().then(() => {
|
|
878
|
+
this._map.setMaxZoom(this.extent.zoom.maxZoom);
|
|
879
|
+
this._map.setMinZoom(this.extent.zoom.minZoom);
|
|
880
|
+
this._map.on('layeradd layerremove', setMapMinAndMaxZoom, this);
|
|
881
|
+
});
|
|
882
|
+
// Handle Ctrl+V paste for layers, links and geojson
|
|
883
|
+
this.el.addEventListener('keydown', (e) => {
|
|
884
|
+
if (e.keyCode === 86 && e.ctrlKey) {
|
|
885
|
+
navigator.clipboard.readText().then((layer) => {
|
|
886
|
+
Util._pasteLayer(this.el, layer);
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
else if (e.keyCode === 32 &&
|
|
890
|
+
this.el.shadowRoot.activeElement?.nodeName !== 'INPUT') {
|
|
891
|
+
// Prevent default spacebar event on map
|
|
892
|
+
e.preventDefault();
|
|
893
|
+
this._map.fire('keypress', { originalEvent: e });
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
_dropHandler(event) {
|
|
898
|
+
event.preventDefault();
|
|
899
|
+
let text = event.dataTransfer.getData('text');
|
|
900
|
+
Util._pasteLayer(this.el, text);
|
|
901
|
+
}
|
|
902
|
+
_dragoverHandler(event) {
|
|
903
|
+
event.preventDefault();
|
|
904
|
+
event.dataTransfer.dropEffect = 'copy';
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Toggle debug overlay on the map
|
|
908
|
+
*/
|
|
909
|
+
toggleDebug() {
|
|
910
|
+
if (this._debug) {
|
|
911
|
+
this._debug.remove();
|
|
912
|
+
this._debug = undefined;
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
this._debug = debugOverlay().addTo(this._map);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
locate(options) {
|
|
919
|
+
//options: https://leafletjs.com/reference.html#locate-options
|
|
920
|
+
if (this._geolocationButton) {
|
|
921
|
+
this._geolocationButton.stop();
|
|
922
|
+
}
|
|
923
|
+
if (options) {
|
|
924
|
+
if (options.zoomTo) {
|
|
925
|
+
options.setView = options.zoomTo;
|
|
926
|
+
delete options.zoomTo;
|
|
927
|
+
}
|
|
928
|
+
this._map.locate(options);
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
this._map.locate({ setView: true, maxZoom: 16 });
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
_changeWidth(width) {
|
|
935
|
+
// Match mapml-viewer: modify the :host CSS rule, not inline styles
|
|
936
|
+
// This allows light DOM CSS to override the shadow DOM default
|
|
937
|
+
if (this._container) {
|
|
938
|
+
this._container.style.width = width + 'px';
|
|
939
|
+
// Modify the :host rule (always LAST stylesheet, first rule)
|
|
940
|
+
const sheets = this.el.shadowRoot.styleSheets;
|
|
941
|
+
if (sheets.length > 0) {
|
|
942
|
+
sheets[sheets.length - 1].cssRules[0].style.width = width + 'px';
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
if (this._map) {
|
|
946
|
+
this._map.invalidateSize(false);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
_changeHeight(height) {
|
|
950
|
+
// Match mapml-viewer: modify the :host CSS rule, not inline styles
|
|
951
|
+
// This allows light DOM CSS to override the shadow DOM default
|
|
952
|
+
if (this._container) {
|
|
953
|
+
this._container.style.height = height + 'px';
|
|
954
|
+
// Modify the :host rule (always LAST stylesheet, first rule)
|
|
955
|
+
const sheets = this.el.shadowRoot.styleSheets;
|
|
956
|
+
if (sheets.length > 0) {
|
|
957
|
+
sheets[sheets.length - 1].cssRules[0].style.height = height + 'px';
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (this._map) {
|
|
961
|
+
this._map.invalidateSize(false);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
_updateMapCenter() {
|
|
965
|
+
// Update component props to match map state and sync to DOM attributes
|
|
966
|
+
// Note: Stencil mutable props don't automatically reflect changes back to DOM attributes
|
|
967
|
+
if (this._map) {
|
|
968
|
+
const center = this._map.getCenter();
|
|
969
|
+
this.lat = center.lat;
|
|
970
|
+
this.lon = center.lng;
|
|
971
|
+
this.zoom = this._map.getZoom();
|
|
972
|
+
// Manually sync the props back to DOM attributes
|
|
973
|
+
this.el.setAttribute('lat', this.lat.toString());
|
|
974
|
+
this.el.setAttribute('lon', this.lon.toString());
|
|
975
|
+
this.el.setAttribute('zoom', this.zoom.toString());
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
_resetHistory() {
|
|
979
|
+
this._history = [];
|
|
980
|
+
this._historyIndex = -1;
|
|
981
|
+
this._traversalCall = false;
|
|
982
|
+
// weird but ok (original comment)
|
|
983
|
+
this._addToHistory();
|
|
984
|
+
}
|
|
985
|
+
_addToHistory() {
|
|
986
|
+
// this._traversalCall tracks how many consecutive moveends to ignore from history
|
|
987
|
+
// Check if we should ignore this moveend event due to programmatic navigation
|
|
988
|
+
if (this._traversalCall && this._traversalCall > 0) {
|
|
989
|
+
this._traversalCall--;
|
|
990
|
+
return; // Don't add to history during back/forward/reload operations
|
|
991
|
+
}
|
|
992
|
+
let mapLocation = this._map.getPixelBounds().getCenter();
|
|
993
|
+
let location = {
|
|
994
|
+
zoom: this._map.getZoom(),
|
|
995
|
+
x: mapLocation.x,
|
|
996
|
+
y: mapLocation.y
|
|
997
|
+
};
|
|
998
|
+
this._historyIndex++;
|
|
999
|
+
this._history.splice(this._historyIndex, 0, location);
|
|
1000
|
+
// Remove future history when adding new location while in middle of history
|
|
1001
|
+
if (this._historyIndex + 1 !== this._history.length) {
|
|
1002
|
+
this._history.length = this._historyIndex + 1;
|
|
1003
|
+
}
|
|
1004
|
+
// Update context menu button states based on history position
|
|
1005
|
+
this._updateNavigationControls();
|
|
1006
|
+
// Sync updated history properties to element for MapML controls
|
|
1007
|
+
this.el._history = this._history;
|
|
1008
|
+
this.el._historyIndex = this._historyIndex;
|
|
1009
|
+
}
|
|
1010
|
+
_updateNavigationControls() {
|
|
1011
|
+
// Centralize navigation control state management
|
|
1012
|
+
const canGoBack = this._historyIndex > 0;
|
|
1013
|
+
const canGoForward = this._historyIndex < this._history.length - 1;
|
|
1014
|
+
const canReload = this._historyIndex > 0;
|
|
1015
|
+
// Update context menu items
|
|
1016
|
+
this._map.contextMenu.toggleContextMenuItem('Back', canGoBack ? 'enabled' : 'disabled');
|
|
1017
|
+
this._map.contextMenu.toggleContextMenuItem('Forward', canGoForward ? 'enabled' : 'disabled');
|
|
1018
|
+
this._map.contextMenu.toggleContextMenuItem('Reload', canReload ? 'enabled' : 'disabled');
|
|
1019
|
+
// Update reload button
|
|
1020
|
+
if (canReload) {
|
|
1021
|
+
this._reloadButton?.enable();
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
this._reloadButton?.disable();
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Navigate back in map history
|
|
1029
|
+
*/
|
|
1030
|
+
back() {
|
|
1031
|
+
if (this._historyIndex <= 0)
|
|
1032
|
+
return;
|
|
1033
|
+
let curr = this._history[this._historyIndex];
|
|
1034
|
+
this._historyIndex--;
|
|
1035
|
+
let prev = this._history[this._historyIndex];
|
|
1036
|
+
// Set traversal call count based on operations needed
|
|
1037
|
+
if (prev.zoom !== curr.zoom) {
|
|
1038
|
+
this._traversalCall = 2; // panBy + setZoom
|
|
1039
|
+
let currScale = this._map.options.crs.scale(curr.zoom);
|
|
1040
|
+
let prevScale = this._map.options.crs.scale(prev.zoom);
|
|
1041
|
+
let scale = currScale / prevScale;
|
|
1042
|
+
this._map.panBy([prev.x * scale - curr.x, prev.y * scale - curr.y], { animate: false });
|
|
1043
|
+
this._map.setZoom(prev.zoom);
|
|
1044
|
+
}
|
|
1045
|
+
else {
|
|
1046
|
+
this._traversalCall = 1; // panBy only
|
|
1047
|
+
this._map.panBy([prev.x - curr.x, prev.y - curr.y]);
|
|
1048
|
+
}
|
|
1049
|
+
// Update controls immediately (don't wait for moveend)
|
|
1050
|
+
this._updateNavigationControls();
|
|
1051
|
+
// Sync to element
|
|
1052
|
+
this.el._historyIndex = this._historyIndex;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Allows user to move forward in history
|
|
1056
|
+
*/
|
|
1057
|
+
forward() {
|
|
1058
|
+
let history = this._history;
|
|
1059
|
+
let curr = history[this._historyIndex];
|
|
1060
|
+
if (this._historyIndex < history.length - 1) {
|
|
1061
|
+
this._map.contextMenu.toggleContextMenuItem('Back', 'enabled');
|
|
1062
|
+
this._historyIndex++;
|
|
1063
|
+
let next = history[this._historyIndex];
|
|
1064
|
+
// Disable forward contextmenu item when at the end of history
|
|
1065
|
+
if (this._historyIndex === history.length - 1) {
|
|
1066
|
+
this._map.contextMenu.toggleContextMenuItem('Forward', 'disabled');
|
|
1067
|
+
}
|
|
1068
|
+
if (next.zoom !== curr.zoom) {
|
|
1069
|
+
this._traversalCall = 2;
|
|
1070
|
+
let currScale = this._map.options.crs.scale(curr.zoom);
|
|
1071
|
+
let nextScale = this._map.options.crs.scale(next.zoom);
|
|
1072
|
+
let scale = currScale / nextScale;
|
|
1073
|
+
this._map.panBy([next.x * scale - curr.x, next.y * scale - curr.y], { animate: false });
|
|
1074
|
+
this._map.setZoom(next.zoom);
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
this._traversalCall = 1;
|
|
1078
|
+
this._map.panBy([next.x - curr.x, next.y - curr.y]);
|
|
1079
|
+
}
|
|
1080
|
+
// Update controls immediately (don't wait for moveend)
|
|
1081
|
+
this._updateNavigationControls();
|
|
1082
|
+
// Sync to element
|
|
1083
|
+
this.el._historyIndex = this._historyIndex;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Allows the user to reload/reset the map's location to its initial location
|
|
1088
|
+
* and reset the history to the initial state
|
|
1089
|
+
*/
|
|
1090
|
+
reload() {
|
|
1091
|
+
if (this._history.length === 0)
|
|
1092
|
+
return;
|
|
1093
|
+
let initialLocation = this._history[0]; // Get initial location
|
|
1094
|
+
let curr = {
|
|
1095
|
+
zoom: this._map.getZoom(),
|
|
1096
|
+
x: this._map.getPixelBounds().getCenter().x,
|
|
1097
|
+
y: this._map.getPixelBounds().getCenter().y
|
|
1098
|
+
};
|
|
1099
|
+
// Reset history completely - this is the key change
|
|
1100
|
+
this._history = [initialLocation]; // Keep only the initial location
|
|
1101
|
+
this._historyIndex = 0; // Set to the only remaining entry
|
|
1102
|
+
// Set traversal call count based on operations needed
|
|
1103
|
+
if (initialLocation.zoom !== curr.zoom) {
|
|
1104
|
+
this._traversalCall = 2; // panBy + setZoom
|
|
1105
|
+
let currScale = this._map.options.crs.scale(curr.zoom);
|
|
1106
|
+
let initScale = this._map.options.crs.scale(initialLocation.zoom);
|
|
1107
|
+
let scale = currScale / initScale;
|
|
1108
|
+
this._map.panBy([initialLocation.x * scale - curr.x, initialLocation.y * scale - curr.y], { animate: false });
|
|
1109
|
+
this._map.setZoom(initialLocation.zoom);
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
this._traversalCall = 1; // panBy only
|
|
1113
|
+
this._map.panBy([initialLocation.x - curr.x, initialLocation.y - curr.y]);
|
|
1114
|
+
}
|
|
1115
|
+
// Update controls immediately - now with reset history state
|
|
1116
|
+
this._updateNavigationControls();
|
|
1117
|
+
// Sync reset history to element
|
|
1118
|
+
this.el._history = this._history;
|
|
1119
|
+
this.el._historyIndex = this._historyIndex;
|
|
1120
|
+
this._map.getContainer().focus();
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Internal method to toggle fullscreen (used by MapML context menu)
|
|
1124
|
+
*/
|
|
1125
|
+
_toggleFullScreen() {
|
|
1126
|
+
this._map.toggleFullscreen();
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Open the map source in a new window
|
|
1130
|
+
*/
|
|
1131
|
+
viewSource() {
|
|
1132
|
+
let blob = new Blob([this._source], { type: 'text/plain' }), url = URL.createObjectURL(blob);
|
|
1133
|
+
window.open(url);
|
|
1134
|
+
URL.revokeObjectURL(url);
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Zoom the map to a specific location and zoom level
|
|
1138
|
+
* @param lat - Latitude coordinate
|
|
1139
|
+
* @param lon - Longitude coordinate
|
|
1140
|
+
* @param zoom - Zoom level (optional, defaults to current zoom)
|
|
1141
|
+
*/
|
|
1142
|
+
zoomToExtent(west, south, east, north) {
|
|
1143
|
+
if (!this._map) {
|
|
1144
|
+
console.warn('Map is not initialized. Cannot zoom to extent.');
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
this._map.fitBounds(latLngBounds([+south, +west], [+north, +east]));
|
|
1148
|
+
this._updateMapCenter();
|
|
1149
|
+
}
|
|
1150
|
+
zoomTo(lat, lon, zoom) {
|
|
1151
|
+
// Ensure map is initialized before attempting to zoom
|
|
1152
|
+
if (!this._map) {
|
|
1153
|
+
console.warn('Map is not initialized. Cannot zoom to location.');
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
// Convert zoom to number if provided, otherwise use current zoom
|
|
1157
|
+
const targetZoom = (zoom !== undefined && Number.isInteger(+zoom)) ? +zoom : this.zoom;
|
|
1158
|
+
// Create LatLng object for the target location
|
|
1159
|
+
const location = new LatLng(+lat, +lon);
|
|
1160
|
+
// Set the map view to the new location and zoom
|
|
1161
|
+
this._map.setView(location, targetZoom);
|
|
1162
|
+
// Update the component properties to reflect the new state
|
|
1163
|
+
// This matches the behavior in the original mapml-viewer.js
|
|
1164
|
+
// this.zoom = targetZoom;
|
|
1165
|
+
// this.lat = location.lat;
|
|
1166
|
+
// this.lon = location.lng;
|
|
1167
|
+
// The moveend event will fire automatically and:
|
|
1168
|
+
// 1. Call _updateMapCenter() to sync lat/lon/zoom props
|
|
1169
|
+
// 2. Call _addToHistory() to update the history stack
|
|
1170
|
+
// 3. Update context menu button states
|
|
1171
|
+
}
|
|
1172
|
+
async whenProjectionDefined(projection) {
|
|
1173
|
+
// Mirror the original whenProjectionDefined logic
|
|
1174
|
+
return new Promise((resolve, reject) => {
|
|
1175
|
+
if (window.M[projection]) {
|
|
1176
|
+
resolve(window.M[projection]);
|
|
1177
|
+
}
|
|
1178
|
+
else {
|
|
1179
|
+
reject(new Error('Projection ' + projection + ' is not defined'));
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
defineCustomProjection(jsonTemplate) {
|
|
1184
|
+
// Delegate to the global M.defineCustomProjection API
|
|
1185
|
+
if (window.M && window.M.defineCustomProjection) {
|
|
1186
|
+
window.M.defineCustomProjection(jsonTemplate);
|
|
1187
|
+
const t = JSON.parse(jsonTemplate);
|
|
1188
|
+
return t.projection;
|
|
1189
|
+
}
|
|
1190
|
+
else {
|
|
1191
|
+
throw new Error('MapML API not loaded');
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Promise-based method to wait until map is ready
|
|
1196
|
+
* Returns a promise that resolves when the map is fully initialized
|
|
1197
|
+
*/
|
|
1198
|
+
async whenReady() {
|
|
1199
|
+
return new Promise((resolve, reject) => {
|
|
1200
|
+
let interval, failureTimer;
|
|
1201
|
+
if (this.el._map) {
|
|
1202
|
+
resolve();
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
let viewer = this.el;
|
|
1206
|
+
interval = setInterval(testForMap, 200, viewer);
|
|
1207
|
+
failureTimer = setTimeout(mapNotDefined, 5000);
|
|
1208
|
+
}
|
|
1209
|
+
function testForMap(viewer) {
|
|
1210
|
+
if (viewer._map) {
|
|
1211
|
+
clearInterval(interval);
|
|
1212
|
+
clearTimeout(failureTimer);
|
|
1213
|
+
resolve();
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function mapNotDefined() {
|
|
1217
|
+
clearInterval(interval);
|
|
1218
|
+
clearTimeout(failureTimer);
|
|
1219
|
+
reject('Timeout reached waiting for map to be ready');
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Promise-based method to wait until all layers are ready
|
|
1225
|
+
* Returns a promise that resolves when all child layers are fully initialized
|
|
1226
|
+
*/
|
|
1227
|
+
async whenLayersReady() {
|
|
1228
|
+
let layersReady = [];
|
|
1229
|
+
// Get all map-layer child elements
|
|
1230
|
+
const layers = this.el.querySelectorAll('map-layer');
|
|
1231
|
+
for (let i = 0; i < layers.length; i++) {
|
|
1232
|
+
const layer = layers[i];
|
|
1233
|
+
if (layer.whenReady) {
|
|
1234
|
+
layersReady.push(layer.whenReady());
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
return Promise.allSettled(layersReady);
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Convert GeoJSON to MapML and append as a layer
|
|
1241
|
+
* @param json - GeoJSON object (FeatureCollection, Feature, or Geometry)
|
|
1242
|
+
* @param options - Conversion options:
|
|
1243
|
+
* - label: Layer label (defaults to json.name, json.title, or locale default)
|
|
1244
|
+
* - projection: Target projection (defaults to map's projection)
|
|
1245
|
+
* - caption: Feature caption property name or function
|
|
1246
|
+
* - properties: Custom properties handling (function, string, or HTMLElement)
|
|
1247
|
+
* - geometryFunction: Custom geometry processing function
|
|
1248
|
+
* @returns The created map-layer element
|
|
1249
|
+
*/
|
|
1250
|
+
geojson2mapml(json, options = {}) {
|
|
1251
|
+
// Use current map projection if not specified
|
|
1252
|
+
if (options.projection === undefined) {
|
|
1253
|
+
options.projection = this.projection;
|
|
1254
|
+
}
|
|
1255
|
+
// Call Util.geojson2mapml to create the layer element
|
|
1256
|
+
let geojsonLayer = Util.geojson2mapml(json, options);
|
|
1257
|
+
// Append the layer to the map
|
|
1258
|
+
this.el.appendChild(geojsonLayer);
|
|
1259
|
+
return geojsonLayer;
|
|
1260
|
+
}
|
|
1261
|
+
render() {
|
|
1262
|
+
return null;
|
|
1263
|
+
}
|
|
1264
|
+
static get is() { return "gcds-ext-map"; }
|
|
1265
|
+
static get encapsulation() { return "shadow"; }
|
|
1266
|
+
static get originalStyleUrls() {
|
|
1267
|
+
return {
|
|
1268
|
+
"$": ["gcds-ext-map.css"]
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
static get styleUrls() {
|
|
1272
|
+
return {
|
|
1273
|
+
"$": ["gcds-ext-map.css"]
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
static get properties() {
|
|
1277
|
+
return {
|
|
1278
|
+
"lat": {
|
|
1279
|
+
"type": "number",
|
|
1280
|
+
"mutable": true,
|
|
1281
|
+
"complexType": {
|
|
1282
|
+
"original": "number",
|
|
1283
|
+
"resolved": "number",
|
|
1284
|
+
"references": {}
|
|
1285
|
+
},
|
|
1286
|
+
"required": false,
|
|
1287
|
+
"optional": true,
|
|
1288
|
+
"docs": {
|
|
1289
|
+
"tags": [],
|
|
1290
|
+
"text": ""
|
|
1291
|
+
},
|
|
1292
|
+
"getter": false,
|
|
1293
|
+
"setter": false,
|
|
1294
|
+
"reflect": false,
|
|
1295
|
+
"attribute": "lat",
|
|
1296
|
+
"defaultValue": "0"
|
|
1297
|
+
},
|
|
1298
|
+
"lon": {
|
|
1299
|
+
"type": "number",
|
|
1300
|
+
"mutable": true,
|
|
1301
|
+
"complexType": {
|
|
1302
|
+
"original": "number",
|
|
1303
|
+
"resolved": "number",
|
|
1304
|
+
"references": {}
|
|
1305
|
+
},
|
|
1306
|
+
"required": false,
|
|
1307
|
+
"optional": true,
|
|
1308
|
+
"docs": {
|
|
1309
|
+
"tags": [],
|
|
1310
|
+
"text": ""
|
|
1311
|
+
},
|
|
1312
|
+
"getter": false,
|
|
1313
|
+
"setter": false,
|
|
1314
|
+
"reflect": false,
|
|
1315
|
+
"attribute": "lon",
|
|
1316
|
+
"defaultValue": "0"
|
|
1317
|
+
},
|
|
1318
|
+
"zoom": {
|
|
1319
|
+
"type": "number",
|
|
1320
|
+
"mutable": true,
|
|
1321
|
+
"complexType": {
|
|
1322
|
+
"original": "number",
|
|
1323
|
+
"resolved": "number",
|
|
1324
|
+
"references": {}
|
|
1325
|
+
},
|
|
1326
|
+
"required": false,
|
|
1327
|
+
"optional": true,
|
|
1328
|
+
"docs": {
|
|
1329
|
+
"tags": [],
|
|
1330
|
+
"text": ""
|
|
1331
|
+
},
|
|
1332
|
+
"getter": false,
|
|
1333
|
+
"setter": false,
|
|
1334
|
+
"reflect": false,
|
|
1335
|
+
"attribute": "zoom",
|
|
1336
|
+
"defaultValue": "0"
|
|
1337
|
+
},
|
|
1338
|
+
"projection": {
|
|
1339
|
+
"type": "string",
|
|
1340
|
+
"mutable": true,
|
|
1341
|
+
"complexType": {
|
|
1342
|
+
"original": "string",
|
|
1343
|
+
"resolved": "string",
|
|
1344
|
+
"references": {}
|
|
1345
|
+
},
|
|
1346
|
+
"required": false,
|
|
1347
|
+
"optional": true,
|
|
1348
|
+
"docs": {
|
|
1349
|
+
"tags": [],
|
|
1350
|
+
"text": ""
|
|
1351
|
+
},
|
|
1352
|
+
"getter": false,
|
|
1353
|
+
"setter": false,
|
|
1354
|
+
"reflect": false,
|
|
1355
|
+
"attribute": "projection",
|
|
1356
|
+
"defaultValue": "'OSMTILE'"
|
|
1357
|
+
},
|
|
1358
|
+
"controls": {
|
|
1359
|
+
"type": "boolean",
|
|
1360
|
+
"mutable": false,
|
|
1361
|
+
"complexType": {
|
|
1362
|
+
"original": "boolean",
|
|
1363
|
+
"resolved": "boolean",
|
|
1364
|
+
"references": {}
|
|
1365
|
+
},
|
|
1366
|
+
"required": false,
|
|
1367
|
+
"optional": false,
|
|
1368
|
+
"docs": {
|
|
1369
|
+
"tags": [],
|
|
1370
|
+
"text": ""
|
|
1371
|
+
},
|
|
1372
|
+
"getter": false,
|
|
1373
|
+
"setter": false,
|
|
1374
|
+
"reflect": true,
|
|
1375
|
+
"attribute": "controls",
|
|
1376
|
+
"defaultValue": "false"
|
|
1377
|
+
},
|
|
1378
|
+
"static": {
|
|
1379
|
+
"type": "boolean",
|
|
1380
|
+
"mutable": false,
|
|
1381
|
+
"complexType": {
|
|
1382
|
+
"original": "boolean",
|
|
1383
|
+
"resolved": "boolean",
|
|
1384
|
+
"references": {}
|
|
1385
|
+
},
|
|
1386
|
+
"required": false,
|
|
1387
|
+
"optional": true,
|
|
1388
|
+
"docs": {
|
|
1389
|
+
"tags": [],
|
|
1390
|
+
"text": ""
|
|
1391
|
+
},
|
|
1392
|
+
"getter": false,
|
|
1393
|
+
"setter": false,
|
|
1394
|
+
"reflect": true,
|
|
1395
|
+
"attribute": "static",
|
|
1396
|
+
"defaultValue": "false"
|
|
1397
|
+
},
|
|
1398
|
+
"_controlslist": {
|
|
1399
|
+
"type": "string",
|
|
1400
|
+
"mutable": false,
|
|
1401
|
+
"complexType": {
|
|
1402
|
+
"original": "string",
|
|
1403
|
+
"resolved": "string",
|
|
1404
|
+
"references": {}
|
|
1405
|
+
},
|
|
1406
|
+
"required": false,
|
|
1407
|
+
"optional": true,
|
|
1408
|
+
"docs": {
|
|
1409
|
+
"tags": [],
|
|
1410
|
+
"text": ""
|
|
1411
|
+
},
|
|
1412
|
+
"getter": false,
|
|
1413
|
+
"setter": false,
|
|
1414
|
+
"reflect": true,
|
|
1415
|
+
"attribute": "controlslist"
|
|
1416
|
+
},
|
|
1417
|
+
"locale": {
|
|
1418
|
+
"type": "any",
|
|
1419
|
+
"mutable": true,
|
|
1420
|
+
"complexType": {
|
|
1421
|
+
"original": "any",
|
|
1422
|
+
"resolved": "any",
|
|
1423
|
+
"references": {}
|
|
1424
|
+
},
|
|
1425
|
+
"required": false,
|
|
1426
|
+
"optional": true,
|
|
1427
|
+
"docs": {
|
|
1428
|
+
"tags": [],
|
|
1429
|
+
"text": ""
|
|
1430
|
+
},
|
|
1431
|
+
"getter": false,
|
|
1432
|
+
"setter": false,
|
|
1433
|
+
"reflect": false,
|
|
1434
|
+
"attribute": "locale"
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
static get methods() {
|
|
1439
|
+
return {
|
|
1440
|
+
"whenProjectionDefined": {
|
|
1441
|
+
"complexType": {
|
|
1442
|
+
"signature": "(projection: string) => Promise<unknown>",
|
|
1443
|
+
"parameters": [{
|
|
1444
|
+
"name": "projection",
|
|
1445
|
+
"type": "string",
|
|
1446
|
+
"docs": ""
|
|
1447
|
+
}],
|
|
1448
|
+
"references": {
|
|
1449
|
+
"Promise": {
|
|
1450
|
+
"location": "global",
|
|
1451
|
+
"id": "global::Promise"
|
|
1452
|
+
}
|
|
1453
|
+
},
|
|
1454
|
+
"return": "Promise<unknown>"
|
|
1455
|
+
},
|
|
1456
|
+
"docs": {
|
|
1457
|
+
"text": "",
|
|
1458
|
+
"tags": []
|
|
1459
|
+
}
|
|
1460
|
+
},
|
|
1461
|
+
"whenReady": {
|
|
1462
|
+
"complexType": {
|
|
1463
|
+
"signature": "() => Promise<void>",
|
|
1464
|
+
"parameters": [],
|
|
1465
|
+
"references": {
|
|
1466
|
+
"Promise": {
|
|
1467
|
+
"location": "global",
|
|
1468
|
+
"id": "global::Promise"
|
|
1469
|
+
}
|
|
1470
|
+
},
|
|
1471
|
+
"return": "Promise<void>"
|
|
1472
|
+
},
|
|
1473
|
+
"docs": {
|
|
1474
|
+
"text": "Promise-based method to wait until map is ready\nReturns a promise that resolves when the map is fully initialized",
|
|
1475
|
+
"tags": []
|
|
1476
|
+
}
|
|
1477
|
+
},
|
|
1478
|
+
"whenLayersReady": {
|
|
1479
|
+
"complexType": {
|
|
1480
|
+
"signature": "() => Promise<PromiseSettledResult<void>[]>",
|
|
1481
|
+
"parameters": [],
|
|
1482
|
+
"references": {
|
|
1483
|
+
"Promise": {
|
|
1484
|
+
"location": "global",
|
|
1485
|
+
"id": "global::Promise"
|
|
1486
|
+
},
|
|
1487
|
+
"PromiseSettledResult": {
|
|
1488
|
+
"location": "global",
|
|
1489
|
+
"id": "global::PromiseSettledResult"
|
|
1490
|
+
}
|
|
1491
|
+
},
|
|
1492
|
+
"return": "Promise<PromiseSettledResult<void>[]>"
|
|
1493
|
+
},
|
|
1494
|
+
"docs": {
|
|
1495
|
+
"text": "Promise-based method to wait until all layers are ready\nReturns a promise that resolves when all child layers are fully initialized",
|
|
1496
|
+
"tags": []
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
static get elementRef() { return "el"; }
|
|
1502
|
+
static get watchers() {
|
|
1503
|
+
return [{
|
|
1504
|
+
"propName": "controls",
|
|
1505
|
+
"methodName": "controlsChanged"
|
|
1506
|
+
}, {
|
|
1507
|
+
"propName": "_controlslist",
|
|
1508
|
+
"methodName": "controlsListChanged"
|
|
1509
|
+
}, {
|
|
1510
|
+
"propName": "projection",
|
|
1511
|
+
"methodName": "projectionChanged"
|
|
1512
|
+
}, {
|
|
1513
|
+
"propName": "static",
|
|
1514
|
+
"methodName": "staticChanged"
|
|
1515
|
+
}];
|
|
1516
|
+
}
|
|
1517
|
+
}
|