From 6c3a7ca4084035be244419ccbf84aa5a481aa8f2 Mon Sep 17 00:00:00 2001 From: Martin Bauer Date: Sat, 28 Sep 2013 11:41:05 +0200 Subject: [PATCH] location field refactor --- .../eventplanner/event_update_form.html | 1 + location_field/media/form.css | 29 ++ location_field/media/form.html | 28 ++ location_field/media/form.js | 286 +++++++++++------- location_field/widgets.py | 23 +- website/static/css/concert_route.css | 10 + website/templates/website/concert_route.html | 4 +- 7 files changed, 261 insertions(+), 120 deletions(-) create mode 100644 location_field/media/form.css create mode 100644 location_field/media/form.html diff --git a/eventplanner/templates/eventplanner/event_update_form.html b/eventplanner/templates/eventplanner/event_update_form.html index 63851b1..6334f6f 100644 --- a/eventplanner/templates/eventplanner/event_update_form.html +++ b/eventplanner/templates/eventplanner/event_update_form.html @@ -42,6 +42,7 @@ {% addtoblock "css" strip %} {% endaddtoblock %} {% addtoblock "css" strip %} {% endaddtoblock %} +{% addtoblock "css" strip %} {% endaddtoblock %} {% addtoblock "js" %} diff --git a/location_field/media/form.css b/location_field/media/form.css new file mode 100644 index 0000000..35751df --- /dev/null +++ b/location_field/media/form.css @@ -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; +} \ No newline at end of file diff --git a/location_field/media/form.html b/location_field/media/form.html new file mode 100644 index 0000000..6c9d350 --- /dev/null +++ b/location_field/media/form.html @@ -0,0 +1,28 @@ +
+ +
+ +
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ +
+
+
+
+
\ No newline at end of file diff --git a/location_field/media/form.js b/location_field/media/form.js index 7dff5f6..d719d10 100644 --- a/location_field/media/form.js +++ b/location_field/media/form.js @@ -1,127 +1,189 @@ ($ || 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(); - var coordinate_field = parent.find('input[type=text]'); + // Default Argument for init_position + 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; - var current_position; + this.geocoder = new google.maps.Geocoder(); + this.geocoder.region = "de"; + this.geocoder.location = init_position; - //coordinate_field.hide(); - coordinate_field.attr("readonly","readonly") - - function load() + this.marker = new google.maps.Marker({ + map: this.map, + position: init_position, + 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 }; - map = new google.maps.Map(map[0], options); - - 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 ); + this.marker.setPosition( location ); + this.map.setCenter( location ); + this.map.panTo( location ); } - 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(){ - var $el = $(this); + // Init Map + $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'))), - zoom = parseInt($el.attr('data-zoom')); - - location_field_load( $map, $based_field, zoom ); + + $dialogElement.dialog('open'); }); + }); diff --git a/location_field/widgets.py b/location_field/widgets.py index a255e99..da00966 100644 --- a/location_field/widgets.py +++ b/location_field/widgets.py @@ -1,6 +1,8 @@ from django.forms import widgets from django.utils.safestring import mark_safe +import os + class LocationWidget(widgets.TextInput): def __init__(self, attrs=None, based_field=None, zoom=None, width=610, height = 480, **kwargs): self.based_field = based_field @@ -24,26 +26,33 @@ class LocationWidget(widgets.TextInput): based_field = "#id_" + self.based_field.name attrs = attrs or {} + attrs['readonly'] = "readonly" attrs['data-location-widget'] = name attrs['data-based-field'] = based_field attrs['data-zoom'] = self.zoom attrs['data-map'] = '#map_' + name - + attrs['data-dialog-id'] = "#map_dialog_" + name text_input = super(LocationWidget, self).render(name, value, attrs) - map_div = u''' -
-
-
- ''' - 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: + css = { + 'all' : ('/location_field/media/form.css', ) + } # 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 + '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js', '//maps.google.com/maps/api/js?sensor=false&language=de', '/static/js/bindWithDelay.js', '/location_field/media/form.js', ) + + + diff --git a/website/static/css/concert_route.css b/website/static/css/concert_route.css index f65def7..6170387 100644 --- a/website/static/css/concert_route.css +++ b/website/static/css/concert_route.css @@ -4,6 +4,16 @@ height: 480px; } +#map img +{ + max-width: none; +} +#map label +{ + margin-bottom: 0px; + display: inline; +} + #concert_route .map iframe{ display: block; } diff --git a/website/templates/website/concert_route.html b/website/templates/website/concert_route.html index fbaefa6..b5c84cc 100644 --- a/website/templates/website/concert_route.html +++ b/website/templates/website/concert_route.html @@ -100,7 +100,9 @@ var myOptions = { zoom: 10, mapTypeId: google.maps.MapTypeId.ROAD, - zoomControl: false + zoomControl: false, + panControl: false, + streetViewControl: false } var directionsService = new google.maps.DirectionsService(); var directionsDisplay = new google.maps.DirectionsRenderer();