1

The basic functionality of my web map is to allow users to switch between choropleth views using a dropdown menu. This basically works, but the issue I'm now having is with the info box that allows a user to get information about the polygon when they hover over it.

I can only get that functionality to work correctly for one choropleth map at a time. For the choropleth that doesn't work, the hover information will not change on the map and after moving the mouse away from the polygon, the color automatically changes back to the first choropleth map, rather than staying with the intended color selection. I'm not sure exactly where my code is wrong, probably within my "Hover Functionality" lines:

//----------------------------------
// EV COUNT CHOROPLETH LEGEND - lower right corner
//----------------------------------

var legend = L.control({
  position: "bottomright"
});

legend.onAdd = function(map) {
  var div = L.DomUtil.create("div", "info legend"),
    grades = [1, 100, 500, 1000, 5000, 10000, 25000, 50000, 154000],
    labels = [],
    from,
    to;
  // loop through "grades" and create respective entries - colored box + range
  for (var i = 0; i < grades.length; i++) {
    from = grades[i];
    to = grades[i + 1];

    labels.push( //cf. .legend i style in css - 17x17 box
      '<i style="background:' +
        getColor(from + 1) +
        '"></i> ' +
        from +
        (to ? "&ndash;" + to : "+") // catching the last case, i.e., i+1 is not defined anymore
        // condition ? exprIfTrue : exprIfFalse
    );
  }
  //debugger;
  div.innerHTML = labels.join("<br>");
  return div;
};

legend.addTo(map);

//-----------------------------------------------
// INFO CONTROL FOR EV COUNT POPUP ON MOUSE HOVER - lower left corner
//-----------------------------------------------

var info = L.control({
  position: "bottomleft"
});

info.onAdd = function(map) {
  this._div = L.DomUtil.create("div", "info");
  this.update();
  return this._div;
};

info.update = function(vehicles) {
  this._div.innerHTML =
    "<h4>EV Registration</h4>" +
    (vehicles
      ? "<b>" + vehicles.name + "</b><br>" + vehicles.evcount + " registered electric vehicles"
      : "Hover over a county");
      // condition ? exprIfTrue : exprIfFalse
};

info.addTo(map);

//-----------------------------------------------
// FUNCTIONS FOR HANDLING THE POPUPS AND
// THE STYLING OF THE COUNTY POLYGONS - EV COUNT
//-----------------------------------------------

// Create chorolpleth map and get associated color depending on EV count value
function getColor(d) {
  return d > 154000 ? "#004529" : 
         d > 50000  ? "#006837" :
         d > 25000  ? "#238443" :
         d > 10000  ? "#41ab5d" :
         d > 5000   ? "#78c679" :
         d > 1000   ? "#addd8e" :
         d > 500    ? "#d9f0a3" :
         d > 100    ? "#f1fcb9" :
                      "#e5e5ce" ;
         
}

function style(feature) {
  return {
    weight: 2,
    opacity: 1,
    color: "white",
    dashArray: "3",
    fillOpacity: 0.7,
    fillColor: getColor(feature.properties.evcount)
  };
}

//-----------------------------------------------
// GRAY OUTLINE MOUSE HOVER FUNCTIONALITY
//-----------------------------------------------

function highlightFeature(e) {
  var layer = e.target;

  layer.setStyle({
    weight: 4,
    color: "#666",
    dashArray: "",
    fillOpacity: 0.7
  });

  if (!L.Browser.ie && !L.Browser.opera) {
    layer.bringToFront();
  }
  info.update(layer.feature.properties);
}

function resetHighlight(e) {
  geojson.resetStyle(e.target);
  info.update();
}

function zoomToFeature(e) {
  map.fitBounds(e.target.getBounds());
}

function onEachFeature(feature, layer) {
  layer.on({
    //addEventListeners
    mouseover: highlightFeature, // mouse moves over shape
    mouseout: resetHighlight, // mouse leaves shape
    click: zoomToFeature // click on shape and map will zoom
  });
}

var geojson;

var counties=
    "https://rjankows88.carto.com/api/v2/sql?format=GeoJSON&q=SELECT * FROM public.california";
console.log("County Query: " + counties);

$.getJSON(counties, function(cartodbdata2) {
  geojson = L.geoJson(cartodbdata2, {
    // add popup with info to each geosjon feature
    style: style, //style polygons
    onEachFeature: onEachFeature //attached popup behavior
  }).addTo(map);
    map.fitBounds(geojson.getBounds()); // zooms to fit data
});

//----------------------------------
// POPULATION CHOROPLETH LEGEND - lower right corner
//----------------------------------

var poplegend = L.control({
  position: "bottomright"
});

poplegend.onAdd = function(map) {
  var div = L.DomUtil.create("div", "info legend"),
    grades = [1000, 65000, 155000, 280000, 550000, 1150000, 2470000, 3330000, 11000000],
    poplabels = [],
    from,
    to;
  // loop through "grades" and create respective entries - colored box + range
  for (var i = 0; i < grades.length; i++) {
    from = grades[i];
    to = grades[i + 1];

    poplabels.push( //cf. .legend i style in css - 17x17 box
      '<i style="background:' +
        getColorpop(from + 1) +
        '"></i> ' +
        from +
        (to ? "&ndash;" + to : "+") // catching the last case, i.e., i+1 is not defined anymore
        // condition ? exprIfTrue : exprIfFalse
    );
  }
  //debugger;
  div.innerHTML = poplabels.join("<br>");
  return div;
};


poplegend.addTo(map);

//-----------------------------------------------
// INFO CONTROL FOR POPULATION POPUP ON MOUSE HOVER - lower left corner
//-----------------------------------------------

var popinfo = L.control({
  position: "bottomleft"
});

popinfo.onAdd = function(map) {
  this._div = L.DomUtil.create("div", "info");
  this.update();
  return this._div;
};

popinfo.update = function(population) {
  this._div.innerHTML =
    "<h4>Population Estimate (2019) </h4>" +
    (population
      ? "<b>" + population.name + "</b><br>" + population.pop2019 + " people per county"
      : "Hover over a county");
      // condition ? exprIfTrue : exprIfFalse
};

popinfo.addTo(map);

//-----------------------------------------------
// FUNCTIONS FOR HANDLING THE POPUPS AND
// THE STYLING OF THE COUNTY POLYGONS - POPULATION
//-----------------------------------------------

// Create chorolpleth map and get associated color depending on population
function getColorpop(p) {
  return p > 11000000 ? "#034e7b" : 
         p > 3330000  ? "#0570b0" :
         p > 2470000  ? "#3690c0" :
         p > 1150000  ? "#74a9cf" :
         p > 550000   ? "#a6bddb" :
         p > 280000   ? "#d0d1e6" :
         p > 155000   ? "#ece7f2" :
         p > 65000    ? "#fff7fb" :
                      "#f0f0f0" ;
         
}

function style2(feature) {
  return {
    weight: 2,
    opacity: 1,
    color: "white",
    dashArray: "3",
    fillOpacity: 0.7,
    fillColor: getColorpop(feature.properties.pop2019)
  };
}

//-----------------------------------------------
// GRAY OUTLINE MOUSE HOVER FUNCTIONALITY
//-----------------------------------------------

function highlightFeature(e) {
  var layer2 = e.target;

  layer2.setStyle({
    weight: 4,
    color: "#666",
    dashArray: "",
    fillOpacity: 0.7
  });

  if (!L.Browser.ie && !L.Browser.opera) {
    layer2.bringToFront();
  }
  popinfo.update(layer2.feature.properties);
}

function resetHighlight(e) {
  geojson2.resetStyle(e.target);
  popinfo.update();
}

function zoomToFeature(e) {
  map.fitBounds(e.target.getBounds());
}

function onEachFeature(feature, layer2) {
  layer2.on({
    //addEventListeners
    mouseover: highlightFeature, // mouse moves over shape
    mouseout: resetHighlight, // mouse leaves shape
    click: zoomToFeature // click on shape and map will zoom
  });
}

var geojson2;

var population =
    "https://rjankows88.carto.com/api/v2/sql?format=GeoJSON&q=SELECT * FROM public.california";
console.log("Population Query: " + population);

$.getJSON(population, function(cartodbdata3) {
  geojson2 = L.geoJson(cartodbdata3, {
    // add popup with info to each geosjon feature
    style: style2, //style polygons
    onEachFeature: onEachFeature //attached popup behavior
  }).addTo(map);
    map.fitBounds(geojson2.getBounds()); // zooms to fit data
});

var evlayer = {legend, info, geojson};

var poplayer = {poplegend, popinfo, geojson2};

//-----------------------------------------------
// CONTROL FOR DROPDOWN
//-----------------------------------------------

var myDropdown = L.Control.extend({
  options: {
    position: "topleft"
  },
  onAdd: function(map) {
    this._div = L.DomUtil.create("div", "myDropdown");
    this._div.innerHTML =
      '<h2 id="title">Select a layer </h2>' + 
      '<select id="selector">' +
      '<option value="init">Any</option>' +
      '<option value="evlayer">Electric Vehicles per County</option>' +
      '<option value="poplayer">Population Estimate per County</option>' +
      "</select>";
    L.DomEvent.disableClickPropagation(this._div);
    return this._div;
  }
});
map.addControl(new myDropdown());

var layer_select = L.DomUtil.get("selector");
//prevent clicks on the selector from propagating through to the map
//(otherwise popups will close immediately after opening)
L.DomEvent.addListener(layer_select, "click", function(e) {
  L.DomEvent.stopPropagation(e);
});
L.DomEvent.addListener(layer_select, "change", change);

//-----------------------------------------------
// DROPDOWN MENU FUNCTIONALITY
//-----------------------------------------------

function change(e) {
  var showEvlayer = false;
  var showPoplayer = false;
  var evlayerShown = map.hasLayer(geojson);
  var poplayerShown = map.hasLayer(geojson2);
  
  switch ($('select').val()) {
    case 'init':
      showEvlayer = false;
      showPoplayer = false;
      break;
    case 'evlayer':
      showEvlayer = true;
      break;
    case 'poplayer':
      showPoplayer = true;
  }
  if (evlayerShown) {
    if (!showEvlayer) {
      map.removeLayer(geojson);
      map.removeControl(legend);
      map.removeControl(info);
    }
    }
  else if (showEvlayer) {
    map.addLayer(geojson);
    map.addControl(legend);
    map.addControl(info);
  }
  if (poplayerShown) {
    if (!showPoplayer) {
      map.removeLayer(geojson2);
      map.removeControl(poplegend);
      map.removeControl(popinfo);
    }
    }
  else if (showPoplayer) {
    map.addLayer(geojson2);
    map.addControl(poplegend);
    map.addControl(popinfo);
  }
};
1
  • Thanks for the tip. My code as been added to the body of the question Apr 27 at 16:49

1 Answer 1

0

Your problems have nothing to do with GIS, it's pure JS stuff. It was pointed out in the answer to your previous question that you used the same style style for both of your choropleth layers.

The goes also for your onEachFeature, highlightFeature and resetHighlight functions. They are currently the same for both of your choropleth layers, so the second definition overrides the first one. You must use separate functions for each layer.

2
  • Hi, I tried that - I changed the name of the style function, and I also tried changing the names of each of those second functions as well. It did not produce the desired functionality... It's not reflected here because I changed it back to my original script since it was still not really working Apr 27 at 18:10
  • See working CodePen: codepen.io/TomazicM/pen/popMrdO
    – TomazicM
    Apr 27 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.