Skip to content

Instantly share code, notes, and snippets.

@clooth
Created August 15, 2012 20:34
Show Gist options
  • Save clooth/3363368 to your computer and use it in GitHub Desktop.
Save clooth/3363368 to your computer and use it in GitHub Desktop.
GoogleMapsWidget
from django import forms
from django.conf import settings
from django.utils.safestring import mark_safe
class GoogleMapsWidget(forms.HiddenInput):
# Media to be includes with the widget
class Media:
js = (
'http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js',
)
def render(self, name, value, attrs=None, choices=()):
# Default center for the widget
self.attrs['map_center'] = self.attrs.get('map_center', u'64.0000,24.0000')
# Map size
self.attrs['map_width'] = self.attrs.get('map_width', 640)
self.attrs['map_height'] = self.attrs.get('map_height', 480)
# Default search location
self.attrs['default_search'] = self.attrs.get('name', u'Helsinki, Finland')
# Javascript initialization
map_script = u"""
<script src="http://maps.google.com/maps/api/js?sensor=true&api_key=AIzaSyAiRxWGHmWZWDZbC0jgWRn5UDEXiFmQZm4"></script>
<script>
var GoogleMapsWidget = {};
// GoogleMapsWidget Javascript
$(function() {
// Coordinate Elements
var latitude_input = $('#%(latitude_id)s'),
longitude_input = $('#%(longitude_id)s'),
latitude_value = latitude_input.val(),
longitude_value = longitude_input.val();
// Map options
var map_options = {
zoom: 12,
center: new google.maps.LatLng(%(map_center)s),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// If we have coordinates already, set the center to that
if (latitude_value != '' && longitude_value != '') {
map_options.center = new google.maps.LatLng(latitude_value, longitude_value);
}
// Create the map
var map = new google.maps.Map(document.getElementById('gmw-map'), map_options);
// Initialize Google's Geocoder
var geocoder = new google.maps.Geocoder();
// Create the draggable marker
var marker = new google.maps.Marker({
position: map_options.center,
map: map,
draggable: true
});
// Function for updating the coordinate values
var updateCoordinates = function(info) {
latitude_input.val(info.lat());
longitude_input.val(info.lng());
};
// Function for updating the center of the map and the marker
var updateMapDisplay = function(latitude, longitude) {
var location = new google.maps.LatLng(latitude, longitude);
marker.setPosition(location);
map.setCenter(location);
};
// Function to reset the marker back where it used to be
var resetMapDisplay = function() {
marker.setPosition(map_options.center);
map.setCenter(map_options.center);
};
// Bind the drag event to change the coordinates
google.maps.event.addListener(marker, 'dragend', function(event) {
updateCoordinates(event.latLng);
// NOTE: Center map to new coordinates?
});
// Hide original form elements
longitude_input.parent().parent().hide();
// Address resolving form
var address_input = $('#gmw-address'),
search_button = $('#gmw-search'),
search_results = $('#gmw-search-results'),
error_message = $('#gmw-search-error');
// Resolve address from given input (called on submit)
var resolveAddress = function() {
// Get current address value
var address_value = address_input.val();
// Run geocoder
geocoder.geocode( { 'address': address_value }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
// Remove previous items
search_results.html('');
var results_count = results.length,
result_links_list = [];
// Loop through the found locations with the address and
// display them as a neat list underneath the form
for (var i = 0; i < results_count; i++) {
var formatted_address = results[i].formatted_address,
address_location = results[i].geometry.location,
address_latitude = address_location.lat(),
address_longitude = address_location.lng();
// If it's the first one, automatically center the map to that and update the coordinates
if (i == 0) {
updateMapDisplay(address_latitude, address_longitude);
}
// Append list items
result_links_list.push($('<li><a href="#" latitude="'+ address_latitude +'" longitude="'+ address_longitude +'" class="gmw-address-link"><span>'+ formatted_address +'</span></a></li>'));
}
// Update list display
search_results.append(result_links_list);
} else {
error_message.html('The Geocoder was unable to find your address because: '+ status);
}
// Re-enable search if it's disabled
search_button.removeAttr('disabled');
});
};
// Bind search event
search_button.bind('click', function(event) {
event.preventDefault();
// Disable search button
search_button.attr('disabled', 'disabled');
// Resolve address
resolveAddress();
});
// Bind result link clicks
search_results.on('click', 'a', function(event) {
var latitude = parseFloat($(this).attr('latitude')),
longitude = parseFloat($(this).attr('longitude'));
updateMapDisplay(latitude, longitude);
});
});
</script>
""" % { 'latitude_id': attrs['id'], 'longitude_id': self.attrs['longitude_id'], 'map_center': self.attrs['map_center'] }
# HTML initialization
map_html = u"""
<style type="text/css">
/* GoogleMapsWidget CSS */
.cf:before,.cf:after{content:" ";display:table}.cf:after{clear:both}.cf{*zoom: 1}
#gmw-container {
clear: both;
width: 100%%;
}
#gmw-container, #gmw-controls {
}
#gmw-controls {
width: 200px;
float: left;
padding: 10px;
background-color: #fff;
border: 1px #ccc solid;
border-right: 0px;
}
#gmw-controls .field {
display: block;
clear: both;
padding: 5px 0px;
}
#gmw-search-results {
list-style: none;
margin: 0;
padding: 0;
display: block;
}
#gmw-search-results li {
display: block;
padding: 5px;
}
#gmw-map {
width: %(map_width)ipx;
height: %(map_height)ipx;
background-color: #fff;
padding: 10px;
border: 1px #ccc solid;
}
</style>
<div id="gmw-container" class="cf">
<div id="gmw-controls">
<div class="field cf"><input id="gmw-reset" type="button" value="Reset to original" /></div>
<div class="field cf search">
<input id="gmw-address" type="text" value="%(default_search)s" />
<input id="gmw-search" type="button" value="Locate" />
</div>
<div class="field cf results">
<ul id="gmw-search-results"></ul>
</div>
</div>
<div id="gmw-map"></div>
</div>
""" % {'map_width':self.attrs['map_width'],'map_height':self.attrs['map_height'],'default_search':self.attrs['default_search']}
rendered = super(GoogleMapsWidget, self).render(name, value, attrs)
return rendered + mark_safe(map_html + map_script)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment