Skip to content

Commit b44bc70

Browse files
Anshpreet8Anshpreetprushforth
authored
Allow Multiple extents (#632)
* rebased multiple extents * added multiple extents html files * delete css that might've been added when rebasing * removeChild instead of removing layer * fixed opacity * changed extent HTML anatomy * changed to adding layerBounds after * changed the var name to extentBounds * added tests * fixed zIndex * reordering extents * added more tests, made fieldset hidden if no layer attr and fixed issues * fixed 2 test issues * Fix starting zIndex not set (check for falsey, including null and undefined, see this [article](https://codeburst.io/javascript-null-vs-undefined-20f955215a2#5317)). * Ensure \<map-extent> element doesn't get reparented when reordering. Remove TemplatedTileLayer.addTo function (redundant). * Merge functions _getCombinedExtentsLayerBounds and _setLayerElExtent. Remove getCombinedExtentsLayerBounds, make calls for this behaviour go through _setLayerElExtent only. * Restore extentPCRSFallback bounds template property, which contains the map-meta name=extent, used as the extent in case there are no map-extent elements with their inputs specifying native bounds for content. * Add test for meta extent use by templatedFeatures * Fix test failures for different types of layer. Ensure that extents that load slowly and which fire the `extentload` event are handled properly, which is more common with `<layer- src="...">` layers, and which are created (typically though not exclusively) through drag and drop. * Remove redundant call to _removeExtents (gets executed by the following map.removeLayer anyway) * Comment, clarify multipleExtents tests. * Comment, clarify multipleQueryExtents tests. Fix problem where the _extent._queries property was ignored during layer remove events, fixed. * Remove obsolete code from MapLayer.js * Update how templated layer / multiple extent opacity is managed. Co-authored-by: Anshpreet <[email protected]> Co-authored-by: Peter Rushforth <[email protected]>
1 parent fabeb42 commit b44bc70

19 files changed

+1377
-597
lines changed

src/layer.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,18 @@ export class MapLayer extends HTMLElement {
195195
let type = layerTypes[j];
196196
if(this.checked && layer[type]){
197197
if(type === "_templatedLayer"){
198-
for(let j =0;j<layer[type]._templates.length;j++){
199-
if(layer[type]._templates[j].rel ==="query") continue;
200-
total++;
201-
if(!(layer[type]._templates[j].layer.isVisible))count++;
198+
for(let i =0;i<layer._extent._mapExtents.length;i++){
199+
for(let j = 0; j < layer._extent._mapExtents[i].templatedLayer._templates.length; j++){
200+
if(layer._extent._mapExtents[i].templatedLayer._templates[j].rel ==="query") continue;
201+
total++;
202+
layer._extent._mapExtents[i].removeAttribute("disabled");
203+
layer._extent._mapExtents[i].disabled = false;
204+
if(!(layer._extent._mapExtents[i].templatedLayer._templates[j].layer.isVisible)){
205+
count++;
206+
layer._extent._mapExtents[i].setAttribute("disabled", "");
207+
layer._extent._mapExtents[i].disabled = true;
208+
}
209+
}
202210
}
203211
} else {
204212
total++;

src/mapml.css

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,9 @@ button.mapml-button:disabled,
649649
box-sizing: border-box;
650650
}
651651

652-
.mapml-layer-item {
652+
.mapml-layer-item,
653+
.mapml-layer-grouped-extents,
654+
.mapml-layer-extent {
653655
background-color: #fff;
654656
border: 1px solid #fff;
655657
margin: 0;
@@ -659,15 +661,18 @@ button.mapml-button:disabled,
659661
.mapml-layer-item:not(:last-of-type) {
660662
border-bottom: 1px solid #e3e3e3;
661663
}
662-
.mapml-layer-item[aria-grabbed="true"] {
664+
.mapml-layer-item[aria-grabbed="true"],
665+
.mapml-layer-extent[aria-grabbed="true"] {
663666
border: 1px solid #e3e3e3;
664667
border-radius: 0;
665668
}
666-
.mapml-layer-item:first-of-type {
669+
.mapml-layer-item:first-of-type,
670+
.mapml-layer-extent:first-of-type {
667671
border-top-left-radius: 4px;
668672
border-top-right-radius: 4px;
669673
}
670-
.mapml-layer-item:last-of-type {
674+
.mapml-layer-item:last-of-type,
675+
.mapml-layer-extent:last-of-type {
671676
border-bottom-left-radius: 4px;
672677
border-bottom-right-radius: 4px;
673678
}
@@ -776,3 +781,25 @@ label.mapml-layer-item-toggle {
776781
) {
777782
outline: 0!important;
778783
}
784+
785+
/*
786+
* Extent Elements in the Layer Control
787+
*/
788+
789+
.mapml-layer-item-settings .mapml-layer-extent {
790+
padding-inline-start: 1.8rem;
791+
}
792+
793+
.mapml-layer-item-settings .mapml-layer-extent .mapml-layer-item-properties{
794+
padding-inline-start: 0;
795+
}
796+
797+
.mapml-layer-item-settings .mapml-layer-extent .mapml-layer-item-opacity {
798+
padding-inline-start: 1.6rem;
799+
}
800+
801+
.mapml-layer-item-settings .mapml-layer-extent .mapml-layer-item-controls{
802+
position: absolute;
803+
right: 0;
804+
}
805+

src/mapml/handlers/ContextMenu.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ export var ContextMenu = L.Handler.extend({
417417
this._clickEvent = e;
418418
let elem = e.originalEvent.target;
419419
if(elem.closest("fieldset")){
420-
elem = elem.closest("fieldset").querySelector("span");
420+
elem = elem.closest("fieldset");
421+
elem = (elem.className === "mapml-layer-extent") ? elem.closest("fieldset").parentNode.parentNode.parentNode.querySelector("span") : elem.querySelector("span");
421422
if(!elem.layer.validProjection) return;
422423
this._layerClicked = elem;
423424
this._showAtPoint(e.containerPoint, e, this._layerMenu);

src/mapml/handlers/QueryHandler.js

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,14 @@ export var QueryHandler = L.Handler.extend({
3737
_queryTopLayer: function(event) {
3838
var layer = this._getTopQueryableLayer();
3939
if (layer) {
40+
if(layer._mapmlFeatures) delete layer._mapmlFeatures;
4041
this._query(event, layer);
4142
}
4243
},
4344
_query(e, layer) {
44-
var obj = {},
45-
template = layer.getQueryTemplates()[0],
46-
zoom = e.target.getZoom(),
45+
var zoom = e.target.getZoom(),
4746
map = this._map,
48-
crs = layer.crs,
47+
crs = layer._extent.crs, // the crs for each extent would be the same
4948
tileSize = map.options.crs.options.crs.tile.bounds.max.x,
5049
container = layer._container,
5150
popupOptions = {autoClose: false, autoPan: true, maxHeight: (map.getSize().y * 0.5) - 50},
@@ -59,7 +58,45 @@ export var QueryHandler = L.Handler.extend({
5958
tileMatrixClickLoc = tcrsClickLoc.divideBy(tileSize).floor(),
6059
tileBounds = new L.Bounds(tcrsClickLoc.divideBy(tileSize).floor().multiplyBy(tileSize),
6160
tcrsClickLoc.divideBy(tileSize).ceil().multiplyBy(tileSize));
62-
61+
62+
let point = this._map.project(e.latlng),
63+
scale = this._map.options.crs.scale(this._map.getZoom()),
64+
pcrsClick = this._map.options.crs.transformation.untransform(point,scale),
65+
contenttype;
66+
var templates = layer.getQueryTemplates(pcrsClick);
67+
68+
var fetchFeatures = function(template, obj, lastOne) {
69+
fetch(L.Util.template(template.template, obj), { redirect: 'follow' }).then((response) => {
70+
contenttype = response.headers.get("Content-Type");
71+
if (response.status >= 200 && response.status < 300) {
72+
return response.text();
73+
} else {
74+
throw new Error(response.status);
75+
}
76+
}).then((mapml) => {
77+
if (contenttype.startsWith("text/mapml")) {
78+
//if(!this.mapml) this.mapml = "";
79+
//this.mapml = this.mapml.concat(mapml);
80+
if(!layer._mapmlFeatures) layer._mapmlFeatures = [];
81+
let parser = new DOMParser(),
82+
mapmldoc = parser.parseFromString(mapml, "application/xml"),
83+
features = Array.prototype.slice.call(mapmldoc.querySelectorAll("map-feature"));
84+
if(features.length) layer._mapmlFeatures = layer._mapmlFeatures.concat(features);
85+
mapmldoc.features = layer._mapmlFeatures;
86+
if(lastOne) return handleMapMLResponse(mapmldoc, e.latlng);
87+
} else {
88+
return handleOtherResponse(mapml, layer, e.latlng);
89+
}
90+
}).catch((err) => {
91+
console.log('Looks like there was a problem. Status: ' + err.message);
92+
});
93+
};
94+
95+
for(let i = 0; i < templates.length; i++){
96+
97+
var obj = {},
98+
template = templates[i];
99+
63100
// all of the following are locations that might be used in a query, I think.
64101
obj[template.query.tilei] = tcrsClickLoc.x.toFixed() - (tileMatrixClickLoc.x * tileSize);
65102
obj[template.query.tilej] = tcrsClickLoc.y.toFixed() - (tileMatrixClickLoc.y * tileSize);
@@ -106,34 +143,14 @@ export var QueryHandler = L.Handler.extend({
106143
}
107144
}
108145

109-
let point = this._map.project(e.latlng),
110-
scale = this._map.options.crs.scale(this._map.getZoom()),
111-
pcrsClick = this._map.options.crs.transformation.untransform(point,scale),
112-
contenttype;
113-
114-
if(template.layerBounds.contains(pcrsClick)){
115-
fetch(L.Util.template(template.template, obj), { redirect: 'follow' }).then((response) => {
116-
contenttype = response.headers.get("Content-Type");
117-
if (response.status >= 200 && response.status < 300) {
118-
return response.text();
119-
} else {
120-
throw new Error(response.status);
121-
}
122-
}).then((mapml) => {
123-
if (contenttype.startsWith("text/mapml")) {
124-
return handleMapMLResponse(mapml, e.latlng);
125-
} else {
126-
return handleOtherResponse(mapml, layer, e.latlng);
127-
}
128-
}).catch((err) => {
129-
console.log('Looks like there was a problem. Status: ' + err.message);
130-
});
146+
if(template.extentBounds.contains(pcrsClick)){
147+
let lastOne = (i === (templates.length - 1)) ? true: false;
148+
fetchFeatures(template, obj, lastOne);
131149
}
132-
function handleMapMLResponse(mapml, loc) {
133-
let parser = new DOMParser(),
134-
mapmldoc = parser.parseFromString(mapml, "application/xml");
150+
}
151+
function handleMapMLResponse(mapmldoc, loc) {
135152

136-
for(let feature of mapmldoc.querySelectorAll('map-feature')){
153+
for(let feature of mapmldoc.features){
137154
if(!feature.querySelector('map-geometry')){
138155
let geo = document.createElement('map-geometry'), point = document.createElement('map-point'),
139156
coords = document.createElement('map-coordinates');
@@ -171,7 +188,7 @@ export var QueryHandler = L.Handler.extend({
171188
div.appendChild(c);
172189
// passing a latlng to the popup is necessary for when there is no
173190
// geometry / null geometry
174-
layer._totalFeatureCount = mapmldoc.querySelectorAll("map-feature").length;
191+
layer._totalFeatureCount = mapmldoc.features.length;
175192
layer.bindPopup(div, popupOptions).openPopup(loc);
176193
layer.on('popupclose', function() {
177194
map.removeLayer(f);

src/mapml/layers/ControlLayer.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ export var MapMLLayerControl = L.Control.Layers.extend({
8383
input[0].closest("fieldset").disabled = false;
8484
label[0].style.fontStyle = "normal";
8585
}
86+
// check if an extent is disabled and disable it
87+
if(this._layers[i].layer._extent && this._layers[i].layer._extent._mapExtents){
88+
for(let j = 0; j < this._layers[i].layer._extent._mapExtents.length; j++){
89+
let input = this._layers[i].layer._extent._mapExtents[j].extentAnatomy,
90+
label = input.getElementsByClassName("mapml-layer-item-name")[0];
91+
if(this._layers[i].layer._extent._mapExtents[j].disabled && this._layers[i].layer._extent._mapExtents[j].checked){
92+
label.style.fontStyle = "italic";
93+
input.disabled = true;
94+
} else {
95+
label.style.fontStyle = "normal";
96+
input.disabled = false;
97+
}
98+
}
99+
}
86100
}
87101

88102
},

src/mapml/layers/DebugLayer.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,23 @@ export var DebugVectors = L.LayerGroup.extend({
180180
this.addLayer(this._centerVector);
181181

182182
for (let i of id) {
183-
if (layers[i].layerBounds) {
184-
let boundsArray = [
185-
layers[i].layerBounds.min,
186-
L.point(layers[i].layerBounds.max.x, layers[i].layerBounds.min.y),
187-
layers[i].layerBounds.max,
188-
L.point(layers[i].layerBounds.min.x, layers[i].layerBounds.max.y)
189-
];
183+
if (layers[i].layerBounds || layers[i].extentBounds) {
184+
let boundsArray;
185+
if(layers[i].layerBounds){
186+
boundsArray = [
187+
layers[i].layerBounds.min,
188+
L.point(layers[i].layerBounds.max.x, layers[i].layerBounds.min.y),
189+
layers[i].layerBounds.max,
190+
L.point(layers[i].layerBounds.min.x, layers[i].layerBounds.max.y)
191+
];
192+
} else {
193+
boundsArray = [
194+
layers[i].extentBounds.min,
195+
L.point(layers[i].extentBounds.max.x, layers[i].extentBounds.min.y),
196+
layers[i].extentBounds.max,
197+
L.point(layers[i].extentBounds.min.x, layers[i].extentBounds.max.y)
198+
];
199+
}
190200
let boundsRect = projectedExtent(boundsArray, {
191201
color: colors[j % colors.length],
192202
weight: 2,

src/mapml/layers/FeatureLayer.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export var MapMLFeatures = L.FeatureGroup.extend({
1717

1818
this._layers = {};
1919
if(this.options.query){
20-
this._mapmlFeatures = mapml;
20+
this._mapmlFeatures = mapml.features ? mapml.features: mapml;
2121
this.isVisible = true;
2222
let native = this._getNativeVariables(mapml);
2323
this.options.nativeZoom = native.zoom;
@@ -72,8 +72,8 @@ export var MapMLFeatures = L.FeatureGroup.extend({
7272

7373

7474
showPaginationFeature: function(e){
75-
if(this.options.query && this._mapmlFeatures.querySelectorAll("map-feature")[e.i]){
76-
let feature = this._mapmlFeatures.querySelectorAll("map-feature")[e.i];
75+
if(this.options.query && this._mapmlFeatures[e.i]){
76+
let feature = this._mapmlFeatures[e.i];
7777
this.clearLayers();
7878
this.addData(feature, this.options.nativeCS, this.options.nativeZoom);
7979
e.popup._navigationBar.querySelector("p").innerText = (e.i + 1) + "/" + this.options._leafletLayer._totalFeatureCount;

0 commit comments

Comments
 (0)