Feed on
Posts
Comments

For Plone there a few Google Maps packages available. I could get any of these working in Plone 4. I ended up writing my own jQuery code that allows setting a location in edit mode and shows the information when you view you view your content. I’m using the latest Google Maps API v3 for geolocation and drawing maps.

This example is applicable to Plone 3 and 4. But the jQuery/Maps API are generic, so if you’re not interested in the Plone stuff just skip to the jQuery code.


Selecting a locaiton in Google Maps

Use case:

  • Select a location based on an address or by dragging a marker in the map. Store latitude, longitude and zoom level.
  • Display a Google Map widget on your content type that show a stored location

Prequisites

  • You know how to create your custom content type in Plone (if you want to integrate this example in Plone).
  • Basic javascript/jQuery skills

Getting started

Your custom content type

We want to store the longitude, latitude and zoom level in the content.

Create you own custom content types and add the following fields:

  • longitude and latitude in a string field
  • zoomLevel in a integer field

Include necessary javascript and CSS

We are including jQuery. jQuery UI with only the live search function included, this allows direct results when searching for a location. The Google Maps API v3. And some CSS for the map canvas and the live search field.

If you’re planning to use the jquery libraries from my site, please download the files and host these on your own site.

<script src="http://www.leong.nl/wp-content/jquery-1.4.2.min_.js" type="text/javascript"><!--mce:0--></script>
 
<script src="http://www.leong.nl/wp-content/jquery-ui-1.8.1.custom.min_.js" type="text/javascript"><!--mce:1--></script>
 
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"><!--mce:2--></script>
 
<style type="text/css">
#map_canvas {        
  width: 650px;    
  height: 500px;        
  margin-bottom: 2em;  
} 
 
.ui-autocomplete  {        
  background-color: white;       
  width: 300px;        
  border: 1px solid #cfcfcf;        
  list-style-type: none;        
  padding-left: 0px;        
  cursor: pointer; 
}  
</style>

The Google Maps jQuery code

This is jQuery code for displaying and selecting locations in Google Maps. Most of the Maps API code used in this example comes from this article on cibul.org. The article has a good explanation how the Maps API works.

Short explanation on the code below. The inserting of the Maps and search field is all done in javascript code. Without this code you can still save or view the lat/long coordinates. Based on editing or viewing content different functions are called.

 
// based on: http://tech.cibul.org/geocode-with-google-maps-api-v3/
// replace jq with $ character if you're using this code outside Plone
 
var DEFAULT_LATITUDE = 53.21310;
var DEFAULT_LONGITUDE = 5.71713;
var DEFAULT_ZOOM_LEVEL = 9;
 
var ploneMaps = {
 
    /**
     *  Show the map based on saved location
     */
    googleMapsView: function(message) {
        jq('#archetypes-fieldname-latitude').hide();
        jq('#archetypes-fieldname-longitude').hide();
        jq('#archetypes-fieldname-zoomLevel').hide();
 
        var html = "<label>Location:</label><br/>";
        html += "<div id='map_canvas'></div>";
        jq(html).insertBefore('#archetypes-fieldname-latitude');
 
        var longitude = parseFloat(jq("#parent-fieldname-longitude").text());
        var latitude = parseFloat(jq("#parent-fieldname-latitude").text());
        var zoom = parseInt(jq("#parent-fieldname-zoomLevel").text());
 
        ploneMaps.googleMapsDraw(longitude, latitude, zoom, true, false);
    },
    /**
     *  Show the saved location or starting point.
     *  Set-up a search widget for address geocoding
     */
    googleMapsEdit: function(message) {
        jq('#archetypes-fieldname-latitude').hide();
        jq('#archetypes-fieldname-longitude').hide();
        jq('#archetypes-fieldname-zoomLevel').hide();
 
        // create search field
        var html = "<div class='field' id='google-map-search'>";
        html += "<label for='map-search'>Location</label>";
        html += "<div class='formHelp'>Use the marker to select a location ";
        html += "or search field to select a location.</div>";
        html += "<input name='map-search' type='text' size='45'></input>";
        html += "<div id='map_canvas'></div>";
        html += "</div>";
 
        jq(html).insertBefore('#archetypes-fieldname-latitude');
 
        // no form submit when an enter is given in search field
        jq('#google-map-search').keypress(function(e){
           if(e.which == 13){
               e.preventDefault();
           }
        });
 
        // save zoomlevel on submit
        jq('form#plaats-base-edit').submit(function(e){
           jq("#zoomLevel").val(map.getZoom());
        });
 
        // saved location
        var latitude = jq('#latitude').val();
        var longitude = jq('#longitude').val();
        var zoomLevel = parseInt(jq('#zoomLevel').val());
 
        // use default location if nothing is saved
        if (!latitude || !longitude) {
            latitude = DEFAULT_LATITUDE;
            longitude = DEFAULT_LONGITUDE;
            zoomLevel = DEFAULT_ZOOM_LEVEL;
        }
 
        var data = ploneMaps.googleMapsDraw(longitude, latitude, zoomLevel, true, true);
        var map = data[0];
        var markerObj = data[1];
 
        ploneMaps.googleMapsHelper(map, markerObj);
    },
    /**
     * Draw the location based on specific parameters
     */
    googleMapsDraw: function(longitude, latitude, zoomLevel, marker, drag) {
        var map = false;
        if (!isNaN(longitude) && !isNaN(latitude)) {
            var location = new google.maps.LatLng(latitude, longitude);
 
            var myOptions = {
              zoom: zoomLevel,
              center: location,
              mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
            if (marker) {
                marker  = new google.maps.Marker({position: location, map: map, draggable: drag});
            }
 
        }
        return [map, marker]
    },
    /**
     * Helper function, ajax address search and marker event listener
     */
    googleMapsHelper: function(map, marker) {
        //GEOCODER
        geocoder = new google.maps.Geocoder();
        // Form auto completion
        jq("input[name='map-search']").autocomplete({ 
            //This bit uses the geocoder to fetch address values
            source: function(request, response) {
                geocoder.geocode( {'address': request.term, 'region': 'NL' }, function(results, status) {
                  response(jq.map(results, function(item) {
                    return {
                      label: item.formatted_address,
                      value: item.formatted_address,
                      latitude: item.geometry.location.lat(),
                      longitude: item.geometry.location.lng()
                    }
                  }));
                })
            },
            // This bit is executed upon selection of an address
            select: function(event, ui) {
                jq("#latitude").val(ui.item.latitude);
                jq("#longitude").val(ui.item.longitude);
                var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
                marker.setPosition(location);
                map.setCenter(location);
                map.setZoom(11);
            }
        });
        // Reverse Geocoding, when the marker is being dragged on the map update the fields.
        google.maps.event.addListener(marker, 'drag',  function() {
            geocoder.geocode({'latLng': marker.getPosition()}, function(results, status) {
              if (status == google.maps.GeocoderStatus.OK) {
                if (results[0]) {
                  jq("input[name='map-search']").val(results[0].formatted_address);
                  jq("#latitude").val(marker.getPosition().lat());
                  jq("#longitude").val(marker.getPosition().lng());
                }
              }
            });
        });
    }
}
 
jq(document).ready(function() {
 
    // match this jquery selector on the view template of your content type
    if (jq('body.template-plaats_view.portaltype-plaats').length >= 1) {
        ploneMaps.googleMapsView();
    }
    // match this jquery selector on the edit template of your content type
    else if (jq('body.template-base_edit.portaltype-plaats').length >= 1) {
        ploneMaps.googleMapsEdit();
    }
 
});

Trackback URI | Comments RSS

Leave a Reply