We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 33670
    • 3 Posts

    GoogleMaps
    Version: 0.1
    Author: Zydell

    Live Example: http://www.matthijsboot.nl/googlemapsmarker/ (Dutch)
    Note 1: When you view this I may actually be working on it; so it may very well be broken when you are checking it.
    Note 2: I’d love to hear what you think of it, if you have suggestions for my coding (style) and suggestions for additional functionality; so I can add that to my list of todo!

    Requirements: jQuery

    Description:

    • It’s a basic snippet to output google maps on your website.
    • It uses MODX documents as markers and is able to categorize them using a TV
    • It supports custom marker icons and it supports multiple categorized images by using a CHUNK
    • It still needs optimization and loads of changes, its just basic functionality atm



    The GoogleMaps snippet:
    <?php
    /**
     * GoogleMaps Snippet to integrate the google maps API
     *
     * This snippet is loosely based on GoogleMapMarker but 
     * was updated for additional functionality and for 
     * MODX Revolution. It requires JQuery.
     *
     * This snippet uses the document [[*description]] for coordinates
     *
     * To categorize markers you need to create a TV (assigned to the template that the documents use) with the following settings:
     * input options = "Category 1==cat1||Category 2==cat2", output type should be set to comma-separated
     *
     * To use custom icons you need to create a CHUNK using the following format
     * "cat1==image1url||cat2==image2url"
     * Please note that the above 'cat1' and 'cat2' correspond to 'cat1' and 'cat2' in the category TV.
     * 
     * @version 0.1
     * @author Matthijs Boot (matthijsboot.nl)
     *
     * @example [[GoogleMaps& parentids=`1` &tplMap=`googlemaps_tpl` &iconImage=`assets/images/gmaps.png`]]
     * @example [[GoogleMaps? &categorize=`1` &category_tv=`googlemaps_category` &catIcons=`googlemaps_icons`]]
     */
    
    /**
     * TODO
     *
     * - Correctly process markers assigned to multiple categories
     * - Add templates for rendering the (categorized) list
     * - Loads more
     */
    
    // -- CONFIGURATION  --
    
    // Comma-separated list of IDs of the folders with the marker documents
    $config['parentids'] = (isset($parentids)) ? $parentids: '';
    // Field to sort by
    $config['sortby'] = (isset($sortBy)) ? $sortBy : 'createdon';
    // Direction to sort by
    $config['sortdir'] = (isset($sortDir)) ? $sortDir : 'ASC';
    
    // Categorize the documents (by template variable)
    $config['categorize'] = (isset($categorize)) ? $categorize : 0;
    // Categorize template variable
    $config['category_tv'] = (isset($category_tv)) ? $category_tv : '';
    // Id of the div where the category checkboxes will be placed
    $config['catDiv'] = (isset($catDiv)) ? $catDiv : 'marker_categories';
    // Chunk that contains the link between categories and their images
    $config['catIcons'] = (isset($catIcons)) ? $catIcons : '';
    // (Relative) url to a custom icon image
    $config['iconImage'] = (isset($iconImage)) ? $iconImage : '';
    
    // Show a basic form to show/hide the markers (0, 1)
    $config['showForm'] = (isset($showForm)) ? $showForm : 1;
    // Show a list of all the markers (0, 1)
    $config['showList'] = (isset($showList)) ? $showList : 0;
    // Id of the div where the list will be put into
    $config['listDiv'] = (isset($listDiv)) ? $listDiv: 'mapslist';
    
    // Chunk that contains the template containing the google map
    $config['tplMap'] = (isset($tplMap)) ? $tplMap : '';
    // Id of the div where the map will be rendered
    $config['mapDiv'] = (isset($mapDiv)) ? $mapDiv : 'map';
    
    // Initial type of the map (either 'ROADMAP', 'SATTELITE', 'HYBRID' or 'TERRAIN')
    $config['mapTypeId'] = (isset($mapType)) ? $mapType : 'ROADMAP';
    // Initial center coordinates of the map '<latitude>, <longitude>'
    $config['initCoords'] = (isset($initCoords)) ? $initCoords: '51.831163, 5.856228'; // Nijmegen, The Netherlands ;-)
    // Initial zoomlevel of the map
    $config['initZoom'] = (isset($initZoom)) ? $initZoom: '8';
    
    // Disable the default UI (0, 1)
    $config['disableDefaultUI'] = (isset($disableDefaultUI)) ? $disableDefaultUI : '';
    // Set the Zoom control style ('SMALL', 'LARGE', 'DEFAULT')
    $config['ZoomControlStyle'] = (isset($ZoomControlStyle)) ? $ZoomControlStyle : '';
    // Set the MapType control style ('HORIZONTAL_BAR', 'DROPDOWN_MENU', 'DEFAULT')
    $config['MapTypeControlStyle'] = (isset($MapTypeControlStyle)) ? $MapTypeControlStyle : '';
    
    // Extra options can be added by putting them in this string using the following format:
    // param1,value1||param2,value2||param3,value3
    $config['extraOptions'] = (isset($extraOptions)) ? $extraOptions : '';
    
    
    // -- START OF THE SNIPPET --
    
    // Register the google maps api js to the header of the document
    $modx->regClientStartupScript('http://maps.google.com/maps/api/js?v=3.2&sensor=false');
    
    
    // -- PROCESS TEMPLATES AND VARIABLES --
    
    // Set and parse the template for the map
    if (empty($config['tplMap']))
    {
    	// This is the default template
    	$templates['tplMap'] = $modx->newObject('modChunk', array('name' => 'tplMap'));
    	$templates['tplMap']->setContent("<div class=\"left\" id=\"[[+mapDiv]]\" style=\"width: 300px; height: 300px;\"></div>\n");
    } else 
    	// Otherwise use the set template
    	$templates['tplMap'] = $modx->getChunk($config['tplMap']);
    
    // Parse extra google maps API options that can be set in $extraOptions (param1,value1||param2,value2 etc)
    if (!empty($config['extraOptions']))
    {
    	$config['extraOptions'] = explode("||", $config['extraOptions']);
    	foreach ($config['extraOptions'] as $value)
    	{
    		$value = explode(",", $value);
    		$data['extraOptions'] .= '    ' . $value[0] . ': ' . $value[1] . ",\n";
    	}
    }
    
    // If set to categorize the markers, load the category data from the template variable and save it
    if ($config['categorize'])
    {
    	if (empty($config['category_tv'])) return "<!-- GOOGLEMAPS SNIPPET: ERROR, Please set the TV containing the categories using &category_tv=`TV-name` -->";
    	$categories = $modx->getObject('modTemplateVar', array('name' => $config['category_tv']));
    	$categories = explode("||", $categories->get('elements'));
    	foreach ($categories as $category)
    	{
    		$var = explode("==", $category);
    		$data['categories'][$var[1]] = $var[0];
    	}
    	if (empty($data['categories'])) return "<!-- GOOGLEMAPS SNIPPET: ERROR, No categories found in the TV that should contain the categories, please check the TV! -->";
    }
    
    // If set to categorize the markers and categories are set, load and parse the categories from the chunk and save it as array
    if ($config['catIcons'])
    {
    	$icons = explode("||", $modx->getChunk($config['catIcons']));
    	$config['catIcons'] = array();
    	foreach ($icons as $icon)
    	{
    		$i = explode("==", $icon);
    		$data['catIcons'][$i[0]] = $i[1];
    	}
    }
    
    // Set google maps options for changing the look and feel of google maps
    if (!empty($config['disableDefaultUI'])) 
    	$data['customOptions'] .= '    disableDefaultUI: ' . $config['disableDefaultUI'] . ",\n";
    if (!empty($config['ZoomControlStyle'])) 
    	$data['customOptions'] .= "    zoomControlOptions: {\n      style: google.maps.ZoomControlStyle." . $config['ZoomControlStyle'] . "\n    },\n";
    if (!empty($config['MapTypeControlStyle'])) 
    	$data['customOptions'] .= "    mapTypeControlOptions: {\n      style: google.maps.MapTypeControlStyle." . $config['MapTypeControlStyle'] . "\n    },\n";
    
    // -- CREATE MARKERS --
    
    // For now use this query to get all documents
    $c = $modx->newQuery('modResource');
    $c->where(array(
    	'parent' => $config['parentids'],
    ));
    $c->sortby($config['sortby'], $config['sortdir']);
    $marker_docs = $modx->resource->getMany('Children', $criteria);
    $marker_cats = isset($config['categorize']) ? $modx->getObject('modTemplateVar',array('name'=>$config['category_tv'])) : '';
    
    // Loop all the documents (markers) and creates output that contains all the required data in JavaScript array format.
    $data['markers'] = "  var markerdata = [\n";
    foreach($marker_docs as $marker)
    {
    	// Document ID
    	$marker_id = $marker->get('id');
    	// Document Data
    	$placeholders = array
    	(
    		'id' => $marker_id,
    		'description' => $marker->get('description'),
    		'pagetitle' => $marker->get('pagetitle'),
    		'content' => $marker->get('content'),
    	);
    	// The actual content of the data
    	$content = json_encode($placeholders['content']);
    
    	// Set the id, pagetitle, description and content
    	$data['markers'] .= "    [" . $placeholders['id'] . ", '" . $placeholders['pagetitle'] . "', " . $placeholders['description'] . ", " . $content;
    
    	// If set to categorize the markers
    	if ($config['categorize'] && $config['category_tv'] && isset($marker_cats))
    	{
    		// Fetches the set categories for this document
    		$category = explode(",",$marker_cats->renderOutput($marker_id));
    		$category = $category[0]; // for now only one category can be assigned
    
    		// add the category to the JavaScript data
    		$placeholders['category'] = ($config['categorize']) ? $category : '';
    
    		// add the icon_url to the JavaScript data
    		if ($data['catIcons'][$category])
    			$placeholders['icon_url'] = $data['catIcons'][$category];
    		elseif ($config['iconImage'])
    			$placeholders['icon_url'] = $config['iconImage'];
    		else
    			$placeholders['icon_url'] = '';
    	} else {
    		$placeholders['category'] = '';
    		if ($config['iconImage'])
    			$placeholders['icon_url'] = $config['iconImage'];
    		else
    			$placeholders['icon_url'] = '';
    	}
    
    	// Set the category and icon image and close the document array
    	$data['markers'] .=  ", '" . $placeholders['category'] . "', '" . $placeholders['icon_url'] . "'],\n";
    	// Save the document data
    	$data['placeholders'][$marker_id] = $placeholders;
    }
    // Close the JS markerdata array
    $data['markers'] .= "  ];\n";
    
    // -- CREATE THE HTML OUTPUT --
    
    // Renders the html where the google map will be rendered in
    $output .= $templates['tplMap']->process(array('mapDiv' => $config['mapDiv']));
    
    // If set to categorize the markers, this will output a basic form with checkboxes to show/hide the various categories
    if ($config['categorize'] && $config['showForm'])
    {
    	$output .= '<div id="' . $config['catDiv'] . '">
    	<form class="left" action="" id="' . $config['catDiv'] . '_form">
    		<fieldset id="' . $config['catDiv'] . '_fieldset">' . "\n";
    
    	foreach ($data['categories'] as $category => $description)
    	{
    		$output .= '			<input type="checkbox" checked="checked" name="' . $config['catDiv'] . '" value="' . $category . '" /> ';
    		if (isset($data['catIcons'][$category]))
    			$output .= '<img height="16" src="' . $data['catIcons'][$category] . '" alt="' . $description . '" />';
    		elseif ($config['iconImage'])
    			$output .= '<img height="16" src="' . $config['iconImage'] . '" alt="' . $description . '" />';
    
    		$output .= $description . "<br />\n";
    	}
    	$output .= "		</fieldset>
    	</form>
    </div>\n";
    }
    
    // If set this will output a basic (categorized) list with the various markers as clickable links that open the infoboxes
    if ($config['showList'])
    {
    	$output .= "<div class=\"clear\" id=\"" . $config['listDiv'] . "\">\n";
    	$output .= "	<ul>\n";
    
    	if ($config['categorize'])
    	{
    		foreach ($data['categories'] as $category => $description)
    		{
    			$output .= "		<li>";
    			if (isset($data['catIcons'][$category])) 
    				$output .= '<img height="16" src="' . $data['catIcons'][$category] . '" alt="' . $description . '" />';
    			elseif ($config['iconImage'])
    				$output .= '<img height="16" src="' . $config['iconImage'] . '" alt="' . $description . '" />';
    
    			$output .= $description . "\n			<ul>\n";
    
    			foreach ($data['placeholders'] as $id => $values)
    			{
    				if ($values['category'] == $category) $output .= 
    					"				<li><a class=\"mapslink\" href=\"". 
    					$modx->makeUrl($modx->resource->get('id')) . 
    					"\" id=\"mapslink-" . $id . "\">" . $values['pagetitle']. "</a></li>\n";
    			}
    			$output .= "			</ul>\n		</li>\n";
    		}
    	} else {
    		foreach ($data['placeholders'] as $id => $values)
    		{
    			$output .= "		<li><a class=\"mapslink\" href=\"".$modx->makeUrl($modx->resource->get('id')) .
    				"\" id=\"mapslink-" . $id . "\">" . $values['pagetitle']. "</a></li>\n";
    		}
    	}
    	$output .= "	</ul>\n";
    	$output .= "</div>\n";
    }
    
    
    // -- CREATE THE JAVASCRIPT OUTPUT --
    
    $output .= '<script type="text/javascript">
    //<![CDATA[
    
    var markers = [];
    
    $(document).ready(function()
    {
      var latlng = new google.maps.LatLng(' . $config['initCoords'] . ');
      var myOptions =
      {
        zoom: ' . $config['initZoom'] . ',
        center: latlng,
        mapTypeId: google.maps.MapTypeId.' . $config['mapTypeId'] . ",\n";
        $output .= $data['customOptions'];
        $output .= $data['extraOptions'];
        $output .= '
      };
      var map = new google.maps.Map(document.getElementById("' . $config['mapDiv'] . "\"), myOptions);\n";
    
      $output .= $data['markers']; $output .= '
    
      for (i = 0; i < markerdata.length; i++)
      {
        newMarker = new google.maps.Marker({
          position: new google.maps.LatLng(markerdata[i][2], markerdata[i][3]),
          title: markerdata[i][1],
          map: map,
          icon: markerdata[i][6],
        });
        newMarker.id = markerdata[i][0];
        newMarker.category = markerdata[i][5];
        newMarker.listener = attachListener(map, newMarker, markerdata[i][4], "a#mapslink-"+markerdata[i][0]);
    
        markers.push(newMarker);
    
      }
    });'."
    
    function attachListener(map, marker, message, linkselector) {
      var infowindow = new google.maps.InfoWindow({
        content: '<div class=\\\"infowindow\\\">'+message+'<\/div>'
      });
      google.maps.event.addListener(marker, 'click', function() {
        infowindow.open(map, marker);
      });
    
      $(linkselector).click(function(event)
      {
        infowindow.open(map, marker);
        event.preventDefault();
      });
    
      return infowindow;
    }
    
    $('input[name=\"" . $config['catDiv'] . "\"]').change(function()
    {
      var i;
      for (i = 0; i < markers.length; i++) {
        if (markers[i].category === $(this).attr('value')) {
          if ($(this).attr('checked') == true) {
            markers[i].setVisible(true);
          } else {
            markers[i].setVisible(false);
          }
        }
      } 
    });
    
    //]]>
    </script>";
    
    
    // -- RETURN OUTPUT --
    return $output;
    	



    Implementation:
    Make sure that you include jQuery in your document and use this snippet call:
    [[GoogleMaps]]


    This is how I’m currently using it on the live demo:
    [[GoogleMaps? initZoom=`12` &disableDefaultUI=`1` &categorize=`1` &catIcons=`googlemaps_icons` &category_tv=`googlemaps_category` &showList=`1` &showForm=`1`]]


    The googlemaps_category TV (Input Type: Check Box, Output Type: Comma Separated), the input options:
    "Parken==category1||Bossen==category2||Ziekenhuizen==category3"

    The googlemaps_icons chunk that I use contains:
    "category1==assets/images/gmaps.png||category2==assets/images/gmaps2.png||category3==assets/images/gmaps1.png"

    Note that the center location in the snippet is (hard) set to my hometown in the Netherlands, to change it you can manually change the coordinates in the snippet or set them using &initCoords=`xx.xxxx, yy.yyyyy`
      • 18463
      • 121 Posts
      Martijn van Turnhout Reply #2, 15 years, 7 months ago
      Very nice! I’ve been looking for something like this for quite some time now!
        • 33670
        • 3 Posts
        Thanks for your comment; glad you like it. If anyone’s encountering any problems with the snippet let me know and if anyone has ideas for additional functionality (or added it to the snippet code already) I’d like to know as well.