zero change to appcache to get installations to update
[lantea.git] / js / ui.js
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 // Get the best-available indexedDB object.
6 var iDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
7 var mainDB;
8
9 var gUIHideCountdown = 0;
10
11 window.onload = function() {
12   var mSel = document.getElementById("mapSelector");
13   for (var mapStyle in gMapStyles) {
14     var opt = document.createElement("option");
15     opt.value = mapStyle;
16     opt.text = gMapStyles[mapStyle].name;
17     mSel.add(opt, null);
18   }
19
20   var areas = document.getElementsByClassName('overlayArea');
21   for (var i = 0; i <= areas.length - 1; i++) {
22     areas[i].addEventListener("mouseup", uiEvHandler, false);
23     areas[i].addEventListener("mousemove", uiEvHandler, false);
24     areas[i].addEventListener("mousedown", uiEvHandler, false);
25     areas[i].addEventListener("mouseout", uiEvHandler, false);
26
27     areas[i].addEventListener("touchstart", uiEvHandler, false);
28     areas[i].addEventListener("touchmove", uiEvHandler, false);
29     areas[i].addEventListener("touchend", uiEvHandler, false);
30     areas[i].addEventListener("touchcancel", uiEvHandler, false);
31     areas[i].addEventListener("touchleave", uiEvHandler, false);
32   }
33
34
35   initDB();
36   initMap();
37   resizeAndDraw();
38 }
39
40 window.onresize = function() {
41   resizeAndDraw();
42 }
43
44 function initDB() {
45   // Open DB.
46   var request = iDB.open("MainDB", 1);
47   request.onerror = function(event) {
48     // Errors can be handled here. Error codes explain in:
49     // https://developer.mozilla.org/en/IndexedDB/IDBDatabaseException#Constants
50     //document.getElementById("debug").textContent =
51     //  "error opening mainDB: " + event.target.errorCode;
52   };
53   request.onsuccess = function(event) {
54     //document.getElementById("debug").textContent = "mainDB opened.";
55     mainDB = request.result;
56   };
57   request.onupgradeneeded = function(event) {
58     mainDB = request.result;
59     //document.getElementById("debug").textContent = "mainDB upgraded.";
60     // Create a "prefs" objectStore.
61     var prefsStore = mainDB.createObjectStore("prefs");
62     // Create a "track" objectStore.
63     var trackStore = mainDB.createObjectStore("track", {autoIncrement: true});
64     mainDB.onversionchange = function(event) {
65       mainDB.close();
66       mainDB = undefined;
67       initDB();
68     };
69   };
70 }
71
72 function showUI() {
73   if (gUIHideCountdown <= 0) {
74     var areas = document.getElementsByClassName('overlayArea');
75     for (var i = 0; i <= areas.length - 1; i++) {
76       areas[i].classList.remove("hidden");
77     }
78     setTimeout(maybeHideUI, 1000);
79   }
80   gUIHideCountdown = 5;
81 }
82
83 function maybeHideUI() {
84   gUIHideCountdown--;
85   if (gUIHideCountdown <= 0) {
86     var areas = document.getElementsByClassName('overlayArea');
87     for (var i = 0; i <= areas.length - 1; i++) {
88       areas[i].classList.add("hidden");
89     }
90   }
91   else {
92     setTimeout(maybeHideUI, 1000);
93   }
94 }
95
96 function toggleTrackArea() {
97   var fs = document.getElementById("trackArea");
98   if (fs.style.display != "block") {
99     fs.style.display = "block";
100     showUI();
101   }
102   else {
103     fs.style.display = "none";
104   }
105 }
106
107 function toggleSettings() {
108   var fs = document.getElementById("settingsArea");
109   if (fs.style.display != "block") {
110     fs.style.display = "block";
111     showUI();
112   }
113   else {
114     fs.style.display = "none";
115   }
116 }
117
118 var uiEvHandler = {
119   handleEvent: function(aEvent) {
120     var touchEvent = aEvent.type.indexOf('touch') != -1;
121
122     switch (aEvent.type) {
123       case "mousedown":
124       case "touchstart":
125       case "mousemove":
126       case "touchmove":
127       case "mouseup":
128       case "touchend":
129         showUI();
130         break;
131     }
132   }
133 };
134
135 function makeISOString(aTimestamp) {
136   // ISO time format is YYYY-MM-DDTHH:mm:ssZ
137   var tsDate = new Date(aTimestamp);
138   return tsDate.getUTCFullYear() + "-" +
139          (tsDate.getUTCMonth() < 10 ? "0" : "") + tsDate.getUTCMonth() + "-" +
140          (tsDate.getUTCDate() < 10 ? "0" : "") + tsDate.getUTCDate() + "T" +
141          (tsDate.getUTCHours() < 10 ? "0" : "") + tsDate.getUTCHours() + ":" +
142          (tsDate.getUTCMinutes() < 10 ? "0" : "") + tsDate.getUTCMinutes() + ":" +
143          (tsDate.getUTCSeconds() < 10 ? "0" : "") + tsDate.getUTCSeconds() + "Z";
144 }
145
146 function saveTrack() {
147   if (gTrack.length) {
148     var out = '<?xml version="1.0" encoding="UTF-8" ?>' + "\n\n";
149     out += '<gpx version="1.0" creator="Lantea" xmlns="http://www.topografix.com/GPX/1/0">' + "\n";
150     out += '  <trk>' + "\n";
151     out += '    <trkseg>' + "\n";
152     for (var i = 0; i < gTrack.length; i++) {
153       if (gTrack[i].beginSegment && i > 0) {
154         out += '    </trkseg>' + "\n";
155         out += '    <trkseg>' + "\n";
156       }
157       out += '      <trkpt lat="' + gTrack[i].coords.latitude + '" lon="' +
158                                     gTrack[i].coords.longitude + '">' + "\n";
159       if (gTrack[i].coords.altitude) {
160         out += '        <ele>' + gTrack[i].coords.altitude + '</ele>' + "\n";
161       }
162       out += '        <time>' + makeISOString(gTrack[i].time) + '</time>' + "\n";
163       out += '      </trkpt>' + "\n";
164     }
165     out += '    </trkseg>' + "\n";
166     out += '  </trk>' + "\n";
167     out += '</gpx>' + "\n";
168     var outDataURI = "data:application/gpx+xml," + encodeURIComponent(out);
169     window.open(outDataURI, 'GPX Track');
170   }
171 }
172
173 function saveTrackDump() {
174   if (gTrack.length) {
175     var out = JSON.stringify(gTrack);
176     var outDataURI = "data:application/json," + encodeURIComponent(out);
177     window.open(outDataURI, 'JSON dump');
178   }
179 }
180
181 var gPrefs = {
182   objStore: "prefs",
183
184   get: function(aKey, aCallback) {
185     if (!mainDB)
186       return;
187     var transaction = mainDB.transaction([this.objStore]);
188     var request = transaction.objectStore(this.objStore).get(aKey);
189     request.onsuccess = function(event) {
190       aCallback(request.result, event);
191     };
192     request.onerror = function(event) {
193       // Errors can be handled here.
194       aCallback(undefined, event);
195     };
196   },
197
198   set: function(aKey, aValue, aCallback) {
199     if (!mainDB)
200       return;
201     var success = false;
202     var transaction = mainDB.transaction([this.objStore], "readwrite");
203     var objStore = transaction.objectStore(this.objStore);
204     var request = objStore.put(aValue, aKey);
205     request.onsuccess = function(event) {
206       success = true;
207       if (aCallback)
208         aCallback(success, event);
209     };
210     request.onerror = function(event) {
211       // Errors can be handled here.
212       if (aCallback)
213         aCallback(success, event);
214     };
215   },
216
217   unset: function(aKey, aCallback) {
218     if (!mainDB)
219       return;
220     var success = false;
221     var transaction = mainDB.transaction([this.objStore], "readwrite");
222     var request = transaction.objectStore(this.objStore).delete(aKey);
223     request.onsuccess = function(event) {
224       success = true;
225       if (aCallback)
226         aCallback(success, event);
227     };
228     request.onerror = function(event) {
229       // Errors can be handled here.
230       if (aCallback)
231         aCallback(success, event);
232     }
233   }
234 };
235
236 var gTrackStore = {
237   objStore: "track",
238
239   getList: function(aCallback) {
240     if (!mainDB)
241       return;
242     var transaction = mainDB.transaction([this.objStore]);
243     var objStore = transaction.objectStore(this.objStore);
244     if (objStore.getAll) { // currently Mozilla-specific
245       objStore.getAll().onsuccess = function(event) {
246         aCallback(event.target.result);
247       };
248     }
249     else { // Use cursor (standard method).
250       var tPoints = [];
251       objStore.openCursor().onsuccess = function(event) {
252         var cursor = event.target.result;
253         if (cursor) {
254           tPoints.push(cursor.value);
255           cursor.continue();
256         }
257         else {
258           aCallback(tPoints);
259         }
260       };
261     }
262   },
263
264   push: function(aValue, aCallback) {
265     if (!mainDB)
266       return;
267     var transaction = mainDB.transaction([this.objStore], "readwrite");
268     var objStore = transaction.objectStore(this.objStore);
269     var request = objStore.add(aValue);
270     request.onsuccess = function(event) {
271       if (aCallback)
272         aCallback(request.result, event);
273     };
274     request.onerror = function(event) {
275       // Errors can be handled here.
276       if (aCallback)
277         aCallback(false, event);
278     };
279   },
280
281   clear: function(aCallback) {
282     if (!mainDB)
283       return;
284     var success = false;
285     var transaction = mainDB.transaction([this.objStore], "readwrite");
286     var request = transaction.objectStore(this.objStore).clear();
287     request.onsuccess = function(event) {
288       success = true;
289       if (aCallback)
290         aCallback(success, event);
291     };
292     request.onerror = function(event) {
293       // Errors can be handled here.
294       if (aCallback)
295         aCallback(success, event);
296     }
297   }
298 };