From 80ba471f4e4c18776f3331e11d6abddf5b1da639 Mon Sep 17 00:00:00 2001 From: Peter Rushforth Date: Thu, 16 Dec 2021 22:44:31 -0500 Subject: [PATCH] Update dist to pre-integrate work from https://github.com/Maps4HTML/Web-Map-Custom-Element/pull/596 Hopefully won't mess up history too badly, should get overwritten when that PR is merged. --- dist/mapml-viewer.js | 1 + dist/mapml.js | 255 +++++++++++++++++++++++++++++++++++-------- dist/mapml.min.js | 2 +- dist/web-map.js | 2 + 4 files changed, 213 insertions(+), 47 deletions(-) diff --git a/dist/mapml-viewer.js b/dist/mapml-viewer.js index 6df2915..965fcf0 100644 --- a/dist/mapml-viewer.js +++ b/dist/mapml-viewer.js @@ -199,6 +199,7 @@ export class MapViewer extends HTMLElement { query: true, contextMenu: true, announceMovement: M.options.announceMovement, + featureIndex: true, mapEl: this, crs: M[this.projection], zoom: this.zoom, diff --git a/dist/mapml.js b/dist/mapml.js index cefe4ff..f7399c4 100644 --- a/dist/mapml.js +++ b/dist/mapml.js @@ -341,6 +341,7 @@ L.DomUtil.remove(this._container); } L.FeatureGroup.prototype.onRemove.call(this, map); + this._map.featureIndex.cleanIndex(); }, getEvents: function(){ @@ -432,6 +433,8 @@ _resetFeatures : function (zoom){ this.clearLayers(); + // since features are removed and re-added by zoom level, need to clean the feature index before re-adding + if(this._map) this._map.featureIndex.cleanIndex(); if(this._features && this._features[zoom]){ for(let k =0;k < this._features[zoom].length;k++){ this.addLayer(this._features[zoom][k]); @@ -3044,9 +3047,9 @@ mapFocusButton.type = "button"; mapFocusButton.title = "Focus Map"; mapFocusButton.innerHTML = ""; - L.DomEvent.disableClickPropagation(mapFocusButton); - L.DomEvent.on(mapFocusButton, 'click', L.DomEvent.stop); L.DomEvent.on(mapFocusButton, 'click', (e)=>{ + L.DomEvent.stop(e); + map.featureIndex._sortIndex(); map.closePopup(); map._container.focus(); }, popup); @@ -3056,8 +3059,6 @@ previousButton.type = "button"; previousButton.title = "Previous Feature"; previousButton.innerHTML = ""; - L.DomEvent.disableClickPropagation(previousButton); - L.DomEvent.on(previousButton, 'click', L.DomEvent.stop); L.DomEvent.on(previousButton, 'click', layer._previousFeature, popup); // static feature counter that 1/1 @@ -3070,8 +3071,6 @@ nextButton.type = "button"; nextButton.title = "Next Feature"; nextButton.innerHTML = ""; - L.DomEvent.disableClickPropagation(nextButton); - L.DomEvent.on(nextButton, 'click', L.DomEvent.stop); L.DomEvent.on(nextButton, 'click', layer._nextFeature, popup); // creates >| button, focuses map controls @@ -3079,9 +3078,12 @@ controlFocusButton.type = "button"; controlFocusButton.title = "Focus Controls"; controlFocusButton.innerHTML = ""; - L.DomEvent.disableClickPropagation(controlFocusButton); - L.DomEvent.on(controlFocusButton, 'click', L.DomEvent.stop); L.DomEvent.on(controlFocusButton, 'click', (e) => { + map.featureIndex._sortIndex(); + map.featureIndex.currentIndex = map.featureIndex.inBoundFeatures.length - 1; + map.featureIndex.inBoundFeatures[0].path.setAttribute("tabindex", -1); + map.featureIndex.inBoundFeatures[map.featureIndex.currentIndex].path.setAttribute("tabindex", 0); + L.DomEvent.stop(e); map.closePopup(); map._controlContainer.querySelector("A").focus(); }, popup); @@ -3108,9 +3110,11 @@ let isTab = focusEvent.originalEvent.keyCode === 9, shiftPressed = focusEvent.originalEvent.shiftKey; if((path[0].classList.contains("leaflet-popup-close-button") && isTab && !shiftPressed) || focusEvent.originalEvent.keyCode === 27){ - L.DomEvent.stop(focusEvent); - map.closePopup(popup); - group.focus(); + setTimeout(() => { + L.DomEvent.stop(focusEvent); + map.closePopup(popup); + group.focus(); + }, 0); } else if ((path[0].title==="Focus Map" || path[0].classList.contains("mapml-popup-content")) && isTab && shiftPressed){ setTimeout(() => { //timeout needed so focus of the feature is done even after the keypressup event occurs L.DomEvent.stop(focusEvent); @@ -4962,6 +4966,7 @@ return false; }, + // TODO: should be merged with the 'mapfocused' event emitted by mapml-viewer and map, not trivial _isMapFocused: function (e) { //set this._map.isFocused = true if arrow buttons are used if(!this._map._container.parentNode.activeElement){ @@ -4973,6 +4978,7 @@ this._map.isFocused = false; } else this._map.isFocused = isLeafletContainer && ["keyup", "keydown"].includes(e.type); + if(this._map.isFocused) this._map.fire("mapkeyboardfocused"); this._addOrRemoveMapOutline(); this._addOrRemoveCrosshair(); }, @@ -5270,13 +5276,19 @@ this._coordinateToArrays(span, main, subParts, false, span.getAttribute("class"), parents.concat([span])); } let noSpan = coords.textContent.replace(/(<([^>]+)>)/ig, ''), - pairs = noSpan.match(/(\S+\s+\S+)/gim), local = []; + pairs = noSpan.match(/(\S+\s+\S+)/gim), local = [], bounds; for (let p of pairs) { let numPair = []; p.split(/\s+/gim).forEach(M.parseNumber, numPair); let point = M.pointToPCRSPoint(L.point(numPair), this.options.zoom, this.options.projection, this.options.nativeCS); local.push(point); - this._bounds = this._bounds ? this._bounds.extend(point) : L.bounds(point, point); + bounds = bounds ? bounds.extend(point) : L.bounds(point, point); + } + if (this._bounds) { + this._bounds.extend(bounds.min); + this._bounds.extend(bounds.max); + } else { + this._bounds = bounds; } if (isFirst) { main.push({ points: local }); @@ -5289,6 +5301,7 @@ } subParts.unshift({ points: local, + center: bounds.getCenter(), cls: `${cls || ""} ${wrapperAttr.className || ""}`.trim(), attr: attrMap, link: wrapperAttr.link, @@ -5325,6 +5338,10 @@ if (!this._bounds) return null; return this._map.options.crs.unproject(this._bounds.getCenter()); }, + + getPCRSCenter: function () { + return this._bounds.getCenter(); + }, }); /** @@ -5343,8 +5360,6 @@ * @returns {*} */ var FeatureRenderer = L.SVG.extend({ - - /** * Override method of same name from L.SVG, use the this._container property * to set up the role="none presentation" on featureGroupu container, @@ -5387,9 +5402,6 @@ if (p.subrings) { for (let r of p.subrings) { this._createPath(r, layer.options.className, r.attr['aria-label'], (r.link !== undefined), r.attr); - if(r.attr && r.attr.tabindex){ - p.path.setAttribute('tabindex', r.attr.tabindex || '0'); - } } } this._updateStyle(layer); @@ -5416,7 +5428,7 @@ if (title) p.setAttribute('aria-label', title); } else { for(let [name, value] of Object.entries(attr)){ - if(name === "id") continue; + if(name === "id" || name === "tabindex") continue; p.setAttribute(name, value); } } @@ -5642,7 +5654,6 @@ L.LayerGroup.prototype.initialize.call(this, layers, options); if((this.options.onEachFeature && this.options.properties) || this.options.link) { - this.options.group.setAttribute('tabindex', '0'); L.DomUtil.addClass(this.options.group, "leaflet-interactive"); L.DomEvent.on(this.options.group, "keyup keydown mousedown", this._handleFocus, this); let firstLayer = layers[Object.keys(layers)[0]]; @@ -5662,12 +5673,59 @@ if(this.options.featureID) this.options.group.setAttribute("data-fid", this.options.featureID); }, + onAdd: function (map) { + L.LayerGroup.prototype.onAdd.call(this, map); + this.updateInteraction(); + }, + + updateInteraction: function () { + let map = this._map || this.options._leafletLayer._map; + if((this.options.onEachFeature && this.options.properties) || this.options.link) + map.featureIndex.addToIndex(this, this.getPCRSCenter(), this.options.group); + + for (let layerID in this._layers) { + let layer = this._layers[layerID]; + for(let part of layer._parts){ + if(layer.featureAttributes && layer.featureAttributes.tabindex) + map.featureIndex.addToIndex(layer, layer.getPCRSCenter(), part.path); + for(let subPart of part.subrings) { + if(subPart.attr && subPart.attr.tabindex) map.featureIndex.addToIndex(layer, subPart.center, subPart.path); + } + } + } + }, + /** * Handler for focus events * @param {L.DOMEvent} e - Event that occurred * @private */ _handleFocus: function(e) { + if((e.keyCode === 9 || e.keyCode === 16) && e.type === "keydown"){ + let index = this._map.featureIndex.currentIndex; + if(e.keyCode === 9 && e.shiftKey) { + if(index === this._map.featureIndex.inBoundFeatures.length - 1) + this._map.featureIndex.inBoundFeatures[index].path.setAttribute("tabindex", -1); + if(index !== 0){ + L.DomEvent.stop(e); + this._map.featureIndex.inBoundFeatures[index - 1].path.focus(); + this._map.featureIndex.currentIndex--; + } + } else if (e.keyCode === 9) { + if(index !== this._map.featureIndex.inBoundFeatures.length - 1) { + L.DomEvent.stop(e); + this._map.featureIndex.inBoundFeatures[index + 1].path.focus(); + this._map.featureIndex.currentIndex++; + } else { + this._map.featureIndex.inBoundFeatures[0].path.setAttribute("tabindex", -1); + this._map.featureIndex.inBoundFeatures[index].path.setAttribute("tabindex", 0); + } + } + } else if (!(e.keyCode === 9 || e.keyCode === 16 || e.keyCode === 13)){ + this._map.featureIndex.currentIndex = 0; + this._map.featureIndex.inBoundFeatures[0].path.focus(); + } + if(e.target.tagName.toUpperCase() !== "G") return; if((e.keyCode === 9 || e.keyCode === 16 || e.keyCode === 13) && e.type === "keyup") { this.openTooltip(); @@ -5699,22 +5757,10 @@ * @private */ _previousFeature: function(e){ - let group = this._source.group.previousSibling; - if(!group){ - let currentIndex = this._source.group.closest("div.mapml-layer").style.zIndex; - let overlays = this._map.getPane("overlayPane").children; - for(let i = overlays.length - 1; i >= 0; i--){ - let layer = overlays[i]; - if(layer.style.zIndex >= currentIndex) continue; - group = layer.querySelector("g.leaflet-interactive"); - if(group){ - group = group.parentNode.lastChild; - break; - } - } - if (!group) group = this._source.group; - } - group.focus(); + L.DomEvent.stop(e); + this._map.featureIndex.currentIndex = Math.max(this._map.featureIndex.currentIndex - 1, 0); + let prevFocus = this._map.featureIndex.inBoundFeatures[this._map.featureIndex.currentIndex]; + prevFocus.path.focus(); this._map.closePopup(); }, @@ -5724,19 +5770,24 @@ * @private */ _nextFeature: function(e){ - let group = this._source.group.nextSibling; - if(!group){ - let currentIndex = this._source.group.closest("div.mapml-layer").style.zIndex; + L.DomEvent.stop(e); + this._map.featureIndex.currentIndex = Math.min(this._map.featureIndex.currentIndex + 1, this._map.featureIndex.inBoundFeatures.length - 1); + let nextFocus = this._map.featureIndex.inBoundFeatures[this._map.featureIndex.currentIndex]; + nextFocus.path.focus(); + this._map.closePopup(); + }, - for(let layer of this._map.getPane("overlayPane").children){ - if(layer.style.zIndex <= currentIndex) continue; - group = layer.querySelectorAll("g.leaflet-interactive"); - if(group.length > 0)break; + getPCRSCenter: function () { + let bounds; + for(let l in this._layers){ + let layer = this._layers[l]; + if (!bounds) { + bounds = L.bounds(layer.getPCRSCenter(), layer.getPCRSCenter()); + } else { + bounds.extend(layer.getPCRSCenter()); } - group = group && group.length > 0 ? group[0] : this._source.group; } - group.focus(); - this._map.closePopup(); + return bounds.getCenter(); }, }); @@ -5881,6 +5932,116 @@ }); + var FeatureIndex = L.Handler.extend({ + initialize: function (map) { + L.Handler.prototype.initialize.call(this, map); + this.inBoundFeatures = []; + this.outBoundFeatures = []; + this.currentIndex = 0; + this._mapPCRSBounds = M.pixelToPCRSBounds( + map.getPixelBounds(), + map.getZoom(), + map.options.projection); + }, + + addHooks: function () { + this._map.on("mapkeyboardfocused", this._updateMapBounds, this); + this._map.on('mapkeyboardfocused', this._sortIndex, this); + }, + + removeHooks: function () { + this._map.off("mapkeyboardfocused", this._updateMapBounds); + this._map.off('mapkeyboardfocused', this._sortIndex); + }, + + /** + * Adds a svg element to the index of tabbable features, it also keeps track of the layer it's associated + center + * @param layer - the layer object the feature is associated with + * @param lc - the layer center + * @param path - the svg element that needs to be focused, can be a path or g + */ + addToIndex: function (layer, lc, path) { + let mc = this._mapPCRSBounds.getCenter(); + let dist = Math.sqrt(Math.pow(lc.x - mc.x, 2) + Math.pow(lc.y - mc.y, 2)); + let index = this._mapPCRSBounds.contains(lc) ? this.inBoundFeatures : this.outBoundFeatures; + + let elem = {path: path, layer: layer, center: lc, dist: dist}; + path.setAttribute("tabindex", -1); + + index.push(elem); + + // TODO: this insertion loop has potential to be improved slightly + for (let i = index.length - 1; i > 0 && index[i].dist < index[i-1].dist; i--) { + let tmp = index[i]; + index[i] = index[i-1]; + index[i-1] = tmp; + } + + if (this._mapPCRSBounds.contains(lc)) + this.inBoundFeatures = index; + else + this.outBoundFeatures = index; + }, + + /** + * Removes features that are no longer on the map, also moves features to the respective array depending + * on whether the feature is in the maps viewport or not + */ + cleanIndex: function() { + this.currentIndex = 0; + this.inBoundFeatures = this.inBoundFeatures.filter((elem) => { + let inbound = this._mapPCRSBounds.contains(elem.center); + elem.path.setAttribute("tabindex", -1); + if (elem.layer._map && !inbound) { + this.outBoundFeatures.push(elem); + } + return elem.layer._map && inbound; + }); + this.outBoundFeatures = this.outBoundFeatures.filter((elem) => { + let inbound = this._mapPCRSBounds.contains(elem.center); + elem.path.setAttribute("tabindex", -1); + if (elem.layer._map && inbound) { + this.inBoundFeatures.push(elem); + } + return elem.layer._map && !inbound; + }); + }, + + /** + * Sorts the index of features in the map's viewport based on distance from center + * @private + */ + _sortIndex: function() { + this.cleanIndex(); + if(this.inBoundFeatures.length === 0) return; + + let mc = this._mapPCRSBounds.getCenter(); + + this.inBoundFeatures.sort(function(a, b) { + let ac = a.center; + let bc = b.center; + a.dist = Math.sqrt(Math.pow(ac.x - mc.x, 2) + Math.pow(ac.y - mc.y, 2)); + b.dist = Math.sqrt(Math.pow(bc.x - mc.x, 2) + Math.pow(bc.y - mc.y, 2)); + return a.dist - b.dist; + }); + + this.inBoundFeatures[0].path.setAttribute("tabindex", 0); + }, + + /** + * Event handler for 'mapfocused' event to update the map's bounds in terms of PCRS + * @param e - the event object + * @private + */ + _updateMapBounds: function (e) { + // TODO: map's PCRS bounds is used in other parts of the viewer, can be moved out to the map object directly + this._mapPCRSBounds = M.pixelToPCRSBounds( + this._map.getPixelBounds(), + this._map.getZoom(), + this._map.options.projection); + }, + }); + var Options = { announceMovement: false, locale: { @@ -6554,11 +6715,13 @@ M.QueryHandler = QueryHandler; M.ContextMenu = ContextMenu; M.AnnounceMovement = AnnounceMovement; + M.FeatureIndex = FeatureIndex; // see https://leafletjs.com/examples/extending/extending-3-controls.html#handlers L.Map.addInitHook('addHandler', 'query', M.QueryHandler); L.Map.addInitHook('addHandler', 'contextMenu', M.ContextMenu); L.Map.addInitHook('addHandler', 'announceMovement', M.AnnounceMovement); + L.Map.addInitHook('addHandler', 'featureIndex', M.FeatureIndex); M.MapMLLayer = MapMLLayer; M.mapMLLayer = mapMLLayer; diff --git a/dist/mapml.min.js b/dist/mapml.min.js index 7d2b297..052dba3 100644 --- a/dist/mapml.min.js +++ b/dist/mapml.min.js @@ -1,3 +1,3 @@ /*! @maps4html/web-map-custom-element 16-12-2021 */ -!function(){"use strict";var t=L.GridLayer.extend({initialize:function(t){this.zoomBounds=this._getZoomBounds(t.tileContainer,t.maxZoomBound),L.extend(t,this.zoomBounds),L.setOptions(this,t),this._groups=this._groupTiles(this.options.tileContainer.getElementsByTagName("map-tile"))},onAdd:function(){this._bounds=this._getLayerBounds(this._groups,this._map.options.projection),this.layerBounds=this._bounds[Object.keys(this._bounds)[0]];for(let t of Object.keys(this._bounds))this.layerBounds.extend(this._bounds[t].min),this.layerBounds.extend(this._bounds[t].max);L.GridLayer.prototype.onAdd.call(this,this._map),this._handleMoveEnd()},getEvents:function(){let t=L.GridLayer.prototype.getEvents.call(this,this._map);return this._parentOnMoveEnd=t.moveend,t.moveend=this._handleMoveEnd,t.move=(()=>{}),t},_handleMoveEnd:function(t){let e=this._map.getZoom(),i=e;i=(i=i>this.options.maxNativeZoom?this.options.maxNativeZoom:i)=this.zoomBounds.minZoom&&this._bounds[i]&&this._bounds[i].overlaps(M.pixelToPCRSBounds(this._map.getPixelBounds(),this._map.getZoom(),this._map.options.projection)),this.isVisible&&this._parentOnMoveEnd()},_isValidTile(t){return this._groups[this._tileCoordsToKey(t)]},createTile:function(t){let e=this._groups[this._tileCoordsToKey(t)]||[],i=document.createElement("map-tile"),o=this.getTileSize();i.setAttribute("col",t.x),i.setAttribute("row",t.y),i.setAttribute("zoom",t.z);for(let t=0;te.options.zIndex?1:0}},initialize:function(t,e){for(var i in L.setOptions(this,e),this._layerControlInputs=[],this._layers=[],this._lastZIndex=0,this._handlingClick=!1,t)this._addLayer(t[i],i,!0)},onAdd:function(){return this._initLayout(),this._map.on("validate",this._validateInput,this),L.DomEvent.on(this.options.mapEl,"layerchange",this._validateInput,this),L.DomEvent.on(this._container,"keydown",this._focusFirstLayer,this._container),this._update(),this._layers.length<1&&!this._map._showControls?this._container.setAttribute("hidden",""):this._map._showControls=!0,this._container},onRemove:function(t){t.off("validate",this._validateInput,this),L.DomEvent.off(this._container,"keydown",this._focusFirstLayer,this._container);for(var e=0;e0&&(this._container.removeAttribute("hidden"),this._map._showControls=!0),this._map?this._update():this},removeLayer:function(t){L.Control.Layers.prototype.removeLayer.call(this,t),0===this._layers.length&&this._container.setAttribute("hidden","")},_validateInput:function(t){for(let t=0;te.focus(),0)}},_withinZoomBounds:function(t,e){return e.min<=t&&t<=e.max},_addItem:function(t){var e=t.layer.getLayerUserControlsHTML();return t.input=e.querySelector("input"),this._layerControlInputs.push(t.input),t.input.layerId=L.stamp(t.layer),L.DomEvent.on(t.input,"click",this._onInputClick,this),t.layer.on("extentload",this._validateInput,this),this._overlaysList.appendChild(e),e},collapse:function(t){return"SELECT"===t.target.tagName||t.relatedTarget&&t.relatedTarget.parentElement&&("mapml-contextmenu mapml-layer-menu"===t.relatedTarget.className||"mapml-contextmenu mapml-layer-menu"===t.relatedTarget.parentElement.className)||this._map&&"block"===this._map.contextMenu._layerMenu.style.display?this:(L.DomUtil.removeClass(this._container,"leaflet-control-layers-expanded"),this)}}),o=function(t,e){return new i(t,e)};const n="OSMTILE",a="mapmltemplatedtileplaceholder";var s=L.FeatureGroup.extend({initialize:function(t,e){if(L.setOptions(this,e),this.options.static&&(this._container=L.DomUtil.create("div","leaflet-layer",this.options.pane),L.DomUtil.addClass(this._container,"leaflet-pane mapml-vector-container"),L.setOptions(this.options.renderer,{pane:this._container})),this._layers={},this.options.query){this._mapmlFeatures=t,this.isVisible=!0;let e=this._getNativeVariables(t);this.options.nativeZoom=e.zoom,this.options.nativeCS=e.cs}if(t&&!this.options.query){let e=this._getNativeVariables(t);!t.querySelector("map-extent")&&t.querySelector("map-feature")&&this.options.static&&(this._features={},this._staticFeature=!0,this.isVisible=!0,this.zoomBounds=this._getZoomBounds(t,e.zoom),this.layerBounds=this._getLayerBounds(t),L.extend(this.options,this.zoomBounds)),this.addData(t,e.cs,e.zoom),this._staticFeature&&(this._resetFeatures(this._clampZoom(this.options._leafletLayer._map.getZoom())),this.options._leafletLayer._map._addZoomLimit(this))}},onAdd:function(t){L.FeatureGroup.prototype.onAdd.call(this,t),this._mapmlFeatures&&t.on("featurepagination",this.showPaginationFeature,this)},onRemove:function(t){this._mapmlFeatures&&(t.off("featurepagination",this.showPaginationFeature,this),delete this._mapmlFeatures,L.DomUtil.remove(this._container)),L.FeatureGroup.prototype.onRemove.call(this,t)},getEvents:function(){return this._staticFeature?{moveend:this._handleMoveEnd,zoomend:this._handleZoomEnd}:{moveend:this._removeCSS}},showPaginationFeature:function(t){if(this.options.query&&this._mapmlFeatures.querySelectorAll("map-feature")[t.i]){let e=this._mapmlFeatures.querySelectorAll("map-feature")[t.i];this.clearLayers(),this.addData(e,this.options.nativeCS,this.options.nativeZoom),t.popup._navigationBar.querySelector("p").innerText=t.i+1+"/"+this.options._leafletLayer._totalFeatureCount,t.popup._content.querySelector("iframe").setAttribute("sandbox","allow-same-origin allow-forms"),t.popup._content.querySelector("iframe").srcdoc=e.querySelector("map-properties").innerHTML}},_getNativeVariables:function(t){return{zoom:t.querySelector("map-meta[name=zoom]")&&+M.metaContentToObject(t.querySelector("map-meta[name=zoom]").getAttribute("content")).value||0,cs:t.querySelector("map-meta[name=cs]")&&M.metaContentToObject(t.querySelector("map-meta[name=cs]").getAttribute("content")).content||"GCRS"}},_handleMoveEnd:function(){let t=this._map.getZoom(),e=t<=this.zoomBounds.maxZoom&&t>=this.zoomBounds.minZoom;this.isVisible=e&&this._layers&&this.layerBounds&&this.layerBounds.overlaps(M.pixelToPCRSBounds(this._map.getPixelBounds(),t,this._map.options.projection)),this._removeCSS()},_handleZoomEnd:function(t){let e=this._map.getZoom();if(e>this.zoomBounds.maxZoom||ethis.zoomBounds.maxZoom||t=this.options.minZoom&&this.layerBounds.overlaps(i),this.isVisible&&this._parentOnMoveEnd()},createTile:function(t){let e=document.createElement("DIV"),i=this.getTileSize();if(L.DomUtil.addClass(e,"mapml-tile-group"),L.DomUtil.addClass(e,"leaflet-tile"),this._template.linkEl.dispatchEvent(new CustomEvent("tileloadstart",{detail:{x:t.x,y:t.y,zoom:t.z,appendTile:t=>{e.appendChild(t)}}})),this._template.type.startsWith("image/")){let o=L.TileLayer.prototype.createTile.call(this,t,function(){});o.width=i.x,o.height=i.y,e.appendChild(o)}else this._url.includes(a)||this._fetchTile(t,e);return e},_mapmlTileReady:function(t){L.DomUtil.addClass(t,"leaflet-tile-loaded")},getPane:function(){return this.options.pane},_fetchTile:function(t,e){fetch(this.getTileUrl(t),{redirect:"follow"}).then(function(t){return t.status>=200&&t.status<300?Promise.resolve(t):(console.log("Looks like there was a problem. Status Code: "+t.status),Promise.reject(t))}).then(function(t){return t.text()}).then(t=>{return(new DOMParser).parseFromString(t,"application/xml")}).then(i=>{this._createFeatures(i,t,e),this._mapmlTileReady(e)}).catch(t=>{console.log("Error Creating Tile")})},_createFeatures:function(t,e,i){if(t.querySelector("map-link[rel=stylesheet],map-style")){let e=t.querySelector("map-base")&&t.querySelector("map-base").hasAttribute("href")?new URL(t.querySelector("map-base").getAttribute("href")).href:t.URL;M.parseStylesheetAsHTML(t,e,i)}let o=L.SVG.create("svg"),n=L.SVG.create("g"),a=this._map.options.crs.options.crs.tile.bounds.max.x,s=e.x*a,r=e.y*a,l=M.mapMlFeatures(t,{projection:this._map.options.projection,static:!1,interactive:!1});for(let t in l._layers)for(let i in l._layers[t]._layers){let o=l._layers[t]._layers[i];M.FeatureRenderer.prototype._initPath(o,!1),o._project(this._map,L.point([s,r]),e.z),M.FeatureRenderer.prototype._addPath(o,n,!1),M.FeatureRenderer.prototype._updateFeature(o)}o.setAttribute("width",a.toString()),o.setAttribute("height",a.toString()),o.appendChild(n),i.appendChild(o)},getTileUrl:function(t){if(t.z>=this._template.tilematrix.bounds.length||!this._template.tilematrix.bounds[t.z].contains(t))return"";var e={};for(var i in e[this._template.tilematrix.col.name]=t.x,e[this._template.tilematrix.row.name]=t.y,e[this._template.zoom.name]=this._getZoomForUrl(),e[this._template.pcrs.easting.left]=this._tileMatrixToPCRSPosition(t,"top-left").x,e[this._template.pcrs.easting.right]=this._tileMatrixToPCRSPosition(t,"top-right").x,e[this._template.pcrs.northing.top]=this._tileMatrixToPCRSPosition(t,"top-left").y,e[this._template.pcrs.northing.bottom]=this._tileMatrixToPCRSPosition(t,"bottom-left").y,e[this._template.tile.server]=this._getSubdomain(t),this._template.tile)["row","col","zoom","left","right","top","bottom"].indexOf(i)<0&&(e[i]=this._template.tile[i]);if(this._map&&!this._map.options.crs.infinite){let i=this._globalTileRange.max.y-t.y;this.options.tms&&(e[this._template.tilematrix.row.name]=i)}return e.r=this.options.detectRetina&&L.Browser.retina&&this.options.maxZoom>0?"@2x":"",L.Util.template(this._url,e)},_tileMatrixToPCRSPosition:function(t,e){var i=this._map.options.crs,o=this.getTileSize(),n=t.scaleBy(o),a=n.add(o),s=n.add(Math.floor(o/2)),r=i.transformation.untransform(n,i.scale(t.z)),l=i.transformation.untransform(a,i.scale(t.z)),m=i.transformation.untransform(s,i.scale(t.z)),u=null;switch(e){case"top-left":u=r;break;case"bottom-left":u=new L.Point(r.x,l.y);break;case"center-left":u=new L.Point(r.x,m.y);break;case"top-right":u=new L.Point(l.x,r.y);break;case"bottom-right":u=l;break;case"center-right":u=new L.Point(l.x,m.y);break;case"top-center":u=new L.Point(m.x,r.y);break;case"bottom-center":u=new L.Point(m.x,l.y);break;case"center":u=m}return u},_setUpTileTemplateVars:function(t){t.tile={};for(var e,i,o,n,a,s=t.values,r=this.options.crs.options,l=0;l=e.min&&Number.parseInt(y,10)<=e.max?e.value=Number.parseInt(y,10):e.value=e.max,!isNaN(Number.parseInt(g,10))&&Number.parseInt(g,10)>=e.min&&Number.parseInt(g,10)<=e.max&&(e.min=Number.parseInt(g,10)),!isNaN(Number.parseInt(f,10))&&Number.parseInt(f,10)>=e.min&&Number.parseInt(f,10)<=e.max&&(e.max=Number.parseInt(f,10)),t.zoom=e;else if(d)t.tile.server=c,t.tile.subdomains=s[l].servers.slice();else if(_){const e=s[l].htmlselect;t.tile[c]=function(){return e.value}}else{const e=s[l];t.tile[c]=function(){return e.getAttribute("value")}}}var b=this.options.crs.transformation,x=this.options.crs.options.crs.tile.bounds.max.x,v=L.bind(this.options.crs.scale,this.options.crs),A=function(t,e){return b.transform(t,v(e)).divideBy(x).floor()};i&&o?(t.pcrs={},t.pcrs.bounds=L.bounds([i.min,o.min],[i.max,o.max]),t.pcrs.easting=i,t.pcrs.northing=o):a&&n&&!isNaN(e.value)?(t.pcrs||(t.pcrs={},t.pcrs.easting="",t.pcrs.northing=""),t.pcrs.bounds=M.boundsToPCRSBounds(L.bounds(L.point([a.min,n.min]),L.point([a.max,n.max])),e.value,this.options.crs,M.axisToCS("column")),t.tilematrix={},t.tilematrix.col=a,t.tilematrix.row=n):console.log("Unable to determine bounds for tile template: "+t.template),t.tilematrix||(t.tilematrix={},t.tilematrix.col={},t.tilematrix.row={}),t.tilematrix.bounds=[];for(var E=t.pcrs.bounds,C=t.zoom?t.zoom.min:0,S=t.zoom?t.zoom.max:r.resolutions.length,T=0;T<=S;T++)t.tilematrix.bounds[T]=T>=C?L.bounds(A(E.min,T),A(E.max,T)):L.bounds(L.point([-1,-1]),L.point([-1,-1]))}}),m=function(t,e){return new l(t,e)},u=L.Layer.extend({initialize:function(t,e){this._templates=t,L.setOptions(this,e),this._container=L.DomUtil.create("div","leaflet-layer",e.pane),L.DomUtil.addClass(this._container,"mapml-templatedlayer-container");for(var i=0;i=0&&(this._count--,this._map.fire("featurepagination",{i:this._count,popup:this}))},_nextFeature:function(t){this._count+1=this.zoomBounds.minZoom&&this.layerBounds.overlaps(e),this._features.clearLayers(),this.isVisible){var i,o=new Headers({Accept:"text/mapml;q=0.9,application/geo+json;q=0.8"}),n=new DOMParser,a=this._features,s=this._map,r=this,l=function(t,e){return fetch(t,{redirect:"follow",headers:o}).then(function(t){return t.text()}).then(function(o){i=n.parseFromString(o,"application/xml");var s=new URL(i.querySelector("map-base")?i.querySelector("map-base").getAttribute("href"):t).href;t=(t=i.querySelector("map-link[rel=next]")?i.querySelector("map-link[rel=next]").getAttribute("href"):null)?new URL(t,s).href:null;let r=i.querySelector("map-meta[name=zoom]")&&+M.metaContentToObject(i.querySelector("map-meta[name=zoom]").getAttribute("content")).value||0,m=i.querySelector("map-meta[name=cs]")&&M.metaContentToObject(i.querySelector("map-meta[name=cs]").getAttribute("content")).content||"GCRS";if(a.addData(i,m,r),t&&--e)return l(t,e)})};l(this._getfeaturesUrl(),10).then(function(){s.addLayer(a),M.TemplatedFeaturesLayer.prototype._updateTabIndex(r)}).catch(function(t){console.log(t)})}},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},_updateTabIndex:function(t){let e=t||this;for(let t in e._features._layers){let i=e._features._layers[t];if(i._path&&("M0 0"!==i._path.getAttribute("d")?i._path.setAttribute("tabindex",0):i._path.removeAttribute("tabindex"),0===i._path.childElementCount)){let t=document.createElement("title");t.innerText="Feature",i._path.appendChild(t)}}},_updateZIndex:function(){this._container&&void 0!==this.options.zIndex&&null!==this.options.zIndex&&(this._container.style.zIndex=this.options.zIndex)},onRemove:function(){this._map.removeLayer(this._features)},_getfeaturesUrl:function(){var t={};for(var e in this.options.feature.zoom&&(t[this.options.feature.zoom]=this._map.getZoom()),this.options.feature.width&&(t[this.options.feature.width]=this._map.getSize().x),this.options.feature.height&&(t[this.options.feature.height]=this._map.getSize().y),this.options.feature.bottom&&(t[this.options.feature.bottom]=this._TCRSToPCRS(this._map.getPixelBounds().max,this._map.getZoom()).y),this.options.feature.left&&(t[this.options.feature.left]=this._TCRSToPCRS(this._map.getPixelBounds().min,this._map.getZoom()).x),this.options.feature.top&&(t[this.options.feature.top]=this._TCRSToPCRS(this._map.getPixelBounds().min,this._map.getZoom()).y),this.options.feature.right&&(t[this.options.feature.right]=this._TCRSToPCRS(this._map.getPixelBounds().max,this._map.getZoom()).x),this.options.feature)["width","height","left","right","top","bottom","zoom"].indexOf(e)<0&&(t[e]=this.options.feature[e]);return L.Util.template(this._template.template,t)},_TCRSToPCRS:function(t,e){var i=this._map.options.crs;return i.transformation.untransform(t,i.scale(e))},_setUpFeaturesTemplateVars:function(t){var e={feature:{}},i=t.values;e.feature.hidden=[];for(var o=0;o=this.zoomBounds.minZoom&&this.layerBounds.overlaps(e),this.isVisible){var i=this._map,o=i.getPixelBounds().min.subtract(i.getPixelOrigin()),n=i.getSize(),a=this.getImageUrl(),s=this._imageOverlay;this._imageOverlay=M.imageOverlay(a,o,n,0,this._container),this._imageOverlay.addTo(i),s&&this._imageOverlay.on("load error",function(){i.removeLayer(s)})}else this._clearLayer()},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},_updateZIndex:function(){this._container&&void 0!==this.options.zIndex&&null!==this.options.zIndex&&(this._container.style.zIndex=this.options.zIndex)},onRemove:function(t){this._clearLayer(),t._removeZoomLimit(this),this._container=null},getImageUrl:function(){var t={};for(var e in t[this.options.extent.width]=this._map.getSize().x,t[this.options.extent.height]=this._map.getSize().y,t[this.options.extent.bottom]=this._TCRSToPCRS(this._map.getPixelBounds().max,this._map.getZoom()).y,t[this.options.extent.left]=this._TCRSToPCRS(this._map.getPixelBounds().min,this._map.getZoom()).x,t[this.options.extent.top]=this._TCRSToPCRS(this._map.getPixelBounds().min,this._map.getZoom()).y,t[this.options.extent.right]=this._TCRSToPCRS(this._map.getPixelBounds().max,this._map.getZoom()).x,this.options.extent)["width","height","left","right","top","bottom"].indexOf(e)<0&&(t[e]=this.options.extent[e]);return L.Util.template(this._template.template,t)},_TCRSToPCRS:function(t,e){var i=this._map.options.crs;return i.transformation.untransform(t,i.scale(e))},_setUpExtentTemplateVars:function(t){for(var e={extent:{}},i=t.values,o=0;o=0&&t.target.value<=1&&this.changeOpacity(t.target.value)},changeOpacity:function(t){this._container.style.opacity=t,this.opacityEl&&(this.opacityEl.value=t)},onAdd:function(t){!this._extent||this._validProjection(t)?(this._map=t,this._content?(this._mapmlvectors||(this._mapmlvectors=M.mapMlFeatures(this._content,{renderer:M.featureRenderer(),pane:this._container,opacity:this.options.opacity,projection:t.options.projection,_leafletLayer:this,static:!0,onEachFeature:function(t,e){if(t){var i=document.createElement("div");i.classList.add("mapml-popup-content"),i.insertAdjacentHTML("afterbegin",t.innerHTML),e.bindPopup(i,{autoClose:!1,minWidth:165})}}})),t.addLayer(this._mapmlvectors)):this.once("extentload",function(){this._validProjection(t)?(this._mapmlvectors||(this._mapmlvectors=M.mapMlFeatures(this._content,{renderer:M.featureRenderer(),pane:this._container,opacity:this.options.opacity,projection:t.options.projection,_leafletLayer:this,static:!0,onEachFeature:function(t,e){if(t){var i=document.createElement("div");i.classList.add("mapml-popup-content"),i.insertAdjacentHTML("afterbegin",t.innerHTML),e.bindPopup(i,{autoClose:!1,minWidth:165})}}}).addTo(t)),this._setLayerElExtent()):this.validProjection=!1},this),this._imageLayer||(this._imageLayer=L.layerGroup()),t.addLayer(this._imageLayer),(!this._staticTileLayer||null===this._staticTileLayer._container)&&this._mapmlTileContainer.getElementsByTagName("map-tiles").length>0&&(this._staticTileLayer=M.mapMLStaticTileLayer({pane:this._container,_leafletLayer:this,className:"mapml-static-tile-layer",tileContainer:this._mapmlTileContainer,maxZoomBound:t.options.crs.options.resolutions.length-1,tileSize:t.options.crs.options.crs.tile.bounds.max.x}),t.addLayer(this._staticTileLayer)),this._extent?this._templateVars&&(this._templatedLayer=M.templatedLayer(this._templateVars,{pane:this._container,_leafletLayer:this,crs:this.crs}).addTo(t)):this.once("extentload",function(){this._validProjection(t)?this._templateVars&&(this._templatedLayer=M.templatedLayer(this._templateVars,{pane:this._container,_leafletLayer:this,crs:this.crs}).addTo(t),this._setLayerElExtent()):this.validProjection=!1},this),this._setLayerElExtent(),this.setZIndex(this.options.zIndex),this.getPane().appendChild(this._container),setTimeout(()=>{t.fire("checkdisabled")},0),t.on("popupopen",this._attachSkipButtons,this)):this.validProjection=!1},_validProjection:function(t){let e=!1;if(this._templateVars)for(let i of this._templateVars)i.projectionMatch||i.projection===t.options.projection||(e=!0);return!(e||this.getProjection()!==t.options.projection.toUpperCase())},_setLayerElExtent:function(){let t,e;["_staticTileLayer","_imageLayer","_mapmlvectors","_templatedLayer"].forEach(i=>{if(this[i])if("_templatedLayer"===i)for(let o=0;on&&this._extent.zoomin;o<=e&&e<=n||(this._extent.zoomin&&e>n?(this._href=this._extent.zoomin,this._layerEl.src=this._extent.zoomin,this.href=this._extent.zoomin,this._layerEl.src=this._extent.zoomin):this._extent.zoomout&&e{let e,i,o=0;if(i="MAPML-VIEWER"===d.tagName?d.shadowRoot:d.querySelector(".mapml-web-map").shadowRoot,t.target.closest("fieldset").nextElementSibling&&!t.target.closest("fieldset").nextElementSibling.disbaled)for(e=t.target.closest("fieldset").previousElementSibling;e;)o+=2,e=e.previousElementSibling;else e="link";d.removeChild(t.target.closest("fieldset").querySelector("span").layer._layerEl),(e=e?i.querySelector(".leaflet-control-attribution").firstElementChild:e=i.querySelectorAll("input")[o]).focus()},this);let y=L.DomUtil.create("button","mapml-layer-item-settings-control",r);if(y.type="button",y.title="Layer Settings",y.setAttribute("aria-expanded",!1),y.classList.add("mapml-button"),L.DomEvent.on(y,"click",t=>{1==a.hidden?(y.setAttribute("aria-expanded",!0),a.hidden=!1):(y.setAttribute("aria-expanded",!1),a.hidden=!0)},this),e.defaultChecked=!!this._map,e.type="checkbox",i.layer=this,this._legendUrl){var g=document.createElement("a");g.text=" "+this._title,g.href=this._legendUrl,g.target="_blank",g.draggable=!1,i.appendChild(g)}else i.innerHTML=this._title;if(i.id="mapml-layer-item-name-{"+L.stamp(i)+"}",u.innerText="Opacity",u.id="mapml-layer-item-opacity-"+L.stamp(u),l.appendChild(u),l.appendChild(m),m.setAttribute("type","range"),m.setAttribute("min","0"),m.setAttribute("max","1.0"),m.setAttribute("value",this._container.style.opacity||"1.0"),m.setAttribute("step","0.1"),m.setAttribute("aria-labelledby",u.id),m.value=this._container.style.opacity||"1.0",t.setAttribute("aria-grabbed","false"),t.setAttribute("aria-labelledby",i.id),t.onmousedown=(e=>{if("input"===e.target.tagName.toLowerCase()||"select"===e.target.tagName.toLowerCase())return;e.preventDefault();let i=t,o=t.parentNode,n=!1,a=e.clientY;document.body.onmousemove=(t=>{t.preventDefault();let e=t.clientY-a;if(n=Math.abs(e)>5||n,o&&!n||o&&o.childElementCount<=1||o.getBoundingClientRect().top>i.getBoundingClientRect().bottom||o.getBoundingClientRect().bottom{i.setAttribute("aria-grabbed","false"),i.removeAttribute("aria-dropeffect"),i.style.pointerEvents=null,i.style.transform=null;let t=o.children,e=1;for(let i of t){let t=i.querySelector("span").layer._layerEl;t.setAttribute("data-moving",""),d.insertAdjacentElement("beforeend",t),t.removeAttribute("data-moving"),t._layer.setZIndex(e),e++}o.classList.remove("mapml-draggable"),document.body.onmousemove=document.body.onmouseup=null})}),L.DomEvent.on(m,"change",this._changeOpacity,this),s.appendChild(e),s.appendChild(i),y.appendChild(o),o.appendChild(p),this._styles&&a.appendChild(this._styles),this._userInputs){var f=document.createDocumentFragment(),b=this._templateVars;if(b)for(var x=0;x map-option");0===I.length&&P.hasAttribute("value")&&(I=P.getAttribute("value").split(""));for(var B=0;B1){var Z=document.createElement("details"),G=document.createElement("summary");G.innerText="Style",Z.appendChild(G);for(var H=function(t){o.fire("changestyle",{src:t.target.getAttribute("data-href")},!1)},$=0;$'+i+""),L.setOptions(e,{attribution:o});var a=t.querySelector("map-link[rel=legend]");a&&(e._legendUrl=a.getAttribute("href"))},_getUnprojectedMapLatLngBounds:function(t){var e=(t=t||this._map).getPixelOrigin(),i=t.getPixelBounds(),o=t.unproject(e),n=t.unproject(i.getBottomLeft()),a=t.unproject(i.getTopRight()),s=t.unproject(e.add(t.getSize()));return L.latLngBounds(n,a).extend(s).extend(o)},_projectionMatches:function(t){t=t||this._map;var e=this.getProjection();return!(!t.options.projection||"WGS84"!==e&&t.options.projection!==e)},getQueryTemplates:function(){if(this._templatedLayer&&this._templatedLayer._queries)return this._templatedLayer._queries},_attachSkipButtons:function(t){let e,i,o=t.popup,n=t.target,a=o._container.getElementsByClassName("mapml-popup-content")[0];o._container.setAttribute("role","dialog"),a.setAttribute("tabindex","-1"),a.setAttribute("role","document"),o._count=0,o._source._eventParents?(e=o._source._eventParents[Object.keys(o._source._eventParents)[0]],i=o._source.group):e=o._source._templatedLayer,o._container.querySelector('nav[class="mapml-focus-buttons"]')&&(L.DomUtil.remove(o._container.querySelector('nav[class="mapml-focus-buttons"]')),L.DomUtil.remove(o._container.querySelector("hr")));let s=L.DomUtil.create("nav","mapml-focus-buttons"),r=L.DomUtil.create("button","mapml-popup-button",s);r.type="button",r.title="Focus Map",r.innerHTML="",L.DomEvent.disableClickPropagation(r),L.DomEvent.on(r,"click",L.DomEvent.stop),L.DomEvent.on(r,"click",t=>{n.closePopup(),n._container.focus()},o);let l=L.DomUtil.create("button","mapml-popup-button",s);l.type="button",l.title="Previous Feature",l.innerHTML="",L.DomEvent.disableClickPropagation(l),L.DomEvent.on(l,"click",L.DomEvent.stop),L.DomEvent.on(l,"click",e._previousFeature,o);let m=L.DomUtil.create("p","mapml-feature-count",s),u=this._totalFeatureCount?this._totalFeatureCount:1;m.innerText=o._count+1+"/"+u;let p=L.DomUtil.create("button","mapml-popup-button",s);p.type="button",p.title="Next Feature",p.innerHTML="",L.DomEvent.disableClickPropagation(p),L.DomEvent.on(p,"click",L.DomEvent.stop),L.DomEvent.on(p,"click",e._nextFeature,o);let c=L.DomUtil.create("button","mapml-popup-button",s);c.type="button",c.title="Focus Controls",c.innerHTML="",L.DomEvent.disableClickPropagation(c),L.DomEvent.on(c,"click",L.DomEvent.stop),L.DomEvent.on(c,"click",t=>{n.closePopup(),n._controlContainer.querySelector("A").focus()},o);let h=L.DomUtil.create("hr");function d(t){let e=t.originalEvent.path||t.originalEvent.composedPath(),a=9===t.originalEvent.keyCode,s=t.originalEvent.shiftKey;e[0].classList.contains("leaflet-popup-close-button")&&a&&!s||27===t.originalEvent.keyCode?(L.DomEvent.stop(t),n.closePopup(o),i.focus()):("Focus Map"===e[0].title||e[0].classList.contains("mapml-popup-content"))&&a&&s&&setTimeout(()=>{L.DomEvent.stop(t),n.closePopup(o),i.focus()},0)}function _(t){let e=t.originalEvent.path||t.originalEvent.composedPath(),i=9===t.originalEvent.keyCode,a=t.originalEvent.shiftKey;13===t.originalEvent.keyCode&&e[0].classList.contains("leaflet-popup-close-button")||27===t.originalEvent.keyCode?(L.DomEvent.stopPropagation(t),n._container.focus(),n.closePopup(o),27!==t.originalEvent.keyCode&&(n._popupClosed=!0)):i&&e[0].classList.contains("leaflet-popup-close-button")?n.closePopup(o):("Focus Map"===e[0].title||e[0].classList.contains("mapml-popup-content"))&&i&&a&&setTimeout(()=>{L.DomEvent.stop(t),n.closePopup(o),n._container.focus()},0)}o._navigationBar=s,o._content.appendChild(h),o._content.appendChild(s),a.focus(),i?(i.setAttribute("aria-expanded","true"),n.on("keydown",d)):n.on("keydown",_),n.on("popupclose",function t(e){e.popup===o&&(n.off("keydown",d),n.off("keydown",_),n.off("popupclose",t),i&&i.setAttribute("aria-expanded","false"))})}}),b=function(t,e,i){return t||e?new f(t,e,i):null},x=L.Layer.extend({onAdd:function(t){let e=t.getSize();(e.x>400||e.y>300)&&(this._container=L.DomUtil.create("table","mapml-debug",t._container),this._panel=E({className:"mapml-debug-panel",pane:this._container}),t.addLayer(this._panel)),this._grid=S({className:"mapml-debug-grid",pane:t._panes.mapPane,zIndex:400,tileSize:t.options.crs.options.crs.tile.bounds.max.x}),t.addLayer(this._grid),this._vectors=z({className:"mapml-debug-vectors",pane:t._panes.mapPane,toolPane:this._container}),t.addLayer(this._vectors)},onRemove:function(t){t.removeLayer(this._grid),t.removeLayer(this._vectors),this._panel&&(t.removeLayer(this._panel),L.DomUtil.remove(this._container))}}),v=function(){return new x},A=L.Layer.extend({initialize:function(t){L.setOptions(this,t)},onAdd:function(t){this._title=L.DomUtil.create("caption","mapml-debug-banner",this.options.pane),this._title.innerHTML="Debug mode",t.debug={},t.debug._infoContainer=this._debugContainer=L.DomUtil.create("tbody","mapml-debug-panel",this.options.pane);let e=t.debug._infoContainer;t.debug._tileCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),t.debug._tileMatrixCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),t.debug._mapCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),t.debug._tcrsCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),t.debug._pcrsCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),t.debug._gcrsCoord=L.DomUtil.create("tr","mapml-debug-coordinates",e),this._map.on("mousemove",this._updateCoords)},onRemove:function(){L.DomUtil.remove(this._title),this._debugContainer&&(L.DomUtil.remove(this._debugContainer),this._map.off("mousemove",this._updateCoords))},_updateCoords:function(t){if(this.contextMenu._visible)return;let e=this.options.mapEl,i=e._map.project(t.latlng),o=e._map.options.crs.scale(+e.zoom),n=e._map.options.crs.transformation.untransform(i,o),a=e._map.options.crs.options.crs.tile.bounds.max.x,s=i.x%a,r=i.y%a;s<0&&(s+=a),r<0&&(r+=a),this.debug._tileCoord.innerHTML=`\n tile: \n i: ${Math.trunc(s)}, \n j: ${Math.trunc(r)}\n `,this.debug._mapCoord.innerHTML=`\n map: \n i: ${Math.trunc(t.containerPoint.x)}, \n j: ${Math.trunc(t.containerPoint.y)}\n `,this.debug._gcrsCoord.innerHTML=`\n gcrs: \n lon: ${t.latlng.lng.toFixed(6)}, \n lat: ${t.latlng.lat.toFixed(6)}\n `,this.debug._tcrsCoord.innerHTML=`\n tcrs: \n x: ${Math.trunc(i.x)}, \n y: ${Math.trunc(i.y)}\n `,this.debug._tileMatrixCoord.innerHTML=`\n tilematrix: \n column: ${Math.trunc(i.x/a)}, \n row: ${Math.trunc(i.y/a)}\n `,this.debug._pcrsCoord.innerHTML=`\n pcrs: \n easting: ${n.x.toFixed(2)}, \n northing: ${n.y.toFixed(2)}\n `}}),E=function(t){return new A(t)},C=L.GridLayer.extend({initialize:function(t){L.setOptions(this,t),L.GridLayer.prototype.initialize.call(this,this._map)},createTile:function(t){let e=L.DomUtil.create("div","mapml-debug-tile");return e.setAttribute("col",t.x),e.setAttribute("row",t.y),e.setAttribute("zoom",t.z),e.innerHTML=[`col: ${t.x}`,`row: ${t.y}`,`zoom: ${t.z}`].join(", "),e.style.outline="1px dashed red",e}}),S=function(t){return new C(t)},T=L.LayerGroup.extend({initialize:function(t){L.setOptions(this,t),L.LayerGroup.prototype.initialize.call(this,this._map,t)},onAdd:function(t){t.on("overlayremove",this._mapLayerUpdate,this),t.on("overlayadd",this._mapLayerUpdate,this);let e=t.options.crs.transformation.transform(L.point(0,0),t.options.crs.scale(0));this._centerVector=L.circle(t.options.crs.pointToLatLng(e,0),{radius:250}),this._centerVector.bindTooltip("Projection Center"),this._addBounds(t)},onRemove:function(t){this.clearLayers()},_addBounds:function(t){let e=Object.keys(t._layers),i=t._layers,o=["#FF5733","#8DFF33","#3397FF","#E433FF","#F3FF33"],n=0;this.addLayer(this._centerVector);for(let t of e)if(i[t].layerBounds){let e=[i[t].layerBounds.min,L.point(i[t].layerBounds.max.x,i[t].layerBounds.min.y),i[t].layerBounds.max,L.point(i[t].layerBounds.min.x,i[t].layerBounds.max.y)],a=P(e,{color:o[n%o.length],weight:2,opacity:1,fillOpacity:.01,fill:!0});i[t].options._leafletLayer&&a.bindTooltip(i[t].options._leafletLayer._title,{sticky:!0}),this.addLayer(a),n++}if(t.totalLayerBounds){let e=[t.totalLayerBounds.min,L.point(t.totalLayerBounds.max.x,t.totalLayerBounds.min.y),t.totalLayerBounds.max,L.point(t.totalLayerBounds.min.x,t.totalLayerBounds.max.y)],i=P(e,{color:"#808080",weight:5,opacity:.5,fill:!1});this.addLayer(i)}},_mapLayerUpdate:function(t){this.clearLayers(),this._addBounds(t.target)}}),z=function(t){return new T(t)},k=L.Path.extend({options:{className:"mapml-debug-extent"},initialize:function(t,e){this._locations=t,L.setOptions(this,e)},_project:function(){this._rings=[];let t=this._map.options.crs.scale(this._map.getZoom()),e=this._map;for(let i=0;i=0;e--){var i=t[e]._layer;if(t[e].checked&&i.queryable)return i}},_queryTopLayerAtMapCenter:function(t){setTimeout(()=>{!this._map.isFocused||this._map._popupClosed||" "!==t.originalEvent.key&&13!=+t.originalEvent.keyCode?delete this._map._popupClosed:this._map.fire("click",{latlng:this._map.getCenter(),layerPoint:this._map.latLngToLayerPoint(this._map.getCenter()),containerPoint:this._map.latLngToContainerPoint(this._map.getCenter())})},0)},_queryTopLayer:function(t){var e=this._getTopQueryableLayer();e&&this._query(t,e)},_query(t,e){var i={},o=e.getQueryTemplates()[0],n=t.target.getZoom(),a=this._map,s=e.crs,r=a.options.crs.options.crs.tile.bounds.max.x,l=e._container,m={autoClose:!1,autoPan:!0,maxHeight:.5*a.getSize().y-50},u=function(t){return s.transformation.untransform(t,s.scale(n))},p=function(t){return s.unproject(s.transformation.untransform(t,s.scale(n)),n)},c=s.latLngToPoint(t.latlng,n),h=c.divideBy(r).floor(),d=new L.Bounds(c.divideBy(r).floor().multiplyBy(r),c.divideBy(r).ceil().multiplyBy(r));for(var _ in i[o.query.tilei]=c.x.toFixed()-h.x*r,i[o.query.tilej]=c.y.toFixed()-h.y*r,i[o.query.mapi]=a.getSize().divideBy(2).x.toFixed(),i[o.query.mapj]=a.getSize().divideBy(2).y.toFixed(),i[o.query.pixelleft]=s.pointToLatLng(c,n).lng,i[o.query.pixeltop]=s.pointToLatLng(c,n).lat,i[o.query.pixelright]=s.pointToLatLng(c.add([1,1]),n).lng,i[o.query.pixelbottom]=s.pointToLatLng(c.add([1,1]),n).lat,i[o.query.column]=h.x,i[o.query.row]=h.y,i[o.query.x]=c.x.toFixed(),i[o.query.y]=c.y.toFixed(),i[o.query.easting]=u(c).x,i[o.query.northing]=u(c).y,i[o.query.longitude]=p(c).lng,i[o.query.latitude]=p(c).lat,i[o.query.zoom]=n,i[o.query.width]=a.getSize().x,i[o.query.height]=a.getSize().y,i[o.query.mapbottom]=u(c.add(a.getSize().divideBy(2))).y,i[o.query.mapleft]=u(c.subtract(a.getSize().divideBy(2))).x,i[o.query.maptop]=u(c.subtract(a.getSize().divideBy(2))).y,i[o.query.mapright]=u(c.add(a.getSize().divideBy(2))).x,i[o.query.tilebottom]=u(d.max).y,i[o.query.tileleft]=u(d.min).x,i[o.query.tiletop]=u(d.min).y,i[o.query.tileright]=u(d.max).x,o.query)["mapi","mapj","tilei","tilej","row","col","x","y","easting","northing","longitude","latitude","width","height","zoom","mapleft","mapright",",maptop","mapbottom","tileleft","tileright","tiletop","tilebottom","pixeltop","pixelbottom","pixelleft","pixelright"].indexOf(_)<0&&(i[_]=o.query[_]);let y,g=this._map.project(t.latlng),f=this._map.options.crs.scale(this._map.getZoom()),b=this._map.options.crs.transformation.untransform(g,f);o.layerBounds.contains(b)&&fetch(L.Util.template(o.template,i),{redirect:"follow"}).then(t=>{if(y=t.headers.get("Content-Type"),t.status>=200&&t.status<300)return t.text();throw new Error(t.status)}).then(i=>y.startsWith("text/mapml")?function(t,i){let o=(new DOMParser).parseFromString(t,"application/xml");for(let t of o.querySelectorAll("map-feature"))if(!t.querySelector("map-geometry")){let e=document.createElement("map-geometry"),o=document.createElement("map-point"),n=document.createElement("map-coordinates");e.setAttribute("cs","gcrs"),n.innerHTML=`${i.lng} ${i.lat}`,o.appendChild(n),e.appendChild(o),t.appendChild(e)}let n=M.mapMlFeatures(o,{renderer:M.featureRenderer(),pane:l,projection:a.options.projection,_leafletLayer:e,query:!0,static:!0});n.addTo(a);let s=L.DomUtil.create("div","mapml-popup-content"),r=L.DomUtil.create("iframe");r.style="border: none",r.srcdoc=o.querySelector("map-feature map-properties").innerHTML,r.setAttribute("sandbox","allow-same-origin allow-forms"),s.appendChild(r),e._totalFeatureCount=o.querySelectorAll("map-feature").length,e.bindPopup(s,m).openPopup(i),e.on("popupclose",function(){a.removeLayer(n)}),n.showPaginationFeature({i:0,popup:e._popup})}(i,t.latlng):function(t,e,i){let o=L.DomUtil.create("div","mapml-popup-content"),n=L.DomUtil.create("iframe");n.style="border: none",n.srcdoc=t,n.setAttribute("sandbox","allow-same-origin allow-forms"),o.appendChild(n),e.bindPopup(o,m).openPopup(i)}(i,e,t.latlng)).catch(t=>{console.log("Looks like there was a problem. Status: "+t.message)})}}),I=L.Handler.extend({_touchstart:L.Browser.msPointer?"MSPointerDown":L.Browser.pointer?"pointerdown":"touchstart",initialize:function(t){L.Handler.prototype.initialize.call(this,t),this._items=[{text:M.options.locale.cmBack+" (B)",callback:this._goBack},{text:M.options.locale.cmForward+" (F)",callback:this._goForward},{text:M.options.locale.cmReload+" (R)",callback:this._reload},{spacer:"-"},{text:M.options.locale.cmToggleControls+" (T)",callback:this._toggleControls},{text:M.options.locale.cmCopyCoords+" (C)",callback:this._copyCoords,hideOnSelect:!1,popup:!0,submenu:[{text:"tile",callback:this._copyTile},{text:"tilematrix",callback:this._copyTileMatrix},{spacer:"-"},{text:"map",callback:this._copyMap},{spacer:"-"},{text:"tcrs",callback:this._copyTCRS},{text:"pcrs",callback:this._copyPCRS},{text:"gcrs",callback:this._copyGCRS},{spacer:"-"},{text:M.options.locale.cmCopyAll,callback:this._copyAllCoords}]},{text:M.options.locale.cmToggleDebug+" (D)",callback:this._toggleDebug},{text:M.options.locale.cmCopyMapML+" (M)",callback:this._copyMapML},{text:M.options.locale.cmViewSource+" (V)",callback:this._viewSource}],this._layerItems=[{text:M.options.locale.lmZoomToLayer+" (Z)",callback:this._zoomToLayer},{text:M.options.locale.lmCopyExtent+" (C)",callback:this._copyLayerExtent}],this._mapMenuVisible=!1,this._keyboardEvent=!1,this._container=L.DomUtil.create("div","mapml-contextmenu",t._container),this._container.setAttribute("hidden","");for(let t=0;t<6;t++)this._items[t].el=this._createItem(this._container,this._items[t]);this._coordMenu=L.DomUtil.create("div","mapml-contextmenu mapml-submenu",this._container),this._coordMenu.id="mapml-copy-submenu",this._coordMenu.setAttribute("hidden",""),this._clickEvent=null;for(let t=0;t`;e._copyData(a)},_zoomToLayer:function(t){(t instanceof KeyboardEvent?this._map.contextMenu:this.contextMenu)._layerClicked.layer._layerEl.focus()},_goForward:function(t){(t instanceof KeyboardEvent?this._map.options.mapEl:this.options.mapEl).forward()},_goBack:function(t){(t instanceof KeyboardEvent?this._map.options.mapEl:this.options.mapEl).back()},_reload:function(t){(t instanceof KeyboardEvent?this._map.options.mapEl:this.options.mapEl).reload()},_toggleControls:function(t){(t instanceof KeyboardEvent?this._map.options.mapEl:this.options.mapEl)._toggleControls()},_copyMapML:function(t){let e=t instanceof KeyboardEvent?this._map.contextMenu:this.contextMenu,i=t instanceof KeyboardEvent?this._map.options.mapEl:this.options.mapEl;e._copyData(i.outerHTML.replace(/
.*?<\/div>|