Google Maps Marker Toggle Code Example

markertoggle
As a followup to my strangely popular KML Toggle example on Google Maps, someone has prompted me to do a Marker Toggle code example.  I’m pretty late to the game to notice that Google updated some of the Maps library syntax, you can now for example pass an object literal for latitude longitude.  As a warning, the code is a bit clumped together to briefly give an example into working with markers.  I wouldn’t recommend master functions that do everything under the sun which is why Angular is a great library to separate your concerns and dependencies.

This example organizes code as follows:

  • Marker information is formatted as a json object, the standard format used today for data sharing.
  • A single global map variable.
  • The Google Map initializeMap() procedural function
    • In addition this function creates markers and your DOM controls.
  • The createMarkers() function that instantiates markers with infowindows and stores it back in the json.
  • createControls() dynamically generates the controls based on information in the json. This would be akin to using Angular’s ng-repeat.
  • toggleControl() is a state changing function that sets your checkbox state, class style, and marker visibility. It uses inverted logic, if the checkbox is checked, then do the opposite.

Click here to the Google Maps Marker Toggle code example.

// Our data source object in json format 
var markerJson = {
    "coffee1": {
        "name": "Urban Bean Coffee",
        "coordinates": {
            "lat": 44.958813,
            "lng": -93.287918
        }
    },
    "coffee2": {
        "name": "Spyhouse Coffee",
        "coordinates": {
            "lat": 44.998846,
            "lng": -93.246241
        }
    },
    "coffee3": {
        "name": "Blue Moon",
        "coordinates": {
            "lat": 44.948480,
            "lng": -93.216707
        }
    }
};

// Set a global variable for map
var map;

// Setup a listener to load the map via Google
google.maps.event.addDomListener(window, 'load', initializeMap);

/* Google Maps Related Functions */

// Initialize our goo
function initializeMap() {
    var options = {
        center: {
            lat: 44.9812,
            lng: -93.2687
        },
        zoom: 13,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    map = new google.maps.Map(document.getElementById("map_canvas"), options);

    // Create markers into DOM
    createMarkers(markerJson);

    // Create controls dynamically after parsing json
    createControls(markerJson);
};

// Instantiate markers in the background and pass it back to the json object
function createMarkers(markerJson) {
    for (var id in markerJson) {
        var shop = markerJson[id];
        var marker = new google.maps.Marker({
            map: map,
            position: shop.coordinates,
            title: shop.name,
            animation: google.maps.Animation.DROP
        });

        // This attaches unique infowindows to each marker
        // You could otherwise do a global infowindow var and have it overwrite itself
        marker.infowindow = new google.maps.InfoWindow({
            content: "This coffeeshop is called " + shop.name
        });

        marker.addListener('click', function() {
            this.infowindow.open(map, this);
        });

        shop.marker = marker;

    }
};

// In this example create the controls dynamically with all checked, obj is each "coffee" listing
function createControls(markerJson) {
    var html = "";
    for (var id in markerJson) {
        var shop = markerJson[id];
        html += '<li><a class="selected" href="#" id="' + id + '" onclick="toggleControl(this); return false"><input onclick="inputClick(this)" type="checkbox" checked id="' + id + '" />' + shop.name + '</a></li>';
    }
    document.getElementById("controls").innerHTML = html;
};

// Toggle class, checkbox state, and marker visibility
function toggleControl(control) {
    var checkbox = control.getElementsByTagName("input")[0];
    var shop = markerJson[control.id];
    if (checkbox.checked == true) { 
        checkbox.checked = false;
        control.className = "normal";
        shop.marker.setVisible(false); // If you have hundreds of markers use setMap(map)
    } else { 
        checkbox.checked = true;
        control.className = "selected";
        shop.marker.setVisible(true); // Similarly use setMap(null)
    }
}; 

// Cleanup function, resets controls, hides all markers, does not destroy
function removeAll() {
    for (var id in markerJson) {
        var shop = markerJson[id];
        shop.marker.setVisible(false);
        document.getElementById(id).className = "normal";
        document.getElementById(id).getElementsByTagName("input")[0].checked = false;
    }
};

// In this case we are keeping the input box for accessibility purposes, so we bubble up the click event to the parent control
function inputClick(input) {
    input.parentElement.click();
};