Created
August 15, 2012 20:34
-
-
Save clooth/3363368 to your computer and use it in GitHub Desktop.
GoogleMapsWidget
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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