Reputation: 133
I have posted previously in the gis forum (Alt below) though there is little activity so i am trying my luck here. This is also, fundamentally i think, a js object array question. There are numerous similar questions but i just can't get a solution that works for the object structure i have to deal with.
Caveats aside;
The issue: Get the information returned from a (unknown) number of objects nested within an object array parsed so they can be extracted, formatted and displayed in a human readable way. E.g;
Layer id <--- currently returned as val.layer.id (see snippet)
key1 : value1 <
key2 : value2 <-- returns in console.log as Object at val.properties
key3 : value3 <
Layer id
key1 : value1
key2 : value2
Layer id...
I just need each 'features.layer.id' with it's associated 'features.properties', the keys and values of which are unknown and differ between layers (an object located at features.properties). These feature positions are consistent in MapBox and so a solution here should be applicable to future users.
Current code; Commented out are a scattering of my attempts to access and display the required values. The 'features' elementID is the info panel. features is otherwise the returned nested object (see sample).
concattedjson currently produced an error ("unexpected token N") on first letter of first layer title.
map.on('click', function (e) {
map.featuresAt(e.point, {radius: 5, layer: lyrlist}, function (err, features) {
if (err) throw err;
var keys = Object.keys(features);
var val = "";
for (var i = 0; i < keys.length; i++) {
val = features[keys[i]];
//document.getElementById('features').innerHTML = '<b>'+val.layer.id+'</b>';
//console.log(val.layer.id,val.properties);
//console.log(val.properties); shows each layer properties on click
//console.log(val.layer.id); shows each layer title on click
//console.log(val);
var lyrid = val.layer.id;
var prop = val.properties;
concattedjson = JSON.stringify(JSON.parse(lyrid).concat(JSON.parse(prop)));
}
document.getElementById('features').innerHTML = concattedjson
//document.getElementById('features').innerHTML = JSON.stringify(val.layer, ['id'], 2);
//document.getElementById('features').innerHTML = JSON.stringify(val.properties, null, 2);
});
});
Sample of JSON containing two 'layers'
[
{
"layer": {
"id": "Nature Improvement Area",
"minzoom": 7,
"interactive": true,
"paint": {
"fill-opacity": 0.3,
"fill-color": "hsl(0, 24%, 24%)"
},
"type": "fill",
"source": "mapbox://mbbdev.8uf2j3ka",
"source-layer": "lcr_nia_v1_region",
"layout": {
"visibility": "visible"
}
},
"type": "Feature",
"geometry": null,
"properties": {
"NIA_Focu00": "Netherley Brook and Ditton Brook Corridor",
"NIA_Focu01": "INSERT LINK TO PROFILE DOC",
"NIA_Focus_": "07"
},
"id": 16
},
{
"layer": {
"id": "Liverpool City Region",
"minzoom": 6,
"interactive": true,
"paint": {
"fill-opacity": 0.2,
"fill-antialias": true,
"fill-color": "hsl(0, 4%, 40%)"
},
"type": "fill",
"source": "mapbox://mbbdev.67id5f6x",
"source-layer": "lcr_district_boundary_region",
"filter": [
"==",
"$type",
"Polygon"
]
},
"type": "Feature",
"geometry": null,
"properties": {
"AREA_HA": 8618.7,
"NAME": "Knowsley"
},
"id": 1
}
]
Upvotes: 2
Views: 4413
Reputation: 28638
Here's how you iterate the features
object, and create something human readable out of it. Explanation in the comments:
map.on('click', function (e) {
map.featuresAt(e.point, {
radius: 5,
}, function (err, features) {
if (err) throw err;
// Grab the 'ul' element with ID 'features' from the DOM
var featureList = document.getElementById('features');
// Empty the list on every click
featureList.innerHTML = '';
// Iterate the features array
for (var i = 0; i < features.length; i++) {
// Create a listitem for each feature
var featureItem = document.createElement('li');
// Set the feature's listitem's content to the layer's ID
featureItem.textContent = features[i].layer.id;
// Append the featureitem to the featurelist
featureList.appendChild(featureItem);
// Create a new list for the item's properties
var propertyList = document.createElement('ul');
// Append the list to the feature's listitem
featureItem.appendChild(propertyList);
// Create convenience var for the properties object
var properties = features[i].properties;
// Iterate the properties object
for (var property in properties) {
// Create new listitem for every property
var propertyItem = document.createElement('li');
// Set property's listitem's textcontent to key/value
propertyItem.textContent = property + ': ' + properties[property];
// Append property's listitem to the feature's propertylist.
propertyList.appendChild(propertyItem);
}
}
});
});
Here's a working example on Plunker: http://plnkr.co/edit/iqntvRFTcWK1hgpzPBvX?p=preview
You might want to read this if you want to grasp the concept of object properties and how to access them:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors
Upvotes: 3