Addressbook

- location field.. has to be refactored
This commit is contained in:
Martin Bauer
2013-09-22 11:11:48 +02:00
parent 49ba4e5223
commit 230f1e6a36
28 changed files with 587 additions and 463 deletions

0
location_field/__init__.py Executable file
View File

28
location_field/forms.py Normal file
View File

@@ -0,0 +1,28 @@
from django.forms import fields
from location_field.widgets import LocationWidget
class PlainLocationField(fields.CharField):
def __init__(self, based_fields=None, zoom=None, default=None,
*args, **kwargs):
kwargs['initial'] = default
self.widget = LocationWidget(based_fields=based_fields, zoom=zoom,
**kwargs)
dwargs = {
'required': True,
'label': None,
'initial': None,
'help_text': None,
'error_messages': None,
'show_hidden_initial': False,
}
for attr in dwargs:
if attr in kwargs:
dwargs[attr] = kwargs[attr]
super(PlainLocationField, self).__init__(*args, **dwargs)

View File

@@ -0,0 +1,139 @@
($ || django.jQuery)(function($){
function location_field_load(map, location_based, zoom)
{
var parent = map.parent().parent();
var location_map;
var location_coordinate = parent.find('input[type=text]');
function load() {
var point = new google.maps.LatLng(49.340174,10.890595);
var options = {
mapTypeId: google.maps.MapTypeId.HYBRID
};
location_map = new google.maps.Map(map[0], options);
var initial_position;
if (location_coordinate.val())
{
var l = location_coordinate.val().split(/,/);
if (l.length > 1)
{
initial_position = new google.maps.LatLng(l[0], l[1]);
location_map.setZoom( parseInt(l[2]) );
}
}
else
{
location_map.setZoom(zoom);
}
function savePosition( p )
{
point = p;
location_coordinate.val(point.lat().toFixed(6) + "," + point.lng().toFixed(6) + "," + location_map.getZoom() );
}
var marker = new google.maps.Marker({
map: location_map,
position: initial_position,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function(mouseEvent) {
savePosition(mouseEvent.latLng);
});
google.maps.event.addListener(location_map, 'click', function(mouseEvent){
marker.setPosition(mouseEvent.latLng);
savePosition(mouseEvent.latLng);
});
google.maps.event.addListener(location_map, 'zoom_changed', function(mouseEvent){
savePosition(point);
});
location_based.bindWithDelay("keypress", function() {
var lstr = [];
location_based.each(function(){
var b = $(this);
lstr.push(b.val())
});
geocode(lstr.join(','), function(l){
location_coordinate.val( l.lat()+','+l.lng() );
});
onLocationCoordinateChange();
}, 2000 );
function onLocationCoordinateChange()
{
var latlng = jQuery(this).val().split(/,/);
if (latlng.length < 2) return;
var latlng = new google.maps.LatLng(latlng[0], latlng[1]);
placeMarker( latlng );
location_map.setZoom( latlng[2] );
//geocode_reverse(latlng, function(l){
// location_coordinate.val(l.lat()+','+l.lng());
//});
}
function placeMarker(location) {
marker.setPosition(location);
location_map.setCenter(location);
savePosition(location);
location_map.panTo(location);
}
function geocode(address, cb) {
var result;
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({"address": address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
cb(results[0].geometry.location);
placeMarker(results[0].geometry.location);
}
});
}
}
/*
function geocode_reverse(location, cb) {
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({"latLng": location}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
cb(results[0].geometry.location);
placeMarker(results[0].geometry.location);
}
});
}
}*/
placeMarker(initial_position);
}
load();
}
$('input[data-location-widget]').each(function(){
var $el = $(this);
var $map = $($el.attr('data-map')),
$based_fields = $($el.attr('data-based-fields')),
zoom = parseInt($el.attr('data-zoom'));
location_field_load($map, $based_fields, zoom);
});
});

40
location_field/models.py Executable file
View File

@@ -0,0 +1,40 @@
from django.db.models import CharField
from location_field import forms
class BaseLocationField(object):
def __init__(self, based_fields=[], zoom=2, default=None, *args, **kwargs):
self._based_fields = based_fields
self._zoom = zoom
self._default = default
self.default = default
def formfield(self, **kwargs):
return super(BaseLocationField, self).formfield(
form_class=self.formfield_class,
based_fields=self._based_fields,
zoom=self._zoom,
default=self._default,
**kwargs)
class PlainLocationField(BaseLocationField, CharField):
formfield_class = forms.PlainLocationField
def __init__(self, based_fields=None, zoom=None,
max_length=63, *args, **kwargs):
super(PlainLocationField, self).__init__(based_fields=based_fields,
zoom=zoom, *args, **kwargs)
CharField.__init__(self, max_length=max_length, *args, **kwargs)
# south compatibility
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^location_field\.models\.LocationField"])
add_introspection_rules([], ["^django\.contrib\.gis"])
except:
pass

11
location_field/urls.py Normal file
View File

@@ -0,0 +1,11 @@
from django.conf.urls.defaults import patterns
import os
app_dir = os.path.dirname(__file__)
urlpatterns = patterns(
'',
(r'^media/(.*)$', 'django.views.static.serve', {
'document_root': '%s/media' % app_dir}),
)

1
location_field/views.py Executable file
View File

@@ -0,0 +1 @@
# Create your views here.

54
location_field/widgets.py Normal file
View File

@@ -0,0 +1,54 @@
from django.forms import widgets
from django.utils.safestring import mark_safe
class LocationWidget(widgets.TextInput):
def __init__(self, attrs=None, based_fields=None, zoom=None, **kwargs):
self.based_fields = based_fields
self.zoom = zoom
super(LocationWidget, self).__init__(attrs)
def render(self, name, value, attrs=None):
if value is not None:
lat, lng, zoom = value.split(',')
value = '%s,%s,%d' % (
float(lat),
float(lng),
float(zoom)
)
else:
value = ''
if '-' not in name:
prefix = ''
else:
prefix = name[:name.rindex('-') + 1]
based_fields = ','.join(
map(lambda f: '#id_' + prefix + f.name, self.based_fields))
attrs = attrs or {}
attrs['data-location-widget'] = name
attrs['data-based-fields'] = based_fields
attrs['data-zoom'] = self.zoom
attrs['data-map'] = '#map_' + name
text_input = super(LocationWidget, self).render(name, value, attrs)
map_div = u'''
<div style="margin:4px 0 0 0">
<label></label>
<div id="map_%(name)s" style="width: 610px; height: 350px"></div>
</div>
'''
return mark_safe(text_input + map_div % {'name': name})
class Media:
# Use schemaless URL so it works with both, http and https websites
js = (
'//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js', # jquery
'//maps.google.com/maps/api/js?sensor=false&language=de',
'/static/js/bindWithDelay.js',
'/location_field/media/form.js',
)