Reputation: 567
I'm trying to display three maps on one page with leaflet.js and mapquests API. I've created a jQuery for-loop
to read a unique postal code, then convert it (via mapquest) to latitude and longitude, and lastly create three maps, and add the matching latitude and longitude to every map. This would then result in three different maps, displayed on one page.
I've somewhat achieved this with the code below. Every "card" has its own card number (from 1 to 3), postal code, and corresponding map and map ID.
Edit I also get this jQuery error:
jQuery.Deferred exception: t is undefined addTo@https://unpkg.com/[email protected]/dist/leaflet.js:5:64070
MYWEBSITEURL/map.js:38:6
e@https://code.jquery.com/jquery-3.5.1.min.js:2:30005
l/</t<@https://code.jquery.com/jquery-3.5.1.min.js:2:30307
undefined
The issue I now have is that when my jQuery runs I get this console error: TypeError: t is undefined
. I've narrowed it down to it having something to do with either the L.tileLayer()
and/or L.circle()
functions. I've added the latest jQuery and leaflet.js to the page.
Edit Changed the question after @ivansanchez answer, but still the same issues.
Edit Changed the leaflet.js
to leaflet-sr.js
and I now get the error: TypeError: map is undefined
map.js:
$(document).ready(function(){
var postalCodes = [];
var latLng = [];
var lat = [];
var lng = [];
var maps = [];
for(var n = 0; n < 3; n++) {
console.log('Maps for-loop count: '+n);
postalCodes.push($('.card'+[n]+' .card__info--postal > span').html());
$.ajax({ // Get lat & long from postal code
async: false,
url: 'https://www.mapquestapi.com/geocoding/v1/address?key=MYAPIKEY&postalCode='+postalCodes[n]+'&country=finland',
success: function(obj) {
latLng[n] = obj.results[0].locations[0].latLng;
lat[n] = latLng[n].lat;
lng[n] = latLng[n].lng;
},
error: function(xhr) {
console.log('Map error', xhr);
}
});
console.log(latLng[n], lat[n], lng[n]);
var map = L.map('mapid'+[n]).setView([lat[n], lng[n]], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'MYAPIKEY'
}).addTo(maps[n]);
L.circle([lat[n], lng[n]], { // Map out area of the postal code
color: 'rgb(218, 65, 103)',
fillColor: 'rgb(218, 65, 103)',
fillOpacity: 0.5,
radius: 500
}).addTo(maps[n]);
maps.push(map);
}
});
Upvotes: 0
Views: 970
Reputation: 19069
You're doing...
var maps = [ L.map('mapid'+[n]).setView([lat[n], lng[n]], 13) ]; // Creates three maps, that corresponds with three mapids in my HTML
...and that doesn't do what you think it does. You're creating an array of one element, and assigning it to maps
, and you're doing that three times. Therefore, at the second pass of the loop, when the code refers to maps[1]
, that has an undefined
value.
Instead, you probably want to do something like...
var maps = [];
for(var n = 0; n < 3; n++) {
/* stuff */
maps.push( L.map( /*stuff*/ ) );
L.tileLayer( /* stuff */ ).addTo(maps[n]);
}
...or even...
var maps = [];
for(var n = 0; n < 3; n++) {
/* stuff */
var map = L.map( /*stuff*/ );
L.tileLayer( /* stuff */ ).addTo(map);
maps.push(map);
}
On the other hand, you have a good ol' race condition regarding the values of latLng[n]
, lat[n]
and lng[n]
. Since those values are only set when the network operation has finished (since AJAX is async, etc etc), they are (most probably) undefined
when they are used. You might want to delay adding data to each map until you actually got said data, like e.g.
var maps = [];
for(var n = 0; n < 3; n++) {
var map = L.map( /*stuff*/ );
fetch(url)
.then(function(response){return response.json})
.then(function(json)){
L.circle(json.results[0].locations[0]).addTo(map);
});
L.tileLayer( /* stuff */ ).addTo(map);
maps.push(map);
}
Note that the sequence of events here is: a network request is initiated, the map is instantiated, the tilelayer is instantiated, the network request completes, the circle gets instantiated.
(And why yes, I prefer the fetch API over jQuery any day).
Remember that, in Leaflet, it's usually nice to change leaflet.js
into leaflet-src.js
to get better stack traces, and that using the browser's developer tools to set breakpoints prior to exceptions will allow you to see which values are undefined
at that time.
Upvotes: 1
Reputation: 11348
Change your code to:
maps[n] = L.map('mapid'+[n]).setView([lat[n], lng[n]], 13);
Upvotes: 0