Need to find something?

Advanced Custom Fields: Google Map Markers with Filters

Today I am going to extend the last tutorial that I posted about creating Google Map with Advanced Custom Fields, which had dynamic markers. In this tutorial, I will add an extra feature to the map so that we can filter the markers with simple checkbox.

What We Need to Update?

We will basically need to update two parts of our last code to add the filter feature and some CSS styles as you need.

  • The Shortcode function
  • The gmaps.js file

The Shortcode

The following code is for the shortcode. It is similar to what we already created, just some parts are added. New added parts are commented for your convenience.

// Locations Map Shortcode - [locations_map_filtered]

function locations_map_filtered (){
    
    $args = array(
        'post_type' => 'location',
        'posts_per_page' => -1,
    );
    
    $locations_query = new WP_QUERY($args);
    
    if ( $locations_query->have_posts() ) {
    
    ob_start(); ?>

    <!-- Filter Checkboxes -->

    <div class="marker-filter">
        <span class="filter-box">
            <label for="regular">
                <input type="checkbox" name="regular" value="regular" id="regular" checked onchange="filterMarker(this.value);"> 
                Regular
            </label>
        </span>
        <span class="filter-box">
            <label for="special">
                <input type="checkbox" name="special" value="special" id="special" checked onchange="filterMarker(this.value);"> 
                Special
            </label>
        </span>
        <span class="filter-box">
            <label for="upcoming">
                <input type="checkbox" name="upcoming" value="upcoming" id="upcoming" checked onchange="filterMarker(this.value);"> 
                Upcoming
            </label>
        </span>
    </div>
    
    <!-- Filter Checkboxes -->

    <div class="acf-map" style="overflow: hidden; position: relative;">

        <?php while ( $locations_query->have_posts() ) {
            $locations_query->the_post(); 
            $address = get_field('address');
            $title = get_the_title();
            $outlet_type = get_field('outlet_type');
            $phone = get_field('phone');
                        
            if ($outlet_type == 'regular') {
                $type_icon = get_stylesheet_directory_uri().'/images/green-marker.png';
                $outlet_text = 'Regular Outlet';
            } elseif ($outlet_type == 'special') {
                $type_icon = get_stylesheet_directory_uri().'/images/red-marker.png';    
                $outlet_text = 'Special Outlet';
            } else {
                $type_icon = get_stylesheet_directory_uri().'/images/gray-marker.png';
                $outlet_text = 'Upcoming Outlet';
            }

            ?>
            
            <div class="marker" data-type="<?php echo $outlet_type; ?>" data-lat="<?php echo $address['lat']; ?>" data-lng="<?php echo $address['lng']; ?>" data-img="<?php echo $type_icon; ?>">
            
            <!-- Added data-type New!-->

                <div class="inside-marker">
                    <h5><?php echo $title; ?></h5>
                    <?php
                        echo $outlet_text.'<br>';   
                        if($phone) {
                         echo 'Phone: '.$phone;       
                        }
                    ?>
                </div>
            </div>
            
    <?php } ?>
    </div>
    
    <?php wp_reset_postdata(); 
    }
    return ob_get_clean();
}

add_shortcode( 'locations_map_filtered', 'locations_map_filtered' );
Code language: HTML, XML (xml)

The “gmaps.js” File

This file has some significant changes. We are calling a new function filterMarker to trigger the change based on the change of the filter checkboxes. The function takes the passed value from the checkbox and uses that to determine which checkbox was checked/unchecked. Based on that activity, the markers are simply shown & hidden. Here is the full code for the gmaps.js file

(function($) {

/*
*  new_map
*
*  This function will render a Google Map onto the selected jQuery element
*
*  @type	function
*  @date	8/11/2013
*  @since	4.3.0
*
*  @param	$el (jQuery element)
*  @return	n/a
*/

function new_map( $el ) {
	
	// var
	var $markers = $el.find('.marker');
	
	
	// vars
	var args = {
		zoom		: 16,
		center		: new google.maps.LatLng(0, 0),
		mapTypeId	: google.maps.MapTypeId.ROADMAP
	};
	
	
	// create map	        	
	var map = new google.maps.Map( $el[0], args);
	
	
	// add a markers reference
	map.markers = [];
	
	
	// add markers
	$markers.each(function(){
		
    	add_marker( $(this), map );
		
	});
	
	
	// center map
	center_map( map );
	
	
	// return
	return map;
	
}

/*
*  add_marker
*
*  This function will add a marker to the selected Google Map
*
*  @type	function
*  @date	8/11/2013
*  @since	4.3.0
*
*  @param	$marker (jQuery element)
*  @param	map (Google Map object)
*  @return	n/a
*/

function add_marker( $marker, map ) { 
	// var
	var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );
    var icon = $marker.attr('data-img');
    var type = $marker.attr('data-type');
    
	// create marker
	var marker = new google.maps.Marker({
		position	: latlng,
		map			: map,
		icon        : icon,
		type        : type
	});

	// add to array
	map.markers.push( marker );
	
	// if marker contains HTML, add it to an infoWindow
	if( $marker.html() )
	{
		// create info window
		var infowindow = new google.maps.InfoWindow({
			content		: $marker.html()
		});

		// show info window when marker is clicked
		google.maps.event.addListener(marker, 'click', function() {          

			infowindow.open( map, marker );

		});
	}

}

/*
*  Marker Filter - NEW!
*/

filterMarker = function (id) {
    for (i = 0; i < map.markers.length; i++) {
        marker = map.markers[i];
        
        if (document.getElementById(id).checked) {
            if (marker.type == id) {
                marker.setVisible(true);
            } 
        }  else {
            if (marker.type == id) {
                marker.setVisible(false);
            }
        }
        
    }    
}

/*
*  center_map
*
*  This function will center the map, showing all markers attached to this map
*
*  @type	function
*  @date	8/11/2013
*  @since	4.3.0
*
*  @param	map (Google Map object)
*  @return	n/a
*/

function center_map( map ) {

	// vars
	var bounds = new google.maps.LatLngBounds();

	// loop through all markers and create bounds
	$.each( map.markers, function( i, marker ){

		var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );

		bounds.extend( latlng );

	});

	// only 1 marker?
	if( map.markers.length == 1 )
	{
		// set center of map
	    map.setCenter( bounds.getCenter() );
	    map.setZoom( 16 );
	}
	else
	{
		// fit to bounds
		map.fitBounds( bounds );
	}

}

/*
*  document ready
*
*  This function will render each map when the document is ready (page has loaded)
*
*  @type	function
*  @date	8/11/2013
*  @since	5.0.0
*
*  @param	n/a
*  @return	n/a
*/
// global var
var map = null;

$(document).ready(function(){

	$('.acf-map').each(function(){

		// create map
		map = new_map( $(this) );

	});
 
		    //zoom
			google.maps.event.addListener( map, 'zoom_changed', function( e ) {
	        
        	var zoom = map.getZoom();   
			
             if(zoom!= 5)           
             {
			var bounds = map.getBounds();
			
               myLatLngss = [];
              	$.each( map.markers, function( i, marker ){			
			var myLatLng = new google.maps.LatLng(marker.position.lat(), marker.position.lng() );	
						
			if(bounds.contains(myLatLng)===true) {						
             		 myLatLngss.push( myLatLng );
					}
					else {
						   
					}
			});
               if(myLatLngss.length > 0)
               { 
                 document.cookie = "coordn="+myLatLngss;
                 $("#customzm").load(location.href + " #customzm");                 
               } 
            } 
			       
	       });
   google.maps.event.addListener(map, 'dragend', function() {
   //alert('map dragged');
   var bounds = map.getBounds();
			
                  myLatLngss = [];
              	$.each( map.markers, function( i, marker ){

			var myLatLng = new google.maps.LatLng(marker.position.lat(), marker.position.lng() );	
					
			if(bounds.contains(myLatLng)===true) {						
             		 myLatLngss.push( myLatLng );
					}
					else {
   
					}
           if(myLatLngss.length > 0)
               {
                 document.cookie = "coordn="+myLatLngss;
                 $("#customzm").load(location.href + " #customzm");                 
               }
			});
   
 } );
  			

});

})(jQuery);
Code language: JavaScript (javascript)

FYI, the updates are made on line 73 and line 104-123.

A Bit of CSS

You will need to add some CSS to make the checkboxes appear nice. Let’s do that.

.filter-box {
    padding: 5px 10px;
    border: 1px solid #e8e8e8;
    margin-right: 10px;
}
Code language: CSS (css)

The Output

Hope you liked this tutorial. Feel free to post your feedback and share with your friends.

Last Updated: January 31, 2024

Al-Mamun Talukder

About Al-Mamun Talukder

WordPress Developer. Minimalist Designer. Tech Enthusiast. Music & Movie Freak. Loves Cars. Founder of WolfDevs.

Connect with me: Upwork, GitHub, Facebook, Twitter

12 comments

  • Mathieu

    Hi mate,
    Thanks so much for the tutorial, it was a great help for my projet.
    Quick question though, maybe you’ll have the answer :
    How do I set default visibility of the markers ? I have two filters and I’d like to have one of them unchecked by default (markers hidden). I replaced the tag in the php file (“checked” by “unchecked”), so the checkbox is indeed unchecked but the marker is still showing on default view. Once i click (check) and click again (uncheck) the filter, it disappears, but I don’t find the solution to hide it right at the beginning.
    Any idea ?
    Cheers

  • How to make all markers inactive / invisible at the start? I delete checked from inputs type checkbox. I have inactive checkboxes but markers map are visible.

  • Arjun Kushwah

    HI and how we setup it for dropdown, i mean select options
    thank you

  • Thank you so much! This was super helpful! I was wondering if you knew of a way to Filter by having the options in a select dropdown verses individual checkboxes?

  • Is there a way to integrate multiple filters for, say, 3 different ACF fields?

    • A

      Yes possible. If you take a look at the form code, it is executing the “filterMarker” function. You can simply mimic that for your new fields.

  • I’m making a site where admins can place markers and draw routes, how would you integrate the drawing tool?

  • This is awesome. How do you do this without a shortcode?

    • A

      If you want to do it without shortcode, you may make a template and use the code there. Please note, you will need to slightly modify the code.

  • These tutorials have been amazing! Thank you. I got the filtering working for one set of checkboxes. Any ideas about filtering for multiple criteria? For example, in addition to Outlet Type, also having a few filters for Outlet Rating or something else. I tried it on my own but couldn’t get the new checkboxes to actually trigger something. The old ones kept working though. Would love your help!

Leave your comment