Reputation: 33
I'm trying to tie an onClick for each marker to call a function that populates data associated with that marker into an element on the page, but the iterator(i) seems to be overwriting itself (every marker acts as if it's the last one iterated through), but only when used within the onClick function associated with the marker. i works as expected everywhere else. Ignore the console.log lines, I was just trying to track where the variable was breaking. Any help would be appreciated.
var markers = L.markerClusterGroup({maxClusterRadius: 100, disableClusteringAtZoom: 9});
function addMarkers(data, dataset, h) {
// Create a new marker cluster group
var popup = '';
// Loop through data
for (var i = 0; i < Object.keys(data).length; i++) {
// Set the data location property to a variable
var lat = data[i].latitude;
var lon = data[i].longitude;
var location = [lat, lon];
var value = i-1;
// Check for location property
if (location) {
if (dataset.icon == bigfootIcon) {
popup = `${data[i].date}<br/>
${data[i].county}, ${data[i].state}<br/><br/>
${data[i].title}`;
} else if (dataset.icon == ufoIcon) {
popup = `${data[i].date}<br/>
${data[i].city}, ${data[i].state}<br/><br/>
${data[i].title}`;
} else if (dataset.icon == dogmanIcon) {
popup = `${data[i].date}<br/>
${data[i].location}, ${data[i].state_abbrev}`;
} else if (dataset.icon == hauntedIcon) {
popup = `${data[i].location}<br/>
${data[i].city}, ${data[i].state_abbrev}`
};
};
// Add a new marker to the cluster group and bind a pop-up
var marker = L.marker(location, {icon: dataset.icon}).bindPopup(popup).on('click', function() {
// onToggle(dataset);
// var value = i-1;
console.log(data[value]);
onChange(data[value], dataset, h)
});
// console.log(marker);
marker.addTo(markers);
};
// Add our marker cluster layer to the map
map.addLayer(markers);
};
// Called elsewhere to prep for calling the onChange function from a dropdown
function dropdownChange(response, dataset, h) {
var dropdown = dataset.dropdown;
var value = dropdown.property('value');
console.log(value);
dropdown.on('change', function() {
onChange(response[value], dataset, h);
});
};
function onChange(response, dataset, h) {
var dropdown = dataset.dropdown
value = dropdown.property('value');
console.log(value);
console.log(response)
document.getElementById('summaryText').style.display = 'block';
document.getElementById('summaryText').style.maxHeight = `calc(100% - ${h}px)`;
stats.html('');
if (dropdown == datasets[0].dropdown) {
stats.html(`<p>Location: ${response.county}, ${response.state}<br/>
Date: ${response.date}<br/>
Classification: ${response.classification}<br/>
<br/>
Incident:</p>`);
} else if (dropdown == datasets[1].dropdown) {
stats.html(`<p>Location: ${response.city}, ${response.state}<br/>
Date: ${response.date}<br/>
Duration: ${response.duration}<br/>
Shape: ${response.shape}<br/>
<a href='${response.report_link}' target="_blank">Report Link</a><br/>
<br/>
Incident:</p>`);
} else if (dropdown == datasets[2].dropdown) {
stats.html(`<p>Location: ${response.location}, ${response.state_abbrev}<br/>
Date: ${response.date}<br/>
<br/>
Incident:</p>`);
} else if (dropdown == datasets[3].dropdown) {
stats.html(`<p>Location: ${response.city}, ${response.state_abbrev}<br/>
<br/>
Incident:</p>`);
};
summaryText.text('');
summaryText.text(response.summary);
map.flyTo([response.latitude, response.longitude], 15);
};
Upvotes: 3
Views: 129
Reputation: 53205
This is a classic JavaScript var
scope / closure issue.
TL; DR: just replace var value
by const value
and the issue should be gone.
In JavaScript, var
is function scoped, therefore your value
variable is the same throughout all your for loop iterations (but its value is changed in each iteration). At the end of the loop, its value is the last i - 1
.
It is then in the closure of all your Markers click event listeners, but they all reference the exact same value
variable.
With const
keyword, you now have a block scoped variable, much more similar to other programming languages. It is unique to every loop iteration, and each of your Marker click listener has its own value
in its closure.
Upvotes: 2
Reputation: 11338
I'm not sure if this works but try to add the value directly to the marker and then read it out (from the marker) in the click
function:
// Add a new marker to the cluster group and bind a pop-up
var marker = L.marker(location, {icon: dataset.icon}).bindPopup(popup);
marker.value = value;
marker.on('click', function(e) {
var value = e.target.value;
console.log(data[value]);
onChange(data[value], dataset, h)
});
marker.addTo(markers);
Upvotes: 1