Filter map markers in javascript

I am experimenting with the open source tools:  TileMill and MapBox.  In particular, I am using the Weekend Picks template.   Part of this template involves the following bit of javascript code that I am having trouble understanding.  I know generally that this code accomplishes the task of filtering the various markers, but I just don't understand how it works.

    var container = $('#markerfilters');
    $.each(tilejson.markers.markers(), function(index, m) {
        var s = m.data.properties['marker-symbol'];

        if (container.find('[href="#' + s + '"]').length) return;

        var el = $(document.createElement('a'))
            .addClass('markerfilter')
            .attr('href', '#' + s)
            .css('background-image', 'url(http://a.tiles.mapbox.com/v3/marker/pin-l-'+s+'+000000.png)')
            .bind('click', filter);
        container.append(el);
    });


    $('[href="#all"]').bind('click', filter);


    function filter(e) {
        container.find('a').removeClass('selected');
        var id = $(this).addClass('selected').attr('href').replace('#', '');
        tilejson.markers.filter(function(feature) {
            return feature.properties['marker-symbol'] == id || id == 'all';
        });
        return false;
    }

Open in new window


I would really benefit from a detailed explanation, if someone is able to help.  Thanks.
DanielAttardAsked:
Who is Participating?
 
Julian HansenConnect With a Mentor Commented:
Line by line
// This line creates a JQuery object for the #markerfilters object - this will be used 
// in the .each loop

    var container = $('#markerfilters');

// Loop through the list of markers returned by the call to tilejson.markers.markers()
// this will return an arry of objects that contain marker information
// Each iteration of the ach loop (for each item in the array) gets passed the index
// of that item and the item itself

    $.each(tilejson.markers.markers(), function(index, m) {

// get the id of the marker-symbol from the array

        var s = m.data.properties['marker-symbol'];

// This is just a shorthand way of determining if the item exists in the container already
// It is calling the .find function on the href attribute set to a concatenation of '#'
// and the marker-symbol retrieved above. The JQuery .find method will return an 
// array of elements that match the selector criteria - in this case there should only
// be 0 or 1. By checking the length of the return array the code determines if the
// element exists already in the container - in which case it is returns and allows the 
// loop to continue. If the element does not exist length will return 0 and so the code
// will continue.

        if (container.find('[href="#' + s + '"]').length) return;

// If we get here then the marker does not exist so create it
// The code below uses chaining to achieve the desired result
// Each call to a JQuery function returns a JQuery object
// So calls can be chained together
        var el = $(document.createElement('a'))
// Give it a class
            .addClass('markerfilter')
// Set its href to # + marker-symbol value retrieved above
            .attr('href', '#' + s)
// Give it some styling based on its marker symbol

            .css('background-image', 'url(http://a.tiles.mapbox.com/v3/marker/pin-l-'+s+'+000000.png)')
// Bind a click event handler to the marker
            .bind('click', filter);
// And finally append the newly created <a> element to the end of the content in the 
// container id=markerfilters

        container.append(el);
    });

// Here we bind the click event to the element with attribute href = #all - I assume
// This exists in the markup somewhere

    $('[href="#all"]').bind('click', filter);

// This is the event handler for the click event we bound in the code above

    function filter(e) {
// This line removes the selected class from all <a> elements in the container
        container.find('a').removeClass('selected');
// This adds the selected class to the <a> element that was clicked and fired this
// event handler call.
// After setting the class the code removes the '#' from the href attribute for the
// item clicked
        var id = $(this).addClass('selected').attr('href').replace('#', '');
// Without seeing the code for the filter function I can only guess what this does
// The code below seems to be finding a 'feature' (whatever that is in the lib you are using)
// based on the id of the item clicked or if the all button was clicked.
// You would need to look at the tilejson code to get more insight into what this is doing
        tilejson.markers.filter(function(feature) {
            return feature.properties['marker-symbol'] == id || id == 'all';
        });

// Finally return false to disable the normal processing of the click event - i.e. you don't want the browser to attempt to browse to the href of the click event - this disables it
        return false;
    }

Open in new window

0
 
DanielAttardAuthor Commented:
This is amazing julianH, thank you so much.  You went above and beyond the call of duty here.  Thanks for helping this old dog learn a couple of new tricks.
0
 
Julian HansenCommented:
You are welcome - thanks for the points.
0
 
Julian HansenCommented:
Just a correction to my earlier post

// After setting the class the code removes the '#' from the href attribute for the
// item clicked
        var id = $(this).addClass('selected').attr('href').replace('#', '');

Open in new window

Should have been
// This line extracts the marker id from the href attribute by retrieving the 
// href and removing the '#' - it does not (as alluded to above) replace the actual
// attribute in the href

        var id = $(this).addClass('selected').attr('href').replace('#', '');

Open in new window

0
All Courses

From novice to tech pro — start learning today.