add undo feature
authorGuillaume Cottenceau <gcottenc@gmail.com>
Fri, 31 Dec 2010 17:51:35 +0000 (18:51 +0100)
committerGuillaume Cottenceau <gcottenc@gmail.com>
Fri, 31 Dec 2010 17:51:35 +0000 (18:51 +0100)
images/undo.png [new file with mode: 0644]
index.php
messages.en
messages.fr

diff --git a/images/undo.png b/images/undo.png
new file mode 100644 (file)
index 0000000..6972c5e
Binary files /dev/null and b/images/undo.png differ
index e12fc5e426fcc0b4aed1fe864e85588430e8042e..06254719f9faf2911851136781a44d732985e085 100644 (file)
--- a/index.php
+++ b/index.php
@@ -165,20 +165,26 @@ function parse_answer($answer) {
 
       var mylat, mylng;
       var map;
+      var me;
       var places = new Array();
       var geocoder = new google.maps.Geocoder();
       var directions_service = new google.maps.DirectionsService();
       var info_window = null;
       var bounds;
       var travelmode = google.maps.DirectionsTravelMode.DRIVING;
+      var undo_history = new Array();
 
-      function reload(new_places) {
+      function removePlaces() {
           for (var i = 0; i < places.length; i++) {
               places[i].marker.setMap(null);
               places[i].directions_display.setMap(null);
           }
           places = new Array();
           document.getElementById("resultslist").innerHTML = '';
+      }
+
+      function reload(new_places) {
+          removePlaces();
           for (var i = 0; i < new_places.length; i++) {
               createPlace(new_places[i].latlng, new_places[i].name);
           }
@@ -194,6 +200,7 @@ function parse_answer($answer) {
       function travelmodeChanged() {
           setTravelmode(document.getElementById("travelmode").value);
           reload(places);
+          historyPush();
       }
 
       function showDirectionCapture(i) {
@@ -210,11 +217,16 @@ function parse_answer($answer) {
       }
       
       function fitmap() {
-          if (document.getElementById("fitmap").checked) {
+          if (document.getElementById("fitmap").checked && bounds) {
               map.fitBounds(bounds);
           }
       }
 
+      function fitmapChanged() {
+          fitmap();
+          historyPush();
+      }
+
       function showDirections() {
           if (places.length > 0) {
               bounds = new google.maps.LatLngBounds();
@@ -248,6 +260,7 @@ function parse_answer($answer) {
               }
           }
           reload(new_places);
+          historyPush();
       }
 
       function createPlace(latlng, name) {
@@ -284,6 +297,7 @@ function parse_answer($answer) {
                                    createPlace(results[0].geometry.location, address);
                                    document.getElementById('address').value = '';
                                    document.getElementById('address').focus();
+                                   historyPush();
                                } else {
                                    document.getElementById('submitshortresult').innerHTML = "<?php echo t('address.not.found') ?>";
                                    document.getElementById('submitshortresult').style.display = '';
@@ -292,73 +306,129 @@ function parse_answer($answer) {
                            });
       }
 
-      function save() {
-          var link = "#me=" + mylat + ";" + mylng;
+      function getstate() {
+          var link = "me=" + mylat + ";" + mylng;
           link += "&tm=" + document.getElementById("travelmode").value;
           link += "&fb=" + document.getElementById("fitmap").checked;
           link += "&c=" + map.getCenter().lat() + ";" + map.getCenter().lng() + ";" + map.getZoom()
           for (var i = 0; i < places.length; i++) {
               link += "&p=" + places[i].latlng.lat() + ";" + places[i].latlng.lng() + ";" + encodeURI(places[i].name);
           }
+          return link;
+      }
+
+      function save() {
           document.getElementById('savediv').style.display = '';
           var save = document.getElementById('save');
-          save.value = 'http://routes-compare.zarb.org/?saved' + link;
+          save.value = 'http://routes-compare.zarb.org/?saved#' + getstate();
           save.focus();
           save.select();
       }
 
       function startUp(setcenter) {
-          var me = new google.maps.Marker({position: new google.maps.LatLng(mylat, mylng),
-                                           title: 'Me',
-                                           draggable: true,
-                                           icon: getIcon('icon31'),
-                                           shadow: getShadow('icon31')});
+          if (me) {
+              me.setMap(null);
+          }
+          me = new google.maps.Marker({position: new google.maps.LatLng(mylat, mylng),
+                                       title: 'Me',
+                                       draggable: true,
+                                       icon: getIcon('icon31'),
+                                       shadow: getShadow('icon31')});
           me.setMap(map);
           google.maps.event.addListener(me, "dragend", function(mouseEvent) {
                   mylat = mouseEvent.latLng.lat();
                   mylng = mouseEvent.latLng.lng();
                   reload(places);
+                  historyPush();
               });
           if (setcenter) {
               map.setCenter(new google.maps.LatLng(mylat, mylng));
           }
           return me;
       }
-                         
+
+      function setFromState(state) {
+          var params = state.split("&");
+          for (i = 0; i < params.length; i++) {
+              var keyvalue = params[i].split("=");
+              var values = keyvalue[1].split(";");
+              if (keyvalue[0] == 'me') {
+                  mylat = values[0];
+                  mylng = values[1];
+              } else if (keyvalue[0] == 'tm') {
+                  setTravelmode(values[0]);
+                  var tm = document.getElementById("travelmode");
+                  for (var j = 0; j < tm.length; j++) {
+                      if (tm.options[j].value == values[0]) {
+                        tm.options[j].selected = true;
+                      }
+                  }
+              } else if (keyvalue[0] == 'fb') {
+                  document.getElementById("fitmap").checked = values[0] == 'true';
+              } else if (keyvalue[0] == 'c') {
+                  map.setCenter(new google.maps.LatLng(values[0], values[1]));
+                  map.setZoom(parseInt(values[2]));
+              } else if (keyvalue[0] == 'p') {
+                  createPlace(new google.maps.LatLng(values[0], values[1]), decodeURI(values[2]));
+              }
+          }
+          startUp(false);
+      }
+
+      function historyPush() {
+          var state = getstate();
+          if (undo_history.length == 0 || undo_history[undo_history.length-1] != state) {
+              undo_history.push(getstate());
+              if (undo_history.length == 2) {
+                  document.getElementById('undo').style.opacity = 1.0;
+                  document.getElementById('undo').style.filter = '';
+              }
+              //              debug('after push: ' + undo_history);
+          } else {
+            //            debug('not pushing ' + state);
+          }
+      }
+      function historyPop() {
+          // when loading a map-related state, a new event is fired and a history element is thus added;
+          // to compensate for that effect, two pops are performed here, and an additional push below to
+          // have the same effect for non map-related states
+          undo_history.pop();
+          var state = undo_history.pop();
+          //          debug('state to load: ' + state);
+          if (state) {
+              removePlaces();
+              setFromState(state);
+              historyPush();  
+              if (undo_history.length == 1) {
+                  document.getElementById('undo').style.opacity = 0.4;
+                  document.getElementById('undo').style.filter = 'alpha(opacity=40)';
+              }
+          }
+      }
+
       function initialize() {
           map = new google.maps.Map(document.getElementById("mapbox"),
                                     { mapTypeId: google.maps.MapTypeId.ROADMAP,
                                       zoom: 2 });
+          var currently_dragging = false;
+          google.maps.event.addListener(map, "bounds_changed", function() {
+              if (!currently_dragging) {
+                  historyPush();
+              }
+          });
+          google.maps.event.addListener(map, "dragstart", function() {
+              currently_dragging = true;
+          });
+          google.maps.event.addListener(map, "dragend", function() {
+              historyPush();
+              currently_dragging = false;
+          });
 
           mylat = 0;
           mylng = 0;
           var all_params = location.href.split("#")
           if (all_params.length > 1 && all_params[1].length > 0) {
-              var params = all_params[1].split("&");
-              for (i = 0; i < params.length; i++) {
-                  var keyvalue = params[i].split("=");
-                  var values = keyvalue[1].split(";");
-                  if (keyvalue[0] == 'me') {
-                      mylat = values[0];
-                      mylng = values[1];
-                  } else if (keyvalue[0] == 'tm') {
-                      setTravelmode(values[0]);
-                      var tm = document.getElementById("travelmode");
-                      for (var j = 0; j < tm.length; j++) {
-                          if (tm.options[j].value == values[0]) {
-                            tm.options[j].selected = true;
-                          }
-                      }
-                  } else if (keyvalue[0] == 'fb' && values[0] == 'false') {
-                      document.getElementById("fitmap").checked = false;
-                  } else if (keyvalue[0] == 'c') {
-                      map.setCenter(new google.maps.LatLng(values[0], values[1]));
-                      map.setZoom(parseInt(values[2]));
-                  } else if (keyvalue[0] == 'p') {
-                      createPlace(new google.maps.LatLng(values[0], values[1]), decodeURI(values[2]));
-                  }
-              }
-              startUp(false);
+              setFromState(all_params[1]);
           } else {
               <?php
                   if ($latitude) {
@@ -374,7 +444,7 @@ function parse_answer($answer) {
                   }
                ?>
               map.setZoom(<?php echo $zoom ?>);
-              me = startUp(true);
+              startUp(true);
               info_window = new google.maps.InfoWindow({ content: baseinfomessage + '<?php echo t('home.icon.move.possible') ?>' });
               info_window.open(map, me);
               if (!document.cookie || document.cookie.indexOf("not-a-newbie") == -1) {
@@ -405,13 +475,18 @@ function parse_answer($answer) {
 <!-- doesn't work  <option value="google.maps.DirectionsTravelMode.BICYCLING">Bicycling</option> -->
         </select>
         - 
-        <input type="checkbox" id="fitmap" checked="true" onchange="fitmap()"><?php echo t('fit.to.elements') ?>
+        <input type="checkbox" id="fitmap" checked="true" onchange="fitmapChanged()"><?php echo t('fit.to.elements') ?>
         - 
         <a href="#" onclick="save()">
           <?php echo t('save.this.page') ?>
           <img src="images/save.png" class="iconwithtext"/>
         </a>
         -
+        <a href="#" onclick="historyPop()" id="undo" style="opacity:0.4;filter:alpha(opacity=40)">
+          <?php echo t('undo') ?>
+          <img src="images/undo.png" class="iconwithtext"/>
+        </a>
+        -
         <?php if ($language != 'en') { ?>
          <a href="?language=en"><img src="images/en.png" class="iconwithtext" style="opacity:0.4;filter:alpha(opacity=40)"/></a>
         <?php } else { ?>
index 19e6ac2bf50c23fe64f1bcd5663417c2bd51953f..d3acc8c965f287abfe16fe165c4ed2dfdd8f058c 100644 (file)
@@ -6,6 +6,7 @@ travelmode.driving=driving
 travelmode.walking=walking
 fit.to.elements=fit to elements
 save.this.page=save this page
+undo=undo
 
 save.page.expl=The following link will directly present the current data:
 Okay=Okay
index 6fbdf14ee24c7e066b5be33e407d1c9395bead42..04a8c086aeaaab0eaf06f5c8293058e9d37bbe4a 100644 (file)
@@ -6,6 +6,7 @@ travelmode.driving=voiture
 travelmode.walking=marche
 fit.to.elements=ajuster
 save.this.page=sauver cette page
+undo=défaire
 
 save.page.expl=Le lien suivant présentera directement les données actuelles :
 Okay=D&apos;accord