alukach
alukach

Reputation: 6298

Group map points by their category in JavaScript

I'm putting points on a map by parsing through a dynamically created GeoJSON file. I'd like to group these points by it's category attribute (each point has a category property). I've found how to add points to group objects in my mapping library (Leaflet: http://leaflet.cloudmade.com/examples/layers-control.html), but it assumes that I know what the categories are going to be (ex. var citiesLayer = new L.LayerGroup(); ).

What I'd prefer to do is to parse through each point (already doing that part), and do a check to see if a group for category X exists, and either add the point to that group or make a group and add the point. This would allow me to turn all points of a certain category on/off at once. Any ideas as to how I'd do that? I know very little about JavaScript (I'm a Python guy).

Here's my JS:

// http://geoserving.net/odk_geoserver/

function init(){
    $.getJSON(geoJSONURL, makeMap);
}

function makeMap(data) {
    // Assign GeoJSON to variable
    var eventPoints = data;
    // Create new map instance
    var map = new L.Map('map');
    var eventsGeoJSON = new L.GeoJSON(null, {
            pointToLayer: function (latlng){
                return new L.CircleMarker(latlng, {
                    radius: 5,
                    fillColor: "#A3C990",
                    color: "#000",
                    weight: 1,
                    opacity: 1,
                    fillOpacity: 0.4
                });
            }
        });

    // Event Listener for Addition of Data to Boundary Layer
    eventsGeoJSON.on('featureparse', function (e) {
        var popupText = 
        '<div id="feature">';

        for(var i = 0, l = e.properties.event_set__all.length; i < l; i++) {  
            popupText += '<div class="event">' +
            '<p>' +
                '<h3 class="featureInfo">' +
                        e.properties.event_set__all[i].title + 
                '</h3>' +
            '</p>';
            if (e.properties.event_set__all[i].category__category) {
                popupText +=
                '<p>' +
                    '<span class="featureLabel">Category: </span>' +
                    '<span class="featureInfo">' +
                        e.properties.event_set__all[i].category__category + 
                    '</span>' +
                '</p>';
            }
            popupText += '</div>';
        }

        popupText +=
            '<div class="venue">' +
                    '<span class="featureLabel">Venue: </span>' +
                    '<span class="featureInfo">' + 
                        '<a href="../' + e.properties.neighborhood__slug + '/' + e.properties.slug + '">' + 
                            e.properties.venue + 
                        '</a>' +
                    '</span>' +
            '</div>';

        e.layer.bindPopup(popupText);
    }); // End feature parse

    // Populate Points Layer with Data
    eventsGeoJSON.addGeoJSON(eventPoints);

    var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/<My Key>/256/{z}/{x}/{y}.png',
        cloudmadeAttrib = 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2011 CloudMade',
        cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttrib});
    var seattle = new L.LatLng(47.64, -122.34); // geographical point (longitude and latitude)
    map.setView(seattle, 12).addLayer(cloudmade);
    map.addLayer(eventsGeoJSON);
}

An example GeoJSON point:

{
    "crs": null,
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -122.382626,
                    47.6657641
                ]
            },
            "type": "Feature",
            "id": 18,
            "properties": {
                "event_set__all": [
                    {
                        "category__category": "Live",
                        "title": "the Tallboys",
                        "cost": "$5",
                        "description": "",
                        "slug": "the-tallboys"
                    }
                ],
                "neighborhood__slug": "ballard",
                "venue": "Tractor Tavern",
                "neighborhood__neighborhood": "Ballard",
                "address": "5213 Ballard Ave NW, Seattle, WA 98107, USA",
                "slug": "tractor-tavern"
            }
        }
    ]
}

The attribute to be used to group each point is e.properties.event_set__all[0].category__category.

Upvotes: 0

Views: 977

Answers (1)

agershun
agershun

Reputation: 4107

You can group all points with Alasql library:

var res = alasql('SELECT features->0->properties->event_set__all->0->category__category \
                      AS category, ARRAY(_) AS points FROM ? GROUP BY category',[data]);

It groups all points with category selected from this long point name like:

[
    {category:"Live1", points: [{point},{point},...] },
    {category:"Live2", points: [{point},{point},...] }
]

Try this example at jsFiddle.

Upvotes: 1

Related Questions