1

I have a couple of markers that have a css class with its names, for example: markerOne has .markerone as css class, and so on. Its possible to create a function to assign these markers to specific layers or groups? Something like var layerone = $(L.marker).hasClass("markerone")); and assign all markers with that class inside a layer? I want to do this so later I can toggle that layer on/off with addLayer and removeLayer.

Function that I use to show the markers:

function showResourcesByName(name) {
            for (var i = 0; i < markers.resources.length; i++) {
                var resName = markers.resources[i].name;

                if (resName == name) {
                    var resIcon = icons.resources[i].icon;
                    var resSize = icons.resources[i].size;
                    var resPname = icons.resources[i].pname;

                    var customIcon = L.icon({
                        iconUrl: resIcon,
                        iconSize: resSize, // size of the icon
                        iconAnchor:   [resSize[0]/2, resSize[1]/2], // point of the icon which will correspond to marker's location
                        popupAnchor:  [2, -resSize[1]/2] // point from which the popup should open relative to the iconAnchor
                    });

                    for (var j = 0; j < markers.resources[i].coords.length; j++) {
                        var x = markers.resources[i].coords[j].x;
                        var y = markers.resources[i].coords[j].y;

                        marker = L.marker([y, x], {icon: customIcon});
                        marker.addTo(map).bindPopup(resPname);
                        $(marker._icon).addClass(name)



                    }
                }
            }
        }

The class that I mention is the (name) part in $(marker._icon).addClass(name), which grabs the name from markers.js:

    var markers = {
  "resources": [
    {
      "name": "AITokarServer",
      "coords": [
        {
          "x": -1210.0,
          "y": -1770.0
        },
        {
          "x": -1230.0,
          "y": -1810.0
        },

So all markers with the name AITokarServer will have a class .AITokarServer and so on.

RogerHN
  • 584
  • 1
  • 11
  • 31
  • Can you include a simple markup and code that you are working with? – Adam B Feb 15 '16 at 19:26
  • Sure, I added the code with the function that add the class to markers. I have 29 markers types, so it's 29 classes too. – RogerHN Feb 15 '16 at 19:31

2 Answers2

4

You could add some functionality to L.Marker by creating a custom marker class to make things easier. Hook into the onAdd function so that you can automaticly assign a classname upon marker initialization. And you can add a function to check for that classname:

L.CustomMarker = L.Marker.extend({

    // Overwrite onAdd function
    onAdd: function (map) {

        // Run original onAdd function
        L.Marker.prototype.onAdd.call(this, map);

        // Check if there's a class set in options
        if (this.options.className) {

            // Apply className to icon and shadow
            L.DomUtil.addClass(this._icon, this.options.className);
            L.DomUtil.addClass(this._shadow, this.options.className);
        }

        // return instance
        return this;
    },

    // Function for checking class
    hasClass: function (name) {

        // Check if a class is set in options and compare to given one
        return this.options.className && this.options.className === name;
    }
});

Now you easily apply a classname upon initialization of your markers:

var marker = new L.CustomMarker([0, 0], {
    'className': 'foobar'
}).addTo(map);

And check if a certain class is set on your marker:

if (marker.hasClass('foobar')) {
    // YES! Do stuff
}

That said, you don't actually need to add classes to your markers to split them up into different groups. You already have those groups in your datastructure. Consider the following structure:

var markers = [{
    'name': 'Foo',
    'coordinates': [{
        'lat': -25,
        'lng': -25
    }, {
        'lat': 25,
        'lng': -25
    }]
}, {
    'name': 'Bar',
    'coordinates': [{
        'lat': -25,
        'lng': 25
    }, {
        'lat': 25,
        'lng': 25
    }]
}];

To put those into different groups, first create a object to store the groups which you can later add to your layercontrol:

var overlays = {};

Now you can iterate the structure, create layergroups for each set of markers and add them to it:

// iterate the structure, handle each group
markers.forEach(function (group) {

    // check if there's already a group for this name
    if (!overlays.hasOwnProperty(group.name)) {

        // new group, create layergroup, store in object and add to map
        overlays[group.name] = new L.LayerGroup().addTo(map);
    }

    // iterate the coordinates for this group
    group.coordinates.forEach(function (coordinate) {

        // create markers for each coordinate and add to the layergroup
        new L.Marker([coordinate.lat, coordinate.lng]).addTo(overlays[group.name]);

    })
});

Now you can add the overlays object to the layercontrol so you can toggle them:

new L.Control.Layers(null, overlays).addTo(map);

Here's a working example on Plunker: http://plnkr.co/edit/t0YiJO8RmEdnIKKXugdm?p=preview

You can still add classnames if you need to by using the custom marker class above and changing the coordinates iterator like this:

group.coordinates.forEach(function (coordinate) {
    new L.CustomMarker([coordinate.lat, coordinate.lng], {
        'className': group.name
    }).addTo(overlays[group.name]);
})

Here's a working example on Plunker: http://plnkr.co/edit/cHPSLKDbltxr9jFZotOD?p=preview

iH8
  • 27,722
  • 4
  • 67
  • 76
  • This part is a comment right? `Check if a class is set in options and compare to given one` – RogerHN Feb 15 '16 at 19:51
  • Now that I can check the class, can you help me add the markers that have the class "x" to a layer? – RogerHN Feb 16 '16 at 05:20
  • Have done so, answer has been overhauled. Hope that helps, let me know what you think :) Good luck! – iH8 Feb 16 '16 at 12:53
  • Htank you so much iH8! That's exactly what I was trying to achieve! Awesome! – RogerHN Feb 16 '16 at 13:35
  • Hey iH8, I was trying your code, its possible to create a switch to turn the layers on/off with a click, for example a checkbox? I found this example function to use with a input, its hard to implement on your code to toggle the layers on/off? `$( "input" ).change(function( event ) { layerClicked = window[event.target.value]; if (map.hasLayer(layerClicked)) { map.removeLayer(layerClicked); } else{ map.addLayer(layerClicked); } ; });` But in this case, I want the layers by default in off state, and if I check the checkbox, they appear. – RogerHN Feb 17 '16 at 11:17
  • Comments aren't meant/suited for asking new questions, only for clarifying the question/answer. If you have a new question, please post it as such with all the relevant info, what you have tried, what didn't work, error messages, if any, your code etc. etc. I'll keep an eye out. Good luck! – iH8 Feb 17 '16 at 11:23
  • Okay, will try here, just a question about this part `'className': group.name` the two dots means the group.name will be equal to the className? – RogerHN Feb 17 '16 at 11:38
  • Leaflet's options objects are [object literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals) They're key/value pairs surrounded by curly brackets: `{}` separated by comma's: `,`. The key/value pairs are defined by using a colon `:`. A object looks like this: `{'alpha': true, 'bravo': 123, 'charlie': 'foobar'}` The values can be strings, numbers, booleans, arrays, objects or functions. So you can also do stuff like this: `{'myObject': {'foo': 'bar'}, 'myArray': [1,2,3], myFunction: function(){ //do stuff}`}` So yes, that's what it means – iH8 Feb 17 '16 at 11:53
1

In Leaflet, markers do not have CSS classes. Markers have icons, and icons have a className option, so:

var marker1 = L.marker({ 
      icon: L.icon({ 
             className: 'green'
             // Other icon options
      })
      // Other marker options
 });

console.log(marker1.options.icon.options.className);
IvanSanchez
  • 18,272
  • 3
  • 30
  • 45