add admin UI for loading tracks
[lantea.git] / js / map.js
index 242b2726f110a9f4633162f256941ee112a9c64d..b4fae0f7a8558a7f3ecb7f68e43d89636362678e 100644 (file)
--- a/js/map.js
+++ b/js/map.js
@@ -91,6 +91,7 @@ var gDragTouchID, gPinchStartWidth;
 var gGeoWatchID, gGPSWakeLock;
 var gTrack = [];
 var gLastTrackPoint, gLastDrawnPoint;
+var gDrawing = false;
 var gCenterPosition = true;
 
 var gCurPosMapCache;
@@ -706,6 +707,8 @@ function decodeIndex(encodedIdx) {
 }
 
 function drawTrack() {
+  if (gDrawing) { return; }
+  gDrawing = true;
   if (gTrackContext && (document.hidden != true)) { // Only draw if we're actually visible.
     gLastDrawnPoint = null;
     gCurPosMapCache = undefined;
@@ -717,18 +720,20 @@ function drawTrack() {
       }
     }
   }
+  gDrawing = false;
 }
 
-function drawTrackPoint(aLatitude, aLongitude, lastPoint) {
-  var trackpoint = gps2xy(aLatitude, aLongitude);
+function drawTrackPoint(aLatitude, aLongitude, aLastPoint) {
+  var trackpoint = {"worldpos": gps2xy(aLatitude, aLongitude)};
+  var update_drawnpoint = true;
   // lastPoint is for optimizing (not actually executing the draw until the last)
-  trackpoint.segmentEnd = (lastPoint === true);
-  trackpoint.optimized = (lastPoint === false);
-  trackpoint.mappos = {x: Math.round((trackpoint.x - gMap.pos.x) / gMap.zoomFactor + gMap.width / 2),
-                       y: Math.round((trackpoint.y - gMap.pos.y) / gMap.zoomFactor + gMap.height / 2)};
+  trackpoint.segmentEnd = (aLastPoint === true);
+  trackpoint.optimized = (aLastPoint === false);
+  trackpoint.mappos = {x: Math.round((trackpoint.worldpos.x - gMap.pos.x) / gMap.zoomFactor + gMap.width / 2),
+                       y: Math.round((trackpoint.worldpos.y - gMap.pos.y) / gMap.zoomFactor + gMap.height / 2)};
+  trackpoint.skip_drawing = false;
   if (gLastDrawnPoint) {
     // Lines completely outside the current display should not be drawn.
-    trackpoint.skip_drawing = false;
     if ((trackpoint.mappos.x < 0 && gLastDrawnPoint.mappos.x < 0) ||
         (trackpoint.mappos.x > gMap.width && gLastDrawnPoint.mappos.x > gMap.width) ||
         (trackpoint.mappos.y < 0 && gLastDrawnPoint.mappos.y < 0) ||
@@ -768,10 +773,11 @@ function drawTrackPoint(aLatitude, aLongitude, lastPoint) {
                         gTrackContext.lineWidth, 0, Math.PI * 2, false);
       gTrackContext.fill();
     }
-    else if (gLastDrawnPoint &&
-             Math.abs(gLastDrawnPoint.mappos.x - trackpoint.mappos.x) <= 1 &&
-             Math.abs(gLastDrawnPoint.mappos.y - trackpoint.mappos.y) <= 1) {
+    else if (!trackpoint.segmentEnd && gLastDrawnPoint &&
+             (Math.abs(gLastDrawnPoint.mappos.x - trackpoint.mappos.x) <= 1) &&
+             (Math.abs(gLastDrawnPoint.mappos.y - trackpoint.mappos.y) <= 1)) {
       // We would draw the same or almost the same point, don't do any actual drawing.
+      update_drawnpoint = false;
     }
     else {
       // Continue drawing segment, close if needed.
@@ -780,7 +786,9 @@ function drawTrackPoint(aLatitude, aLongitude, lastPoint) {
         gTrackContext.stroke();
     }
   }
-  gLastDrawnPoint = trackpoint;
+  if (update_drawnpoint) {
+    gLastDrawnPoint = trackpoint;
+  }
 }
 
 function drawCurrentLocation(trackPoint) {
@@ -1230,6 +1238,53 @@ function clearTrack() {
   drawTrack();
 }
 
+function loadTrackFromBackend(aTrackId, aFeedbackElement, aSuccessCallback) {
+  if (aFeedbackElement) {
+    aFeedbackElement.textContent = "Loading...";
+    // If someone loads without pointing to UI (e.g. for debugging), we just overwrite whatever's loaded.
+    if (calcTrackLength() > 1) {
+      aFeedbackElement.textContent = "Track >1km loaded, please save/clear.";
+      aFeedbackElement.classList.add("error");
+      return;
+    }
+  }
+  fetchBackend("track_json?id=" + encodeURIComponent(aTrackId), "GET", null,
+    function(aResult, aStatusCode) {
+      if (aStatusCode >= 400) {
+        console.log("loading track failed: " + aStatusCode + ", result: " + aResult.message);
+        if (aFeedbackElement) {
+          aFeedbackElement.textContent = "Error: " + aResult;
+          aFeedbackElement.classList.add("error");
+        }
+      }
+      else if (aResult) {
+        loadTrack(aResult);
+        if (aSuccessCallback) {
+          aSuccessCallback();
+        }
+      }
+      else { // If no result is returned, we assume a general error.
+        console.log("Error getting track with ID " + aTrackId + " from backend.");
+        if (aFeedbackElement) {
+          aFeedbackElement.textContent = "Error fetching track from backend.";
+          aFeedbackElement.classList.add("error");
+        }
+      }
+    }
+  );
+}
+
+function loadTrack(aTrack) {
+  console.log("Loading track with " + aTrack.length + " points.");
+  gTrack = aTrack;
+  gTrackStore.clear(function(aSuccess, aEvent) {
+    for (var i = 0; i < gTrack.length; i++) {
+      try { gTrackStore.push(gTrack[i]); } catch(e) {}
+    }
+  });
+  drawTrack(); // Draws from gTrack, so not problem that gTrackStore is filled async.
+}
+
 var gTileService = {
   objStore: "tilecache",