Reputation: 181
I have the following markercollection.json file with several geographical objects in an array called features
.
{
"features":
[
{
"name": "Point A",
"address": {
"street": "228 Park Ave S",
"zipcode": "10003",
"city": "New York"
},
"description": "Sample description for point A",
"iconFile": "icon-marker-iconsample-a.png",
"filterPrimary": "hotel",
"year": "2014"
},
{
"name": "Point B",
"address": {
"street": "542 W. 27th Street",
"zipcode": "10001",
"city": "New York"
},
"description": "Sample description for point B",
"iconFile": "icon-marker-iconsample-b.png",
"filterPrimary": "pub",
"year": "2015"
}
]
}
I am using the leaflet JavaScript library to put corresponding markers on a map. Since I do not have the longitudes and latitudes I have pass the object's address
to a geocoding service. For this I am currently using mapbox, but I also tried with OSM nominatim. Both work as expected.
The mapbox geocoding API expects a callback function to be passed to do something with the resulting data (i.e. longitude and latitude).
So far I have worked out how to pass the geo-objects to the geocoder and have my addMarkers
callback function add the corresponding markers to my map. In addition to this I would also like to have my markers have different icons depending on the iconFile
value in the original JSON file.
I haven't been able to figure out where to build and subsequently add my customized markers. I tried building the marker icon for every loop but that leaves me with the same icon for all markers (see my screenshot).
I assume this is because the loop has finished before my addMarkers
function is triggered, so the value of sIconFile
is that of the last loop iteration.
Do I have to chain another callback, and if so, what's the best way to do this?
// Pass Mapbox access token and set initial map view
L.mapbox.accessToken = ACCESS_TOKEN;
var myMap = L.mapbox.map('map','mapbox.streets').setView([40.730610, -73.935242], 13);
//
var promise = $.getJSON('data/markercollection.json')
.then(function(data) {
/**
* Iterate through fetched data and do something...
*/
for (var i = 0; i < data.features.length; i++) {
// Build address string for passing to geocoder
var sAddress = data.features[i].address.street + ', ' + data.features[i].address.zipcode + ', ' + data.features[i].address.city;
// Icon file string variable
var sIconFile = data.features[i].iconFile;
/**
* Query Mapbox geocoder with address string
* and pass reply to addMakers function as per
* mapbox geocoder API
*/
L.mapbox.geocoder('mapbox.places').query(sAddress, addMarkers);
// Add markers to geocoded latitudes and longitudes to map
function addMarkers(err, geocoderCallbackData) {
console.log(sIconFile); // accessing the variable here does not work :(
L.marker(geocoderCallbackData.latlng).addTo(myMap);
}
}
// Basic error-handling
}, function() {
console.log('An error has occured!');
});
Upvotes: 0
Views: 344
Reputation: 19288
By looping through data.features
with forEach(fn)
instead of a for(...)
loop, you will benefit from the local scope afforded by fn
.
Therefore :
data.features.forEach(function(feature) {
var sAddress = feature.address.street + ', ' + feature.address.zipcode + ', ' + feature.address.city;
var sIconFile = feature.iconFile;
L.mapbox.geocoder('mapbox.places').query(sAddress, addMarkers);
function addMarkers(err, geocoderCallbackData) {
console.log(sIconFile);
L.marker(geocoderCallbackData.latlng).addTo(myMap);
}
});
Upvotes: 3