[GIS] Leafletjs : combine location data in geoJSON/KML/GPX with other information in CSV through key field

combinecsvgeojsonleaflet

I've been able to load CSV having lat-long co-ordinates into leaflet using this useful solution. Looking for ways to cross-link co-ordinates from a different source and data from another. Describing the use case:
Polygons representing wards in a city are loaded through geoJSON or KML or GPX file, each object having a unique name like "Ward 01". This file has the polygon co-ordinates of each unit, and its name, but not much else. Now, there is another file, a CSV, like this:

name,detail1,detail2,detail3,detail4,detail5
Ward 01,23,45,10,54,30
Ward 02,78,98,14,20,53

..and THIS has the details that we want to see in a popup when the user clicks on a polygon, or mouses over and we display on an info panel, etc etc.
How does one combine the two? So far I've seen solutions where the location data and the details are all in the same file. Real-world cases aren't that simple 😉

The "name" field is the unique non-repeating connector here between the geoJSON/KML/GPX and the CSV.

An alternative is to merge this data sitting in the CSV into the file having the spatial information. Is there an automated way to do it? One hack is to convert the mapping data to a tabular row, merge the data in and convert it all back to geoJSON (or do the same with KML/GPX), but I'm a little vary of taking that complicated route, and it will hamper the occasional updates to data (by non-coders) that this use case requires. It would be a lot more efficient to just pull the details from the CSV for each object in the HTML itself.

Addendum : Yes, using MySQL DB instead of CSV is also acceptable though not preferrable (serverless, portable operation desirable). But please share how to go about it, because I still don't get how to pull it in.

Edit: One major hurdle I'm finding here is the asynchronous loading of the data. Most solutions I see have the entire code loaded into a file-loading script, to be called after the data has finished loading. But here, there's a main program with multiple overlay layers, and a CSV each to load for each layer.

Edit: Here's a link to the project, see source code:
http://nikhilsheth.techydudes.net/files/pune-pb.html

Best Answer

Here is a script to turn your csv into a keyed object as suggested in the comments:

function csvJSON(csv){
  var lines=csv.split("\n");
  var result = {};
  var headers=lines[0].split(",");

  // start at 1 to skip the header row
  for(var i=1;i<lines.length;i++){
    var obj = {}; 
    var currentline=lines[i].split(",");

    var key = currentline[0];
    // start at 1 to skip the first column, which is your key
    for(var j=1;j<headers.length;j++){
      obj[headers[j]] = currentline[j];
    }
    result[key] = obj;
  }

  // return a js object
  return result;
}

// read your csv; will likely need a way to get this from a file in your application; just for demonstration here:
var csv = "name,detail1,detail2,detail3,detail4,detail5\nWard 01,23,45,10,54,30\nWard 02,78,98,14,20,53"

// construct the lookup object from the csv
var csvLookup = csvJSON(csv); 

With this in place, when constructing your popups you can do a simple lookup by key to get the value(s) of interest:

function onEachFeature(feature, layer) {
    // lookup the value from the csv for this polygon feature
    // assuming here key is in feature.properties.name = 'Ward01'
    var ward = feature.properties.name; // or whatever it really is
    var detail = csvLookup[ward]["detail1"];
    layer.bindPopup("<p> Detail1 for " + ward + ": " + detail + "</p>");
}