Ashlander
Ashlander

Reputation: 33

Using an iterator within L.marker

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

Answers (2)

ghybs
ghybs

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

Falke Design
Falke Design

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

Related Questions