summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-08-17 13:13:15 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-08-17 13:13:15 +0200
commit502cc25a0dc57a61289c245d653f96e2b3009efa (patch)
tree83c15cf049d58c222e30d00d1991d8b6c6249f02
parente0029f8e8d11736b41046f2a7390b6f5303fbb58 (diff)
downloadChimère-502cc25a0dc57a61289c245d653f96e2b3009efa.tar.bz2
Chimère-502cc25a0dc57a61289c245d653f96e2b3009efa.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.py18
-rw-r--r--chimere/locale/fr/LC_MESSAGES/django.po91
-rw-r--r--chimere/static/chimere/css/styles.css58
-rw-r--r--chimere/static/chimere/img/images_licences6
-rw-r--r--chimere/static/chimere/js/jquery.chimere.js155
-rw-r--r--chimere/static/chimere/js/nominatim-widget.js41
-rw-r--r--chimere/templates/chimere/blocks/routing.html37
-rw-r--r--chimere/templatetags/chimere_tags.py3
-rw-r--r--chimere/urls.py4
-rw-r--r--chimere/views.py4
-rw-r--r--chimere/widgets.py53
-rw-r--r--example_project/settings.py14
12 files changed, 394 insertions, 90 deletions
diff --git a/chimere/forms.py b/chimere/forms.py
index e3486c0..c036911 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
@@ -438,3 +438,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 8ba4b43..9335b42 100644
--- a/chimere/locale/fr/LC_MESSAGES/django.po
+++ b/chimere/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-15 20:29+0200\n"
+"POT-Creation-Date: 2012-08-17 13:12+0200\n"
"PO-Revision-Date: 2010-03-20 20:00+0100\n"
"Last-Translator: Étienne Loks <etienne.loks@peacefrogs.net>\n"
"MIME-Version: 1.0\n"
@@ -130,6 +130,18 @@ msgstr "Nom"
msgid "Area"
msgstr "Zone"
+#: 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"
@@ -611,19 +623,19 @@ msgstr ""
msgid "Bad param"
msgstr "Mauvais paramètre"
-#: views.py:226
+#: 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:305
+#: 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:427
+#: views.py:429
msgid "Comments/request on the map"
msgstr "Commentaires/requètes sur la carte"
-#: views.py:430
+#: 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."
@@ -632,48 +644,48 @@ msgstr ""
"laissé votre courriel vous serez peut-être contacté bientôt pour plus de "
"détails."
-#: views.py:434
+#: views.py:436
msgid "Temporary error. Renew your message later."
msgstr "Erreur temporaire. Réenvoyez votre message plus tard."
-#: views.py:565
+#: views.py:567
msgid "No category available in this area."
msgstr "Pas de catégorie disponible sur cette zone."
-#: views.py:694
+#: views.py:696
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&nbsp;: «&nbsp;Tracer&nbsp;»."
-#: 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."
@@ -681,7 +693,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\"."
@@ -689,17 +701,17 @@ msgstr ""
"En mode création vous pouvez annuler un tracé en appuyant sur le bouton "
"«&nbsp;Arrêter le tracé&nbsp;»."
-#: 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."
@@ -707,7 +719,7 @@ msgstr ""
"Pour supprimer un point, mettez le curseur de la souris sur celui-ci et "
"appuyez sur le touche «&nbsp;d&nbsp;» ou «&nbsp;Suppr&nbsp;»."
-#: 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"
@@ -716,33 +728,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..."
@@ -911,11 +923,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 "
@@ -979,3 +1007,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 c7a4c05..e551ac6 100644
--- a/chimere/static/chimere/css/styles.css
+++ b/chimere/static/chimere/css/styles.css
@@ -406,36 +406,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;
}
@@ -471,6 +504,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 664ef15..f46f3eb 100644
--- a/chimere/static/chimere/js/jquery.chimere.js
+++ b/chimere/static/chimere/js/jquery.chimere.js
@@ -156,6 +156,40 @@ See the file COPYING for details.
}
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);
@@ -211,37 +245,6 @@ See the file COPYING for details.
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
@@ -266,7 +269,7 @@ See the file COPYING for details.
* 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{
@@ -445,7 +448,6 @@ See the file COPYING for details.
if (settings.current_popup == feature.popup) {
feature.popup.hide();
if (!settings.simple){
- $('#panel').removeClass('panel-minified');
$('#detail').hide();
}
} else {
@@ -505,23 +507,51 @@ See the file COPYING for details.
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()));
@@ -533,20 +563,36 @@ See the file COPYING for details.
// 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;
@@ -566,6 +612,8 @@ See the file COPYING for details.
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(),
@@ -582,8 +630,13 @@ See the file COPYING for details.
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) {
@@ -630,7 +683,6 @@ See the file COPYING for details.
}
else {
if (!settings.simple) {
- $('#panel').addClass('panel-minified');
$('#detail').html(data).show();
}
else {
@@ -803,13 +855,16 @@ See the file COPYING for details.
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) {
@@ -934,8 +989,22 @@ See the file COPYING for details.
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 308fb14..bd1f441 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 da2bc54..f5617de 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'>&nbsp;</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 ead2c93..46b8e95 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
@@ -77,6 +78,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',
@@ -84,6 +96,8 @@ CHIMERE_ROUTING_ENGINE = {
'DB_PATH': '/var/local/routino/',
}
+NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search'
+
ADMINS = (
# ('Your Name', 'your_email@domain.com'),
)