1
votes

Am teaching myself JavaScript using Leaflet to create some simple web maps. This step is to add layer control to the map. I'm testing control for both the base layers and the overlay.

I'm getting a JS type error. I've used some debugging but can't find what I'm doing wrong.

The error is occurring when the "layers" option for the Map API is used. If I remove that option, the error doesn't occur (obviously the map doesn't work, so just done for debugging).

Using debugger in Firefox, the content of the overlay layer groups looks OK. I would appreciate another set of eyes on this.

// Creates a variable to hold the attribution including OSM, Creative Commons license,and Mapbox imagery; this is done via variable because two tileLayers will each need attribution
    var mbAttr = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
                '<a href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA</a>, ' +
                'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    mbUrl = 'https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png';

    var grayscale = L.tileLayer(mbUrl, {id: 'examples.map-20v6611k', attribution: mbAttr}),
        streets = L.tileLayer(mbUrl, {id: 'examples.map-i875mjb7',   attribution: mbAttr});

// var myURL = jQuery( 'script[src$="kcdfp.js"]' ).attr( 'src' ).replace( 'kcdfp.js', '' );  // Gets the URL and removes the file name, which will be replaced in the icon API; can't get it to work
    var myURL = 'http://www.myspatialhome.org/';  // Sets the url for icon images

// Criteria for overlay layers
// In Active -1=YES, 0 = NO
// Create new layerGroups for overlay
    var active = new L.layerGroup();
    var inactive = new L.layerGroup();

// Create Marker icons
    var myIcon = L.icon({
    iconUrl: myURL + 'images/pin24.png',
    iconRetinaUrl: myURL + 'images/pin48.png',
    iconSize: [29, 24],
    iconAnchor: [9, 21],
    popupAnchor: [0, -14]
});

// Loop through the entire JSON file
for ( var i=0; i < kcdfp.length; ++i ) 
    {
    if (kcdfp[i].In_Active == 0){  // Inactive=no, i.e. Active
        L.marker( [kcdfp[i].Lat, kcdfp[i].Lon], {icon: myIcon} )
        .bindPopup( '<a href="ATL_map_service_test_leaflet_url.htm" target="_blank">' + kcdfp[i].Last_Name + '</a>' )
        .addTo( active );  // Add to active layer group
    }
    else {  // Otherwise show a Inactive
        L.marker( [kcdfp[i].Lat, kcdfp[i].Lon], {icon: myIcon} )
        .bindPopup( '<a href="ATL_map_service_test_leaflet_url.htm" target="_blank">' + kcdfp[i].Last_Name + '</a>' )
        .addTo( inactive );  // Add to inactive layer group
        }
}

// Create the map
var map = L.map( 'map', {
        center: [47.5, -121.95],
        minZoom: 10,
        zoom: 10,
        layers: [streets, active, inactive]  // ERROR
});
// Set variables for layer control
    var baseLayers = {
        "Grayscale": grayscale,
        "Streets": streets
    };
    var overlays = {
        "Active": active,
        "Inactive": inactive
    };  // Sets the other variable for layer control

    L.control.layers(baseLayers, overlays).addTo(map);  // Adds a layer control to the map

Edit: Further testing leads me to think the way I'm creating the layerGroups is wrong. I changed the Map to only include the street tileLayer and added the layerGroups with an .addTo(map) clause.

An error appears to happen when the layerGroups are added to the map.

It appears layerGroups wants an array. I changed the Marker with an .addLayer clause. Does layerGroup see that as an array element?

// Loop through the entire JSON file
for ( var i=0; i < kcdfp.length; ++i ) 
    {
    if (kcdfp[i].In_Active == 0){  // Inactive=no, i.e. Active
        L.marker( [kcdfp[i].Lat, kcdfp[i].Lon], {icon: myIcon} )
        .bindPopup( '<a href="ATL_map_service_test_leaflet_url.htm" target="_blank">' + kcdfp[i].Last_Name + '</a>' )
        .addLayer( active );  // Add to active layer group
    }
    else {  // Otherwise show a Inactive
        L.marker( [kcdfp[i].Lat, kcdfp[i].Lon], {icon: myIcon} )
        .bindPopup( '<a href="ATL_map_service_test_leaflet_url.htm" target="_blank">' + kcdfp[i].Last_Name + '</a>' )
        .addLayer( inactive );  // Add to inactive layer group
        }
}
2
BTW, I'd also appreciate getting instructions on where I could have looked in FF debugger to see the problem. I'm as interested in learning more about how to debug as getting the current error fixed. - TomC
halfer: First, as a new forum user I hope this is the right way to respond to your input. I appreciate taking the time to help me with posting protocol. I was tempted along the way to delete all the JS posted originally and replace it entirely. Is that a good or bad idea? - TomC

2 Answers

0
votes

Your add layer flow is a bit reversed.

They should look like

    var newMarker = L.marker( [kcdfp[i].Lat, kcdfp[i].Lon], {icon: myIcon} ).bindPopup( '<a href="ATL_map_service_test_leaflet_url.htm" target="_blank">' + kcdfp[i].Last_Name + '</a>' )
    active.addLayer(newMarker);  // Add to active layer group
0
votes

The root problem turned out to be data errors (i.e. lat/lon NULL). The testing included both the original JS and that modified based on the proposed answer that adds "var newMarker" to the L.marker APIs. The original JS was based on Leaflet tutorial 6.

I'm curious if there are advantages to picking one approach over the other.

Thanks for answers. It helps my JS/Leaflet learning.