diff options
| author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-08-17 13:13:15 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-08-22 02:08:33 +0200 | 
| commit | 1091d481584af4662488ee83d7fa1421f8d1700c (patch) | |
| tree | 0fb060c8cc3c7280a4f9d643db34216597a0b302 | |
| parent | 232a1de132fa75431b45c008b72dafbcc6130b14 (diff) | |
| download | Chimère-1091d481584af4662488ee83d7fa1421f8d1700c.tar.bz2 Chimère-1091d481584af4662488ee83d7fa1421f8d1700c.zip  | |
Improve routing interface and functionalities
* fix POI clicking
* create a nominatim widget to get coordinates from text
* create a JQuery UI button select widget
* create a routing form to get itinerary from a textual form
* CSS for the routing form
* Reverse nominatim: when a point is get for routing on the map
  label for this point is get from nominatim
* Add transport management by user choice
* Update french translation
| -rw-r--r-- | chimere/forms.py | 18 | ||||
| -rw-r--r-- | chimere/locale/fr/LC_MESSAGES/django.po | 87 | ||||
| -rw-r--r-- | chimere/static/chimere/css/styles.css | 58 | ||||
| -rw-r--r-- | chimere/static/chimere/img/images_licences | 6 | ||||
| -rw-r--r-- | chimere/static/chimere/js/jquery.chimere.js | 155 | ||||
| -rw-r--r-- | chimere/static/chimere/js/nominatim-widget.js | 41 | ||||
| -rw-r--r-- | chimere/templates/chimere/blocks/routing.html | 37 | ||||
| -rw-r--r-- | chimere/templatetags/chimere_tags.py | 3 | ||||
| -rw-r--r-- | chimere/urls.py | 4 | ||||
| -rw-r--r-- | chimere/views.py | 4 | ||||
| -rw-r--r-- | chimere/widgets.py | 53 | ||||
| -rw-r--r-- | example_project/settings.py | 14 | 
12 files changed, 392 insertions, 88 deletions
diff --git a/chimere/forms.py b/chimere/forms.py index d877a22..f49a903 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -35,7 +35,7 @@ from chimere.models import Marker, Route, PropertyModel, Property, Area,\       News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \       PictureFile, Importer  from chimere.widgets import AreaField, PointField, TextareaWidget, \ -                            DatePickerWidget +                            DatePickerWidget, ButtonSelectWidget, NominatimWidget  from datetime import timedelta, datetime, tzinfo @@ -454,3 +454,19 @@ class AreaForm(AreaAdminForm):      class Meta:          model = Area +class RoutingForm(forms.Form): +    transport = forms.ChoiceField(label='', widget=ButtonSelectWidget, +                               choices=settings.CHIMERE_ROUTING_TRANSPORT, +                               initial=settings.CHIMERE_ROUTING_TRANSPORT[0][0]) +    start = forms.CharField(label=_(u"Start"), widget=NominatimWidget) +    end = forms.CharField(label=_(u"Finish"), widget=NominatimWidget) +    speed = forms.ChoiceField(label=_(u"Speed"), choices=[], required=False) + +    def __init__(self, *args, **kwargs): +        super(RoutingForm, self).__init__(*args, **kwargs) +        if not settings.CHIMERE_ROUTING_SPEEDS: +            self.fields.pop('speed') +        for transport in settings.CHIMERE_ROUTING_SPEEDS: +            for speed, lbl in settings.CHIMERE_ROUTING_SPEEDS[transport]: +                self.fields['speed'].widget.choices.append( +                                ("%s_%d" % (transport, speed), lbl)) diff --git a/chimere/locale/fr/LC_MESSAGES/django.po b/chimere/locale/fr/LC_MESSAGES/django.po index ad397ae..e68d0e8 100644 --- a/chimere/locale/fr/LC_MESSAGES/django.po +++ b/chimere/locale/fr/LC_MESSAGES/django.po @@ -134,8 +134,20 @@ msgstr "Nom"  msgid "Area"  msgstr "Zone" -#: models.py:50 models.py:124 models.py:151 models.py:244 models.py:453 -#: models.py:822 models.py:903 +#: forms.py:445 +msgid "Start" +msgstr "Départ" + +#: forms.py:446 +msgid "Finish" +msgstr "Arrivée :" + +#: forms.py:447 +msgid "Speed" +msgstr "Vitesse" + +#: models.py:49 models.py:123 models.py:150 models.py:241 models.py:441 +#: models.py:810 models.py:891  msgid "Available"  msgstr "Disponible" @@ -630,19 +642,19 @@ msgstr ""  msgid "Bad param"  msgstr "Mauvais paramètre" -#: views.py:234 +#: views.py:228  msgid "There are missing field(s) and/or errors in the submited form."  msgstr "Il y a des champs manquants ou des erreurs dans ce formulaire." -#: views.py:317 +#: views.py:307  msgid "Bad file. Please check it with an external software."  msgstr "Fichier incohérent. Merci de le vérifier avec un logiciel externe." -#: views.py:439 +#: views.py:429  msgid "Comments/request on the map"  msgstr "Commentaires/requètes sur la carte" -#: views.py:442 +#: views.py:432  msgid ""  "Thank you for your contribution. It will be taken into account. If you have "  "left your email you may be contacted soon for more details." @@ -663,36 +675,36 @@ msgstr "Pas de catégorie disponible sur cette zone."  msgid "Incorrect choice in the list"  msgstr "Choix incorrect dans la liste" -#: widgets.py:187 +#: widgets.py:240  msgid "Latitude"  msgstr "Latitude" -#: widgets.py:187 +#: widgets.py:240  msgid "Longitude"  msgstr "Longitude" -#: widgets.py:212 +#: widgets.py:265  msgid "Invalid point"  msgstr "Point invalide" -#: widgets.py:262 +#: widgets.py:315  msgid "Creation mode"  msgstr "Mode création" -#: widgets.py:263 +#: widgets.py:316  msgid "To start drawing the route click on the toggle button: \"Draw\"."  msgstr ""  "Pour commencer le dessin cliquez sur le bouton : « Tracer »." -#: widgets.py:265 +#: widgets.py:318  msgid "Then click on the map to begin the drawing."  msgstr "Puis cliquez sur la carte pour commencer le dessin." -#: widgets.py:266 +#: widgets.py:319  msgid "You can add points by clicking again."  msgstr "Vous pouvez ajouter des points en cliquant de nouveau." -#: widgets.py:267 +#: widgets.py:320  msgid ""  "To finish the drawing double click. When the drawing is finished you can "  "edit it." @@ -700,7 +712,7 @@ msgstr ""  "Pour finir le tracé double-cliquez. Quand le tracé est fini vous pouvez "  "toujours l'éditer." -#: widgets.py:269 +#: widgets.py:322  msgid ""  "While creating to undo a drawing click again on the toggle button \"Stop "  "drawing\"." @@ -708,17 +720,17 @@ msgstr ""  "En mode création vous pouvez annuler un tracé en appuyant sur le bouton "  "« Arrêter le tracé »." -#: widgets.py:274 +#: widgets.py:327  msgid "Modification mode"  msgstr "Mode modification" -#: widgets.py:275 +#: widgets.py:328  msgid "To move a point click on it and drag it to the desired position."  msgstr ""  "Pour bouger un point, cliquez dessus, maintenez le click pour le déposer à "  "la position désirée." -#: widgets.py:276 +#: widgets.py:329  msgid ""  "To delete a point move the mouse cursor over it and press the \"d\" or \"Del"  "\" key." @@ -726,7 +738,7 @@ msgstr ""  "Pour supprimer un point, mettez le curseur de la souris sur celui-ci et "  "appuyez sur le touche « d » ou « Suppr »." -#: widgets.py:278 +#: widgets.py:331  msgid ""  "To add a point click in the middle of a segment and drag the new point to "  "the desired position" @@ -735,33 +747,33 @@ msgstr ""  "maintenez le bouton appuyé et déplacez le nouveau point à la position "  "désirée." -#: widgets.py:285 +#: widgets.py:338  msgid "Give a name and set category before uploading a file."  msgstr ""  "Renseignez le nom et choisissez au moins une catégorie avant de déposer un "  "fichier." -#: widgets.py:288 +#: widgets.py:341  msgid "Upload a route file (GPX or KML)"  msgstr "Déposer un trajet (fichier GPX ou KML)" -#: widgets.py:289 +#: widgets.py:342  msgid "or"  msgstr "ou" -#: widgets.py:294 +#: widgets.py:347  msgid "Start \"hand\" drawing"  msgstr "Commencer le tracé manuellement" -#: widgets.py:317 +#: widgets.py:370  msgid "Move on the map"  msgstr "Se déplacer" -#: widgets.py:317 +#: widgets.py:370  msgid "Draw"  msgstr "Tracer" -#: widgets.py:442 +#: widgets.py:495  msgid "Select..."  msgstr "Sélectionner..." @@ -955,11 +967,27 @@ msgstr ""  "Utilisez un navigateur internet plus récent ou installez le greffon non "  "libre Flash." -#: templates/chimere/blocks/routing.html:3 -#: templates/chimere/blocks/routing.html:13 +#: templates/chimere/blocks/routing.html:4 +#: templates/chimere/blocks/routing.html:40  msgid "Itinerary"  msgstr "Itinéraire" +#: templates/chimere/blocks/routing.html:19 +msgid "Modify" +msgstr "Modifier" + +#: templates/chimere/blocks/routing.html:22 +msgid "New search" +msgstr "Nouvelle recherche" + +#: templates/chimere/blocks/routing.html:27 +msgid "Start:" +msgstr "Départ :" + +#: templates/chimere/blocks/routing.html:31 +msgid "Finish:" +msgstr "Arrivée :" +  #: templates/chimere/blocks/submited.html:3  msgid ""  "Your new proposition/modification has been submited. A moderator will treat " @@ -1023,3 +1051,6 @@ msgstr "Choisir une zone pré-définie"  #: templates/chimere/feeds/rss.html:64  msgid "Or select the area by zooming and panning this map"  msgstr "Ou sélectionner une zone en zoomant et en se déplaçant sur cette carte" + +#~ msgid "End" +#~ msgstr "Fin" diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index dec91e6..ceb3b60 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -411,36 +411,69 @@ ul#share li{      top:50px;      right:18px;      width:300px; -    bottom:44px; +    max-height:300px;      overflow:auto;      padding:0.5em;      padding-top:0;  } -#chimere_itinerary table +#chimere_itinerary_panel, +#chimere_itinerary{ +    display:none; +} + +#chimere_itinerary_panel label{ +    color:#000; +} + +#chimere_itinerary_panel p +{ +    margin:0.5em; +} + +.itinerary_label{ +    font-size:0.9em; +    padding-top:0.5em; +     font-style:italic; +} + +.itinerary_label.label{ +  font-style:normal; +  font-weight:bold; +} + + +#chimere_itinerary_content{ +    overflow:auto; +    height:190px; +    margin-top:10px; +} + +#chimere_itinerary_content table  {      border-collapse:collapse;  } -#chimere_itinerary td{ -    border:8px solid #fff; +#chimere_itinerary_content table td{ +    border:1px solid #333;  } -#chimere_itinerary td.l{ +#chimere_itinerary_content td.l{      padding:5px;      width:60px;  } -#chimere_itinerary td.r{ +#chimere_itinerary_content td.r{      font-size:0.8em; +    padding:0.8em;  } -#chimere_itinerary span.j{ +#chimere_itinerary_content span.j{      font-style:italic;  } -#chimere_itinerary span.t, -#chimere_itinerary span.b +#chimere_itinerary_content span.t, +#chimere_itinerary_content span.b  {      text-transform: lowercase;  } @@ -476,6 +509,13 @@ ul#share li{      background-color:#ccc;  } +.nominatim-label{ +    display:block; +    font-size:0.9em; +    font-weight:bold; +    height:2.8em; +} +  .simple #panel{      top:5px;  } diff --git a/chimere/static/chimere/img/images_licences b/chimere/static/chimere/img/images_licences index 03d63dc..cbc9307 100644 --- a/chimere/static/chimere/img/images_licences +++ b/chimere/static/chimere/img/images_licences @@ -1,5 +1,5 @@ -* Upload image credit +* Upload image credit (upload.png)      * Farm-Fresh layer gps.png in Farm-Fresh Web Icons  Author: FatCow Web Hosting @@ -16,7 +16,7 @@ Author: The Tango! Desktop Project  Licence: Public domain  Url: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg -* Drawing image credit +* Drawing image credit (drawing.png)      * Icons from the Tango! project set.  Author: The Tango! Desktop Project @@ -24,7 +24,7 @@ Licence: Public domain  Url: http://commons.wikimedia.org/wiki/File:Edit-find-replace.svg  Url 2: http://commons.wikimedia.org/wiki/File:Internet-web-browser.svg -* Quaver image credit +* Quaver image credit (8thNote.png)      *   An 8th-note.  Author: Sbrools diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 7676517..ff90f28 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -171,6 +171,40 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              }              settings.map.setBaseLayer(                              settings.map_layers[settings.selected_map_layer]); + +            /* manage the context menu  */ +            $('#map_menu_zoomin').bind("click", methods.zoomIn); +            $('#map_menu_zoomout').bind("click", methods.zoomOut); +            $('#map_menu_center').bind("click", methods.mapCenter); +            /* manage the routing */ +            if (settings.routing){ +                settings.routing_start = null; +                settings.routing_steps = new Array(); +                settings.routing_end = null; +                settings.icon_start = new OpenLayers.Icon( +                    STATIC_URL + "chimere/img/flag-start.png", +                    new OpenLayers.Size(32, 32), +                    new OpenLayers.Pixel(0, -32)); +                settings.icon_step = new OpenLayers.Icon( +                    STATIC_URL + "chimere/img/flag-step.png", +                    new OpenLayers.Size(32, 32), +                    new OpenLayers.Pixel(0, -32)); +                settings.icon_end = new OpenLayers.Icon( +                    STATIC_URL + "chimere/img/flag-finish.png", +                    new OpenLayers.Size(32, 32), +                    new OpenLayers.Pixel(0, -32)); +                $('#map_menu_from').bind("click", methods.routingFrom); +                $('#map_menu_step').bind("click", methods.routingAddStep); +                $('#map_menu_to').bind("click", methods.routingTo); +                $('#map_menu_clear').bind("click", methods.routingClear); +                settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); +                settings.map.addLayer(settings.layerRoute); +                settings.layerRoute.setOpacity(0.8); +                settings.layerRouteMarker = new OpenLayers.Layer.Markers( +                                                               'Route markers'); +                settings.map.addLayer(settings.layerRouteMarker); +                settings.layerRouteMarker.setOpacity(0.8); +            }              /* Vectors layer */              settings.layerVectors = new OpenLayers.Layer.Vector("Vector Layer");              settings.map.addLayer(settings.layerVectors); @@ -226,37 +260,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {                          settings.layerVectors, helpers.featureRouteCreated);                  }              } -            $('#map_menu_zoomin').bind("click", methods.zoomIn); -            $('#map_menu_zoomout').bind("click", methods.zoomOut); -            $('#map_menu_center').bind("click", methods.mapCenter); -            if (settings.routing){ -                settings.routing_start = null; -                settings.routing_steps = new Array(); -                settings.routing_end = null; -                settings.icon_start = new OpenLayers.Icon( -                    STATIC_URL + "chimere/img/flag-start.png", -                    new OpenLayers.Size(32, 32), -                    new OpenLayers.Pixel(0, -32)); -                settings.icon_step = new OpenLayers.Icon( -                    STATIC_URL + "chimere/img/flag-step.png", -                    new OpenLayers.Size(32, 32), -                    new OpenLayers.Pixel(0, -32)); -                settings.icon_end = new OpenLayers.Icon( -                    STATIC_URL + "chimere/img/flag-finish.png", -                    new OpenLayers.Size(32, 32), -                    new OpenLayers.Pixel(0, -32)); -                $('#map_menu_from').bind("click", methods.routingFrom); -                $('#map_menu_step').bind("click", methods.routingAddStep); -                $('#map_menu_to').bind("click", methods.routingTo); -                $('#map_menu_clear').bind("click", methods.routingClear); -                settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); -                settings.map.addLayer(settings.layerRoute); -                settings.layerRoute.setOpacity(0.8); -                settings.layerRouteMarker = new OpenLayers.Layer.Markers( -                                                               'Route markers'); -                settings.map.addLayer(settings.layerRouteMarker); -                settings.layerRouteMarker.setOpacity(0.8); -            }          }, // end of init          // zoom in from the map menu @@ -281,7 +284,7 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {          * Display menu on the map          */          displayMapMenu: function(e) { -            helpers.hidePopup(); +            if (helpers.hidePopup()) return;              if ($('#chimere_map_menu').is(":visible")){                  $('#chimere_map_menu').hide();              } else{ @@ -460,7 +463,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {                          if (settings.current_popup == feature.popup) {                              feature.popup.hide();                              if (!settings.simple){ -                                $('#panel').removeClass('panel-minified');                                  $('#detail').hide();                              }                          } else { @@ -520,23 +522,51 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              settings.current_feature.geometry = linestring;              settings.layerVectors.addFeatures([settings.current_feature]);          }, +        routingInputChange: function(){ +            $('#map_menu_clear').show(); +            if ($('#nominatim_start_lon').val()){ +                settings.routing_start = new OpenLayers.Marker( +                  new OpenLayers.LonLat($('#nominatim_start_lon').val(), +                                        $('#nominatim_start_lat').val() +                                        ).transform(EPSG_DISPLAY_PROJECTION, +                                            settings.map.getProjectionObject()), +                                      settings.icon_start); +                settings.layerRouteMarker.addMarker(settings.routing_start); +            } +            if ($('#nominatim_end_lon').val()){ +                settings.routing_end = new OpenLayers.Marker( +                  new OpenLayers.LonLat($('#nominatim_end_lon').val(), +                                        $('#nominatim_end_lat').val() +                                        ).transform(EPSG_DISPLAY_PROJECTION, +                                            settings.map.getProjectionObject()), +                                      settings.icon_end); +                settings.layerRouteMarker.addMarker(settings.routing_end); +            } +            if (settings.routing_end && settings.routing_start) methods.route(); +        }, +          // set the start point for routing          routingFrom: function(){              $('#chimere_map_menu').hide(); +            $('#chimere_itinerary_panel').dialog('open');              $('#map_menu_clear').show(); -            $('#chimere_itinerary_panel').dialog('close');              settings.routing_start = new OpenLayers.Marker(                                            settings.current_position.clone(),                                            settings.icon_start);              settings.layerRouteMarker.addMarker(settings.routing_start); +            if (nominatim_url){ +                helpers.updateNominatimName(settings.current_position.clone() +                                 .transform(settings.map.getProjectionObject(), +                                            EPSG_DISPLAY_PROJECTION), +                                            'start_label'); +            }              if (settings.routing_end) methods.route();          }, -          // add a step point for routing          routingAddStep: function(){              $('#chimere_map_menu').hide(); +            $('#chimere_itinerary_panel').dialog('open');              $('#map_menu_clear').show(); -            $('#chimere_itinerary_panel').dialog('close');              settings.routing_steps.push(new OpenLayers.Marker(                                            settings.current_position.clone(),                                            settings.icon_step.clone())); @@ -548,20 +578,36 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {          // set the finish point for routing          routingTo: function(){              $('#chimere_map_menu').hide(); +            $('#chimere_itinerary_panel').dialog('open');              $('#map_menu_clear').show(); -            $('#chimere_itinerary_panel').dialog('close');              settings.routing_end = new OpenLayers.Marker(                                            settings.current_position.clone(),                                            settings.icon_end);              settings.layerRouteMarker.addMarker(settings.routing_end); +            if (nominatim_url){ +                helpers.updateNominatimName(settings.current_position.clone() +                                 .transform(settings.map.getProjectionObject(), +                                            EPSG_DISPLAY_PROJECTION), +                                            'end_label'); +            }              if (settings.routing_start) methods.route();          },          // clear the current itinerary          routingClear: function(){ +            $('#nominatim_start_lon').val(''); +            $('#nominatim_start_lat').val(''); +            $('#nominatim_start_label').html(''); +            $('#chimere_start_label').html(''); +            $('#nominatim_end_lon').val(''); +            $('#nominatim_end_lat').val(''); +            $('#nominatim_end_label').html(''); +            $('#chimere_end_label').html(''); +            $('.nominatim-widget').val('');              $('#chimere_map_menu').hide();              $('#map_menu_clear').hide(); -            $('#chimere_itinerary_panel').dialog('close'); +            $('#chimere_itinerary').hide(); +            $('#chimere_itinerary_form').show();              settings.layerRoute.removeAllFeatures();              settings.layerRouteMarker.clearMarkers();              settings.routing_start = null; @@ -581,6 +627,8 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              steps.push(settings.routing_end.lonlat.clone());              // create the appropriate URL              var uri = extra_url + "route/" +            var transport = $('input:radio[name=transport]:checked').val(); +            uri += transport + "/"              for (var i = 0; i < steps.length; i++) {                  var step = steps[i].transform(                                              settings.map.getProjectionObject(), @@ -597,8 +645,13 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {                          for (var i = 0; i < data.features.length; i++) {                              methods.putRoute(data.features[i]);                          } -                        $('#chimere_itinerary').html( +                        settings.map.zoomToExtent( +                                settings.layerRoute.getDataExtent()); +                        settings.map.zoomOut(); +                        $('#chimere_itinerary_content').html(                                              data.properties.description); +                        $('#chimere_itinerary').show(); +                        $('#chimere_itinerary_form').hide();                          $('#chimere_itinerary_panel').dialog('open');                      },                      error: function (data) { @@ -645,7 +698,6 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {                              }                              else {                                  if (!settings.simple) { -                                    $('#panel').addClass('panel-minified');                                      $('#detail').html(data).show();                                  }                                  else { @@ -818,13 +870,16 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              else { // Default behaviour                  if (settings.current_popup)                  { -                    settings.current_popup.hide();                      if (!settings.simple){ -                        $('#panel').removeClass('panel-minified');                          $('#detail').hide();                      } +                    if (settings.current_popup.visible()){ +                        settings.current_popup.hide(); +                        return true; +                    }                  }              } +            return false;          },          getSubcategories: function (category_id) {              if(settings.get_subcategories_fx) { @@ -949,8 +1004,22 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              if (vertices){                  jQuery('#id_point').val(vertices);              } +        }, +        updateNominatimName:function(lonlat, response_id){ +            $.ajax({ +                url: nominatim_url.substring(0, nominatim_url.length-6) + 'reverse', +                data: { +                    format: "json", +                    lat:lonlat.lat, +                    lon:lonlat.lon +                }, +                success: function (data) { +                    vals = $.parseJSON(data); +                    $('#nominatim_'+response_id).html(vals.display_name); +                    $('#chimere_'+response_id).html(vals.display_name); +                } +            });          } -      }; // End of helpers      $.fn.chimere = function (thing) { diff --git a/chimere/static/chimere/js/nominatim-widget.js b/chimere/static/chimere/js/nominatim-widget.js new file mode 100644 index 0000000..fea654d --- /dev/null +++ b/chimere/static/chimere/js/nominatim-widget.js @@ -0,0 +1,41 @@ + +$(function(){ +    $(".nominatim-widget").autocomplete({ +           source: function (request, response) { +               $.ajax({ +                      url: nominatim_url, +                      data: { +                          format: "json", +                          q: request.term, +                      }, +                      success: function ( data ) { +                          response ( $.map( $.parseJSON(data), function( item ) { +                              return { +                                  label: item.display_name, +                                  value: item.display_name, +                                  lat: item.lat, +                                  lon: item.lon +                              }})); + +                          } +                      }) +            }, +            minLength: 6, +            delay: 1000, +            select: function ( event, ui ) { +                $('#'+$(this).attr('id')+'_lat').val(ui.item.lat); +                $('#'+$(this).attr('id')+'_lon').val(ui.item.lon); +                $('#'+$(this).attr('id')+'_label').html(ui.item.label); +                $('#chimere_'+$(this).attr('id').substring(10)+'_label').html(ui.item.label); +                $('#'+$(this).attr('id')).val(''); +                jQuery("#map").chimere("routingInputChange"); +                return false; +            }, +            open: function() { +                $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); +            }, +            close: function() { +                $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); +            } +    }); +}); diff --git a/chimere/templates/chimere/blocks/routing.html b/chimere/templates/chimere/blocks/routing.html index 226480b..4948a1c 100644 --- a/chimere/templates/chimere/blocks/routing.html +++ b/chimere/templates/chimere/blocks/routing.html @@ -1,8 +1,35 @@  {% load i18n %}  {% if routing %} +{{itinerary_form.media}}  <a href='#' id='routing_button' class='ui-widget ui-button ui-state-default ui-corner-all'>{% trans "Itinerary"%}</a>  <div id='chimere_itinerary_panel'> +    <div id='chimere_itinerary_form'> +    {% for hidden in itinerary_form.hidden_fields %} +      {{ hidden }} +    {% endfor %} +    {% for field in itinerary_form.visible_fields %} +    {% if field.label %}<p><label for='{{field.auto_id}}'>{{ field.label }}</label></p>{%endif%} +    <p>{{field}}</p> +    {% endfor %} +    </div>      <div id='chimere_itinerary'> +        <div id='chimere_itinerary_action'> +            <ul class='action'> +                <li class='ui-widget ui-button ui-state-default ui-corner-all'> +                    <a href='#' id='chimere_itinerary_modify'>{% trans "Modify" %}</a> +                </li> +                <li class='ui-widget ui-button ui-state-default ui-corner-all'> +                    <a href='#' id='chimere_itinerary_new'>{% trans "New search" %}</a> +                </li> +            </ul> +        </div> +        <div class='itinerary_label'> +            <span class='label'>{% trans "Start:"%}</span> <span id='chimere_start_label'></span></div> +        <div id='chimere_itinerary_content'> +        </div> +        <div class='itinerary_label'> +            <span class='label'>{% trans "Finish:"%}</span> <span id='chimere_end_label'></span> +        </div>      </div>  </div>  <script language='javascript' type='text/javascript'> @@ -11,11 +38,19 @@ $(document).ready(function() {              autoOpen: false,              position: [50, 50],              title: "{% trans "Itinerary" %}", -            height: 300 +            height: 360, +            resizable: false      });      $('#routing_button').click(function(){          $('#chimere_itinerary_panel').dialog('open');      }); +    $('#chimere_itinerary_modify').click(function(){ +        $('#chimere_itinerary').hide(); +        $('#chimere_itinerary_form').show(); +    }); +    $('#chimere_itinerary_new').click(function(){ +        $('#map').chimere('routingClear'); +    });  });  </script>  {% endif%} diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index 51e64bf..946e769 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -118,7 +118,8 @@ def map_menu(context):  @register.inclusion_tag('chimere/blocks/routing.html', takes_context=True)  def routing(context): -    context_data =  {'routing':settings.CHIMERE_ENABLE_ROUTING} +    context_data =  {'routing':settings.CHIMERE_ENABLE_ROUTING, +                     'itinerary_form':context['itinerary_form']}      return context_data  @register.inclusion_tag('chimere/blocks/map_params.html', takes_context=True) diff --git a/chimere/urls.py b/chimere/urls.py index aec82fb..81263a0 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -54,9 +54,11 @@ if settings.CHIMERE_FEEDS:  if settings.CHIMERE_ENABLE_ROUTING:      urlpatterns += patterns('chimere.views',          url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?route/'\ +            r'(?P<transport>(%s))/'              r'(?P<lon1>[-]?[0-9]+[.]?[0-9]*)_(?P<lat1>[-]?[0-9]+[.]?[0-9]*)_'\              r'(?P<lonlat_steps>([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ -            r'(?P<lon2>[-]?[0-9]+[.]?[0-9]*)_(?P<lat2>[-]?[0-9]+[.]?[0-9]*)$', +            r'(?P<lon2>[-]?[0-9]+[.]?[0-9]*)_(?P<lat2>[-]?[0-9]+[.]?[0-9]*)$' % +           ('|'.join([key for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])),                  'route', name="route"),      ) diff --git a/chimere/views.py b/chimere/views.py index df403e0..dd3f89a 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -48,7 +48,7 @@ from chimere.widgets import getMapJS, PointChooserWidget, \                              RouteChooserWidget, AreaWidget  from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \       FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\ -     notifyStaff, AreaForm +     notifyStaff, AreaForm, RoutingForm  from chimere.route import router @@ -122,6 +122,8 @@ def index(request, area_name=None, default_area=None, simple=False):      if request.GET and 'lat' in request.GET \        and 'lon' in request.GET:          zoomout = None +    if settings.CHIMERE_ENABLE_ROUTING: +        response_dct['itinerary_form'] = RoutingForm()      response_dct.update({          'actions':actions, 'action_selected':('view',),           'error_message':'', diff --git a/chimere/widgets.py b/chimere/widgets.py index 8e2b8ad..b520fcd 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -26,6 +26,9 @@ from django.core.exceptions import ObjectDoesNotExist  from django.conf import settings  from django.contrib.gis.db import models  from django.contrib.gis.geos import fromstr +from django.utils.html import conditional_escape +from django.forms.widgets import RadioInput, RadioFieldRenderer +from django.utils.encoding import force_unicode  from django.utils.safestring import mark_safe  from django.utils.translation import ugettext as _ @@ -100,6 +103,41 @@ class ChosenSelectWidget(forms.Select):          u"</script>\n" % kwargs['attrs']['id']          return mark_safe(rendered) +""" +JQuery UI button select widget. +""" +class ButtonRadioInput(RadioInput): +    def render(self, name=None, value=None, attrs=None, choices=()): +        name = name or self.name +        value = value or self.value +        attrs = attrs or self.attrs +        if 'id' in self.attrs: +            label_for = ' for="%s_%s"' % (self.attrs['id'], self.index) +        else: +            label_for = '' +        choice_label = conditional_escape(force_unicode(self.choice_label)) +        return mark_safe(u'%s <label%s>%s</label>' % (self.tag(), label_for, +                                                      choice_label)) +class ButtonRadioFieldRenderer(RadioFieldRenderer): +    def __iter__(self): +        for i, choice in enumerate(self.choices): +            yield ButtonRadioInput(self.name, self.value, self.attrs.copy(), +                                   choice, i) +    def render(self): +        return mark_safe(u'\n'.join([force_unicode(w) for w in self])) +class ButtonSelectWidget(forms.RadioSelect): +    def __init__(self, *args, **kwargs): +        self.renderer = ButtonRadioFieldRenderer +        super(ButtonSelectWidget, self).__init__(*args, **kwargs) + +    def render(self, *args, **kwargs): +        rendered = "<div id='%s'>\n" % kwargs['attrs']['id'] +        rendered += super(ButtonSelectWidget, self).render(*args, **kwargs) +        rendered += u"\n<script type='text/javascript'>\n"\ +        u"  $('#%s').buttonset();\n"\ +        u"</script>\n</div>\n" % kwargs['attrs']['id'] +        return mark_safe(rendered) +  class TextareaWidget(forms.Textarea):      """      Manage the edition of a text using TinyMCE @@ -121,6 +159,21 @@ class DatePickerWidget(forms.TextInput):          u"</script>\n" % kwargs['attrs']['id']          return mark_safe(rendered) +class NominatimWidget(forms.TextInput): +    class Media: +        js = ["%schimere/js/nominatim-widget.js" % settings.STATIC_URL] +    def render(self, name, value, attrs=None, area_name=''): +        tpl = u""" +<input type='hidden' name='nominatim_%(id)s_lat' id='nominatim_%(id)s_lat'/> +<input type='hidden' name='nominatim_%(id)s_lon' id='nominatim_%(id)s_lon'/> +<input type='text' class='nominatim-widget' name='nominatim_%(id)s' id='nominatim_%(id)s'/> +<label class='nominatim-label' id='nominatim_%(id)s_label'> </label> +<script type='text/javascript'> +var nominatim_url = "%(nominatim_url)s"; +</script> +""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL} +        return mark_safe(tpl) +  class PointChooserWidget(forms.TextInput):      """      Manage the edition of point on a map diff --git a/example_project/settings.py b/example_project/settings.py index 5684386..750d798 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -5,6 +5,7 @@  # overload all theses settings in your local_settings.py file  import os +_ = lambda s: s  DEBUG = False  TEMPLATE_DEBUG = DEBUG @@ -78,6 +79,17 @@ CHIMERE_SHAPEFILE_ENCODING = 'ISO-8859-1'  # enable routing in Chimère  CHIMERE_ENABLE_ROUTING = False +CHIMERE_ROUTING_TRANSPORT = (('foot', _(u"Foot")), +                             ('bicycle', _(u"Bicycle")), +                             ('motorcar', _(u"Motorcar")), +                            ) + +CHIMERE_ROUTING_SPEEDS = {'foot':((3, _(u"You are walking slowly")), +                                  (6, _(u"You are walking pretty quickly")),), +                          'bicycle':((16, _(u"You are riding pretty slowly")), +                                     (22, _(u"You are riding pretty quickly")),) +                         } +  # available routing engine: 'routino'  CHIMERE_ROUTING_ENGINE = {      'ENGINE': 'routino', @@ -85,6 +97,8 @@ CHIMERE_ROUTING_ENGINE = {      'DB_PATH': '/var/local/routino/',  } +NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search' +  ADMINS = (      # ('Your Name', 'your_email@domain.com'),  )  | 
