Skip to content

Instantly share code, notes, and snippets.

@bartek
Created December 13, 2010 14:48
Show Gist options
  • Save bartek/739049 to your computer and use it in GitHub Desktop.
Save bartek/739049 to your computer and use it in GitHub Desktop.
A simple Google Map Widget with a lat/lng marker. JS file included and required.
/*
* A simple Google maps Javascript widget which will display a map and
* a marker with the ability to move the marker, then setting the
* lat/lng of the marker into the specified (or default) fields.
*/
var google_map_location = new function() {
var jQuery;
var init_options;
var geocoder;
var map, marker, latlng;
/*
* Options available:
* zoom: zoom level of map (default: 14)
* lat: initial lat of map
* lng: initial lng of map
* markerMovedCallback: callback function to use when marker is moved to populate a lat field.
*/
this.init = function(options) {
// Work around for when we have to use closures through django admin to pass in the jQuery object.
jQuery = options.jQuery || $;
init_options = options;
latlng = new google.maps.LatLng(
options.lat || 49.891235,
options.lng || -97.15369
);
var myOptions = {
zoom: options.zoom || 14,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
myOptions);
marker = new google.maps.Marker({
position: latlng,
map: map,
draggable: true,
animation: google.maps.Animation.DROP
});
this.bindHandlers();
// Attempt to get an initialLocation.
if (options.geolocate && navigator.geolocation) {
browserSupportFlag = true;
navigator.geolocation.getCurrentPosition(this.hasPosition, this.noPosition);
}
}
// Once we have received a poistion, center our map and marker to it.
this.hasPosition = function(position) {
latlng = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
map.setCenter(latlng);
marker.setPosition(latlng)
}
// If we have nothing, just show a friendly message
this.noPosition = function(error) {
jQuery("#map_message").html("Could not get current location. Please place marker over the Places location.");
}
/*
* Accept an input field that contains a val() object from jQuery and tries to encode
* an address from it.
*/
this.codeAddress = function(field) {
var self = this;
geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': field.val()}, function(results, status) {
map.setCenter(results[0].geometry.location);
marker.setPosition(results[0].geometry.location);
self.populateLatLngFields(results[0].geometry.location);
});
}
this.populateLatLngFields = function(point) {
jQuery("#id_lat").val(point.lat());
jQuery("#id_lon").val(point.lng());
};
this.bindHandlers = function() {
var self = this;
google.maps.event.addListener(marker, 'dragend', function() {
var point = marker.getPosition();
if(init_options.markerMovedCallback) {
init_options.markerMovedCallback(point);
} else {
self.populateLatLngFields(point);
}
});
};
};
from django.forms.widgets import Input
from django.utils.safestring import mark_safe
class GoogleMapWidget(Input):
"""
Widget to display a Google Map on a page with the ability to move a marker
around and fetch coordinates.
"""
class Media:
js = (
'http://maps.google.com/maps/api/js?sensor=true',
'static/js/google_map_location.js',
)
def render(self, name, value, attrs=None):
"""
Attribute extras:
width: width of the Google Map in pixels or percent. Must be the full string.
height: height of the Google Map in pixels or percent. Must be the full string.
markerMovedCallback: incase we don't want to populate the two default fields, let them specify their own callback.
center: (lat, lng) coordinates in tuple format. If not provided, will auto-detect location if available.
geolocate: Boolean. Default = True, If False, will not do any geolocation. Should be set to False if you provide a center() attribute
you do not want potentially over-ridden.
"""
# Defaults, can be overriden by any same-key passed through `attrs`
final_attrs = self.build_attrs(attrs)
context = {
'width': '600px',
'height': '300px',
'markerMovedCallback': 'null',
'lat': 'null',
'lng': 'null',
'geolocate': 'true',
}
context.update(final_attrs)
if 'center' in final_attrs:
context['lat'], context['lng'] = final_attrs['center']
html = u'''
<input type='text' style='width: 400px;' id='map_search_text' /> <input type='button' id='map_search' value='Search' />
<div id="map_canvas" style='width: %(width)s; height: %(height)s;'></div>
<div id="map_message">Marker has been placed near the coordinates of your current location. Please adjust it to match the Places location.</div>
<script type="text/javascript">
//<![CDATA[
var call_google_map = function(jQuery) {
google_map_location.init({
'jQuery': jQuery,
markerMovedCallback: %(markerMovedCallback)s,
lat: %(lat)s,
lng: %(lng)s,
geolocate: %(geolocate)s
});
// Add some event handlers for our search box.
jQuery("#map_search").click(function() {
google_map_location.codeAddress(jQuery("#map_search_text"));
});
jQuery("#map_search_text").keypress(function(e) {
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
google_map_location.codeAddress(jQuery(this));
return false;
}
});
}
// Do a simple check to see if we're using this widget in the admin.
if (typeof django != 'undefined') {
(function($) {
call_google_map($);
})(django.jQuery);
} else {
call_google_map($);
}
//]]>
</script>
''' % context
return mark_safe(html)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment