location field refactor
This commit is contained in:
parent
05b7a2b969
commit
6c3a7ca408
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/datepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/datepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/timepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/timepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||||
|
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/jquery-ui-1.8.21.custom.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||||
|
|
||||||
|
|
||||||
{% addtoblock "js" %}
|
{% addtoblock "js" %}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
.map_dialog .form-horizontal
|
||||||
|
{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog input
|
||||||
|
{
|
||||||
|
width: 390px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.map_dialog input.displayed_location_input
|
||||||
|
{
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog .map_canvas img
|
||||||
|
{
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog label
|
||||||
|
{
|
||||||
|
margin-bottom: 0px;
|
||||||
|
display: inline;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<div id="map_dialog_%(name)s" class="map_dialog" title="Genauen Ort bestimmen">
|
||||||
|
|
||||||
|
<div style="margin: 4px 0 0 0">
|
||||||
|
<label></label>
|
||||||
|
<div id="map_%(name)s" class="map_canvas" style="width: %(width) dpx; height: %(height) dpx"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label requiredField">Angezeigter Ort </label>
|
||||||
|
<div class="controls">
|
||||||
|
<input class="displayed_location_input" type="text" value="Angezeiger Ort">
|
||||||
|
<button type="submit" class="coord_to_display_button btn btn-small">
|
||||||
|
<i class="icon-map-marker"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label requiredField">Koordinaten</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input class="coordinate_input" readonly="readonly" type="text">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,127 +1,189 @@
|
||||||
($ || django.jQuery)(function($){
|
($ || django.jQuery)(function($){
|
||||||
function location_field_load( map, base_field, initZoom )
|
|
||||||
|
|
||||||
|
|
||||||
|
// map: the div that is made to the map
|
||||||
|
// coordinate_field: input element where position & zoom is stored ( and read to init the map )
|
||||||
|
function MapObject( mapDiv, coordinate_field, init_position, init_zoom )
|
||||||
{
|
{
|
||||||
var parent = map.parent().parent();
|
// Default Argument for init_position
|
||||||
var coordinate_field = parent.find('input[type=text]');
|
init_position = typeof init_position !== 'undefined' ? init_position : new google.maps.LatLng( 49.340174,10.890595 );
|
||||||
|
init_zoom = typeof init_zoom !== 'undefined' ? init_zoom : 16;
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Members --------------------------------------
|
||||||
|
|
||||||
|
this.map = new google.maps.Map( mapDiv, {
|
||||||
|
mapTypeId: google.maps.MapTypeId.HYBRID,
|
||||||
|
zoomControl: true,
|
||||||
|
streetViewControl: false,
|
||||||
|
zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
|
||||||
|
} );
|
||||||
|
|
||||||
var map;
|
this.geocoder = new google.maps.Geocoder();
|
||||||
var current_position;
|
this.geocoder.region = "de";
|
||||||
|
this.geocoder.location = init_position;
|
||||||
|
|
||||||
//coordinate_field.hide();
|
this.marker = new google.maps.Marker({
|
||||||
coordinate_field.attr("readonly","readonly")
|
map: this.map,
|
||||||
|
position: init_position,
|
||||||
function load()
|
draggable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Methods --------------------------------------
|
||||||
|
|
||||||
|
this.placeMarkerUsingAddressString = function ( addressStr )
|
||||||
|
{
|
||||||
|
var theObject = this;
|
||||||
|
this.geocode( addressStr , function(l) {
|
||||||
|
theObject.placeMarker( l );
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.placeMarker = function( location )
|
||||||
{
|
{
|
||||||
var options = { mapTypeId: google.maps.MapTypeId.HYBRID };
|
this.marker.setPosition( location );
|
||||||
map = new google.maps.Map(map[0], options);
|
this.map.setCenter( location );
|
||||||
|
this.map.panTo( location );
|
||||||
if ( coordinate_field.val() ) // Already values in the coordinate field
|
|
||||||
{
|
|
||||||
var l = coordinate_field.val().split(/,/);
|
|
||||||
if (l.length > 1)
|
|
||||||
{
|
|
||||||
current_position = new google.maps.LatLng(l[0], l[1]);
|
|
||||||
map.setZoom( parseInt( l[2] ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! current_position )
|
|
||||||
{
|
|
||||||
var locationRohr = new google.maps.LatLng( 49.340174,10.890595 );
|
|
||||||
current_position = locationRohr;
|
|
||||||
map.setZoom( initZoom );
|
|
||||||
}
|
|
||||||
|
|
||||||
function savePosition( p ) {
|
|
||||||
current_position = p;
|
|
||||||
coordinate_field.val( current_position.lat().toFixed(6) + "," + current_position.lng().toFixed(6) + "," + map.getZoom() );
|
|
||||||
}
|
|
||||||
|
|
||||||
var marker = new google.maps.Marker({
|
|
||||||
map: map,
|
|
||||||
position: current_position,
|
|
||||||
draggable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
google.maps.event.addListener(marker, 'dragend', function(mouseEvent) {
|
|
||||||
savePosition(mouseEvent.latLng);
|
|
||||||
});
|
|
||||||
|
|
||||||
google.maps.event.addListener(map, 'click', function(mouseEvent){
|
|
||||||
marker.setPosition(mouseEvent.latLng);
|
|
||||||
savePosition( mouseEvent.latLng );
|
|
||||||
});
|
|
||||||
|
|
||||||
google.maps.event.addListener(map, 'zoom_changed', function(mouseEvent){
|
|
||||||
savePosition( current_position );
|
|
||||||
});
|
|
||||||
|
|
||||||
base_field.bindWithDelay( "keypress", function() {
|
|
||||||
|
|
||||||
geocode( base_field.val() , function(l){
|
|
||||||
coordinate_field.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 );
|
|
||||||
map.setZoom( latlng[2] );
|
|
||||||
}
|
|
||||||
|
|
||||||
function placeMarker(location) {
|
|
||||||
marker.setPosition(location);
|
|
||||||
map.setCenter(location);
|
|
||||||
savePosition(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( current_position );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load();
|
|
||||||
|
this.geocode = function(address, cb)
|
||||||
|
{
|
||||||
|
var result;
|
||||||
|
if (this.geocoder) {
|
||||||
|
this.geocoder.geocode({"address": address}, function(results, status) {
|
||||||
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
|
cb(results[0].geometry.location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.geocode_reverse = function( cb)
|
||||||
|
{
|
||||||
|
if (this.geocoder) {
|
||||||
|
this.geocoder.geocode({"latLng": this.marker.getPosition() }, function(results, status) {
|
||||||
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
|
cb( results );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveToInputField = function()
|
||||||
|
{
|
||||||
|
var p = this.marker.getPosition();
|
||||||
|
coordinate_field.value = p.lat().toFixed(6) + "," + p.lng().toFixed(6) + "," + this.map.getZoom() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadFromInputField = function()
|
||||||
|
{
|
||||||
|
if ( coordinate_field.value ) // Already values in the coordinate field
|
||||||
|
{
|
||||||
|
var l = coordinate_field.value.split(/,/);
|
||||||
|
if (l.length > 1)
|
||||||
|
{
|
||||||
|
this.placeMarker( new google.maps.LatLng(l[0], l[1]) );
|
||||||
|
this.map.setZoom( parseInt( l[2] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.placeMarker( init_position );
|
||||||
|
this.map.setZoom( 16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Constructor -------------------------------------
|
||||||
|
|
||||||
|
this.init = function()
|
||||||
|
{
|
||||||
|
var theObject = this;
|
||||||
|
// Event handling
|
||||||
|
google.maps.event.addListener( this.marker, 'dragend', function(mouseEvent) {
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
google.maps.event.addListener( this.map, 'click', function(mouseEvent){
|
||||||
|
theObject.placeMarker( mouseEvent.latLng );
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
google.maps.event.addListener( this.map, 'zoom_changed', function(mouseEvent){
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
theObject.loadFromInputField();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(".map_dialog").dialog( {
|
||||||
|
modal: true,
|
||||||
|
width: 650,
|
||||||
|
height: 730,
|
||||||
|
resizeable: false,
|
||||||
|
autoOpen: false
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
$('input[data-location-widget]').click( function() {
|
||||||
|
|
||||||
|
var formCoordField = $(this);
|
||||||
|
var $basedField = $( formCoordField.attr('data-based-field') );
|
||||||
|
var $dialogElement = $( formCoordField.attr('data-dialog-id') );
|
||||||
|
|
||||||
|
var $dialogCoordField = $dialogElement.find(".coordinate_input");
|
||||||
|
var $dialogLocationField = $dialogElement.find(".displayed_location_input");
|
||||||
|
$dialogLocationField.val( $basedField.val() );
|
||||||
|
$dialogCoordField.val( formCoordField.val() );
|
||||||
|
|
||||||
|
// Init Map if not yet initialized:
|
||||||
|
var map;
|
||||||
|
if ( ! $dialogElement[0].map )
|
||||||
|
{
|
||||||
|
map = $( formCoordField.attr('data-map') )[0];
|
||||||
|
var zoom = parseInt( formCoordField.attr('data-zoom') );
|
||||||
|
|
||||||
|
// Add Buttons
|
||||||
|
$dialogElement.dialog( "option", "buttons", {
|
||||||
|
Abbrechen: function() {
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
},
|
||||||
|
Ok: function() {
|
||||||
|
$(formCoordField).val( $dialogCoordField.val() );
|
||||||
|
$basedField.val( $dialogLocationField.val() );
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
} }
|
||||||
|
);
|
||||||
|
|
||||||
$('input[data-location-widget]').each(function(){
|
// Init Map
|
||||||
var $el = $(this);
|
$dialogElement[0].map = new MapObject( map, $dialogCoordField[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialogLocationField.on("keypress", function(e) {
|
||||||
|
if ( e.keyCode == 13 ) { // enter
|
||||||
|
$dialogElement[0].map.placeMarkerUsingAddressString( $dialogLocationField.val() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$dialogElement.find(".coord_to_display_button").click( function() {
|
||||||
|
$dialogElement[0].map.geocode_reverse( function(result) {
|
||||||
|
$dialogLocationField.val( result[0].formatted_address );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var $map = $($el.attr('data-map')),
|
|
||||||
$based_field = $(($el.attr('data-based-field'))),
|
$dialogElement.dialog('open');
|
||||||
zoom = parseInt($el.attr('data-zoom'));
|
|
||||||
|
|
||||||
location_field_load( $map, $based_field, zoom );
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
class LocationWidget(widgets.TextInput):
|
class LocationWidget(widgets.TextInput):
|
||||||
def __init__(self, attrs=None, based_field=None, zoom=None, width=610, height = 480, **kwargs):
|
def __init__(self, attrs=None, based_field=None, zoom=None, width=610, height = 480, **kwargs):
|
||||||
self.based_field = based_field
|
self.based_field = based_field
|
||||||
|
@ -24,26 +26,33 @@ class LocationWidget(widgets.TextInput):
|
||||||
based_field = "#id_" + self.based_field.name
|
based_field = "#id_" + self.based_field.name
|
||||||
|
|
||||||
attrs = attrs or {}
|
attrs = attrs or {}
|
||||||
|
attrs['readonly'] = "readonly"
|
||||||
attrs['data-location-widget'] = name
|
attrs['data-location-widget'] = name
|
||||||
attrs['data-based-field'] = based_field
|
attrs['data-based-field'] = based_field
|
||||||
attrs['data-zoom'] = self.zoom
|
attrs['data-zoom'] = self.zoom
|
||||||
attrs['data-map'] = '#map_' + name
|
attrs['data-map'] = '#map_' + name
|
||||||
|
attrs['data-dialog-id'] = "#map_dialog_" + name
|
||||||
text_input = super(LocationWidget, self).render(name, value, attrs)
|
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: %(width)dpx; height: %(height)dpx"></div>
|
|
||||||
</div>
|
|
||||||
'''
|
|
||||||
|
|
||||||
return mark_safe(text_input + map_div % {'name': name, 'width': self.width, 'height': self.height })
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
with open( path + "/media/form.html" , 'r') as content_file:
|
||||||
|
html = content_file.read()
|
||||||
|
|
||||||
|
return mark_safe(text_input + html % {'name': name, 'width': self.width, 'height': self.height })
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
|
css = {
|
||||||
|
'all' : ('/location_field/media/form.css', )
|
||||||
|
}
|
||||||
# Use schemaless URL so it works with both, http and https websites
|
# Use schemaless URL so it works with both, http and https websites
|
||||||
js = (
|
js = (
|
||||||
'//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js', # jquery
|
'//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js', # jquery
|
||||||
|
'//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
|
||||||
'//maps.google.com/maps/api/js?sensor=false&language=de',
|
'//maps.google.com/maps/api/js?sensor=false&language=de',
|
||||||
'/static/js/bindWithDelay.js',
|
'/static/js/bindWithDelay.js',
|
||||||
'/location_field/media/form.js',
|
'/location_field/media/form.js',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,16 @@
|
||||||
height: 480px;
|
height: 480px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#map img
|
||||||
|
{
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
#map label
|
||||||
|
{
|
||||||
|
margin-bottom: 0px;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
#concert_route .map iframe{
|
#concert_route .map iframe{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,9 @@
|
||||||
var myOptions = {
|
var myOptions = {
|
||||||
zoom: 10,
|
zoom: 10,
|
||||||
mapTypeId: google.maps.MapTypeId.ROAD,
|
mapTypeId: google.maps.MapTypeId.ROAD,
|
||||||
zoomControl: false
|
zoomControl: false,
|
||||||
|
panControl: false,
|
||||||
|
streetViewControl: false
|
||||||
}
|
}
|
||||||
var directionsService = new google.maps.DirectionsService();
|
var directionsService = new google.maps.DirectionsService();
|
||||||
var directionsDisplay = new google.maps.DirectionsRenderer();
|
var directionsDisplay = new google.maps.DirectionsRenderer();
|
||||||
|
|
Loading…
Reference in New Issue