--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/resources/scripts/tracker.js Mon Aug 22 13:59:49 2011 -0400
@@ -0,0 +1,383 @@
+
+function buildMessage(data, boundary) {
+ var CRLF = "\r\n";
+ var parts = [];
+ var iter = 0;
+
+ while (iter < data.length) {
+ var part = "";
+ var type = "TEXT";
+
+ part = 'Content-Disposition: form-data; ';
+ part += 'name="' + data[iter][0] + '"' + CRLF + CRLF;
+
+ part += data[iter][1] + CRLF;
+
+ parts.push(part);
+ iter++;
+ }
+
+ var request = "--" + boundary + CRLF;
+ request+= parts.join("--" + boundary + CRLF);
+ request+= "--" + boundary + "--" + CRLF;
+
+ return request;
+}
+
+function send(user, data) {
+ var boundary = "AJAX-----------------------" + Date.now();
+ var xhr = new XMLHttpRequest;
+
+ if (!("withCredentials" in xhr)) {
+ return false;
+ }
+
+ try {
+ xhr.open("POST", "http://teole.jfouffa.org/2011/07/html5track.php", true);
+ xhr.setRequestHeader('X-HTML5TRACK', 'true');
+ xhr.onreadystatechange = function() {
+ switch (xhr.readyState) {
+ case 4:
+ document.getElementById("log").textContent = "xhr done " + xhr.status + " " + xhr.statusText;
+ break;
+ case 0:
+ document.getElementById("log").textContent = "xhr unsent";
+ break;
+ case 1:
+ document.getElementById("log").textContent = "xhr opened";
+ break;
+ case 2:
+ document.getElementById("log").textContent = "xhr headers_received";
+ break;
+ case 3:
+ document.getElementById("log").textContent = "xhr loading";
+ break;
+ }
+ };
+ var contentType = "multipart/form-data; boundary=" + boundary;
+ xhr.setRequestHeader("Content-Type", contentType);
+
+ var data = buildMessage([ ["user", user], ["gps_coords", data] ], boundary);
+
+ xhr.sendAsBinary(data);
+
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
+
+var storage = (function() {
+ try {
+ return !!window.localStorage.getItem;
+ } catch (e) {
+ return false;
+ }
+})();
+
+
+
+var watchId = 0;
+var running = false;
+
+var duration = 0;
+var start_time = 0;
+var intervalId = 0;
+
+// wait for at least 5 consecutive GPS data before declaring the GPS ready
+var MAX_ERRORS = 2;
+var got_error = MAX_ERRORS;
+
+var discarded = 0;
+var locations = 0;
+
+var coordinates = [];
+
+var dst_unit = 1;
+
+function formatNumber(n) {
+ return (n < 10)? "0" + n : n;
+}
+
+function formatTime(time) {
+ t = parseInt(time);
+ hours = parseInt(t / 3600);
+ minutes = parseInt(t / 60);
+ seconds = t - ((hours * 3600) + (minutes * 60));
+ return ((hours > 0)? formatNumber(hours) + ":": "") + formatNumber(minutes) + ":" + formatNumber(seconds);
+}
+
+
+
+
+function pushCoordinates(position) {
+ coordinates[coordinates.length] =
+ [ position.timestamp, position.coords.longitude, position.coords.latitude, position.coords.altitude, position.coords.speed ];
+// [ position.timestamp, position.coords.longitude, position.coords.latitude, position.coords.altitude ];
+}
+
+function pause() {
+ coordinates[coordinates.length] = [ Date.now(), "pause", 0, 0, 0, 0 ];
+}
+
+function getLastCoordinates() {
+ return (coordinates.length > 0)? coordinates[coordinates.length - 1] : null;
+}
+
+function getCoordinates() {
+ if (coordinates.length > 0 && !running) {
+ var result = "";
+ var i = 0;
+ while (i < coordinates.length) {
+ var position = coordinates[i];
+ var j = 1;
+ result += position[0];
+ while (j < position.length) result += "," + position[j++];
+ result += " ";
+ i++;
+ }
+ return result;
+ }
+ return null;
+}
+
+function calculateDistance(lat1, lon1, lat2, lon2) {
+ var R = 6371; // km
+ var dLat = (lat2-lat1) * Math.PI / 180;
+ var dLon = (lon2-lon1) * Math.PI / 180;
+ var lat1 = lat1 * Math.PI / 180;
+ var lat2 = lat2 * Math.PI / 180;
+ var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
+ Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
+ var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+ var d = R * c;
+ return d;
+}
+
+function calculateDistanceCoordinates() {
+ var result = 0;
+ if (coordinates.length > 0) {
+ var i = 1;
+ while (i < coordinates.length) {
+ var position1 = coordinates[i-1];
+ var position2 = coordinates[i];
+ result += calculateDistance(position1[2], position1[1], position2[2], position2[1]);
+ i++;
+ }
+ }
+ return result;
+}
+
+function calculateDurationCoordinates() {
+ var result = 0;
+ if (coordinates.length > 0) {
+ var i = 1;
+ while (i < coordinates.length) {
+ var position1 = coordinates[i-1];
+ var position2 = coordinates[i];
+ result += (position2[0]- position1[0]);
+ i++;
+ }
+ }
+ return result;
+}
+
+function repaint() {
+ if (document.visibilityState == true && running) {
+ document.getElementById("locations").textContent = String(locations);
+ var d = calculateDistanceCoordinates() * dst_unit;
+ var t = duration + (Date.now() - start_time);
+ document.getElementById("distance").textContent = String(Math.round(d*100)/100);
+ if (t != 0 && d != 0) {
+ document.getElementById("speed").textContent = String(Math.round( (d / (t / 3600000)) * 100) / 100);
+ document.getElementById("pace").textContent = String(Math.round( ((t / 60000)/d) * 100) / 100);
+ }
+ if (coordinates.length > 0) {
+ document.getElementById("gps_text").style.display = "none";
+ document.getElementById("gps_data").style.display = "inline";
+ }
+ }
+}
+
+function logGPS(position, startMsg) {
+ document.getElementById("log").textContent =
+ startMsg + position.timestamp
+ + ": " + position.coords.latitude
+ + ", " + position.coords.longitude
+ + ", " + position.coords.altitude
+ + ", " + position.coords.accuracy
+ + ", " + position.coords.altitudeAccuracy
+ + ", " + position.coords.heading
+ + ", " + position.coords.speed;
+}
+
+function handleSuccess(position) {
+ if (running) {
+ logGPS(position, "GPS: ");
+
+ // discard positions that have no altitude since they're likely inacurate
+ if (position.coords.altitude != null) {
+ pushCoordinates(position);
+ locations++;
+ repaint();
+ } else {
+ document.getElementById("discarded").textContent = String(discarded++);
+ }
+ } else {
+
+
+ if (position.coords.altitude == null) {
+ got_error++;
+ if (got_error > MAX_ERRORS) got_error = MAX_ERRORS;
+ logGPS(position, "[ERROR] GPS: ");
+ } else {
+ got_error--;
+ logGPS(position, "GPS: ");
+ }
+ if (got_error <= 0) {
+ got_error = 0;
+ document.getElementById("gps_text").textContent = "ready";
+ document.getElementById("waves").style.display = "block";
+ } else {
+ document.getElementById("gps_text").textContent = "not ready";
+ document.getElementById("waves").style.display = "none";
+ }
+ }
+}
+
+function handleError(error) {
+ var code = "unknown";
+ switch(error.code) {
+ case error.TIMEOUT:
+ code = "timeout";
+ break;
+ case error.PERMISSION_DENIED:
+ code = "permission denied";
+ break;
+ case error.POSITION_UNAVAILABLE:
+ code = "position unavailable";
+ break;
+ }
+ if (running) {
+ document.getElementById("errors").textContent = String(++got_error);
+ document.getElementById("log").textContent = "[ERROR] GPS: " + code;
+ } else {
+ document.getElementById("gps_text").textContent = code;
+ // wait for 5 non-consecutive errors
+ got_error = MAX_ERRORS;
+ }
+}
+
+function timer() {
+ if (document.visibilityState == true) {
+ document.getElementById("realtime").textContent =
+ formatTime(Math.round((duration+(Date.now()-start_time))/1000));
+ }
+}
+
+function start() {
+ if (!running) {
+ running = true;
+ start_time = Date.now();
+ intervalId = setInterval(timer, 1000);
+ document.getElementById("stop").disabled = false;
+ document.getElementById("start").textContent = "Pause";
+ } else {
+ running = false;
+ clearInterval(intervalId);
+ duration += (Date.now() - start_time);
+ document.getElementById("start").textContent = "Restart";
+ pause();
+ document.getElementById("gps_text").style.display = "inline";
+ document.getElementById("gps_data").style.display = "none";
+ }
+}
+
+function stop() {
+ // navigator.geolocation.clearWatch(watchId);
+ running = false;
+ clearInterval(intervalId);
+ got_error = 0;
+ locations = 0;
+ discarded = 0;
+ duration = 0;
+ document.getElementById("start").textContent = "Start";
+ document.getElementById("stop").disabled = true;
+ document.getElementById("log").textContent = "";
+ var coords = getCoordinates();
+ if (coords != null && storage) {
+ try {
+ window.localStorage.setItem("track_gps_app", coords);
+ } catch (e) {
+ document.getDocumentById("log").textContent = "[ERROR] Can't store the value " + e.code;
+ }
+ }
+ if (coords != null) {
+ if (!send("teole",coords)) {
+ document.getElementById("gps_coords").value = coords;
+ document.getElementById("xhr_failed").style.display = "inline";
+ document.getElementById("xhr_failed").disabled = false;
+ }
+ }
+ coordinates = [];
+}
+
+function init() {
+ if (!!document.visibilityState)
+ document.addEventListener("visibilitychange", repaint, false);
+ else
+ document.visibilityState = true;
+
+ // @@ in the future, make sure this is empty
+ if (storage) {
+ window.localStorage.setItem("track_gps_app", "");
+
+ if (window.localStorage.getItem("track_gps_app_dst_unit") === "mile") {
+ dst_unit = 0.621371192;
+ }
+ setUnit();
+ } else {
+ document.getElementById("log").textContent = "[ERROR] no local storage";
+ }
+ if (!!navigator.geolocation) {
+ watchId = navigator.geolocation.watchPosition(handleSuccess, handleError, {enableHighAccuracy:true, maximumAge:0, timeout:1000});
+ } else {
+ document.getElementById("gps_text").textContent = "not supported";
+ document.getElementById("start").disabled = true;
+ }
+
+ var xhr = new XMLHttpRequest;
+ if (!!xhr && !("withCredentials" in xhr)) {
+ document.getElementById("xhr_failed").style.display = "inline";
+ document.getElementById("xhr_failed").disabled = true;
+ }
+}
+
+window.addEventListener("load", init, false);
+
+function km() {
+ if (storage) {
+ window.localStorage.setItem("track_gps_app_dst_unit", "km");
+ }
+ dst_unit = 1;
+ setUnit();
+ repaint();
+}
+
+function mile() {
+ if (storage) {
+ window.localStorage.setItem("track_gps_app_dst_unit", "mile");
+ }
+ dst_unit = 0.621371192;
+ setUnit();
+ repaint();
+}
+
+function setUnit() {
+ var text = (dst_unit == 0.621371192)? "mile" : "km";
+ var nodes = document.getElementsByClassName("dst_unit");
+ i = 0;
+ do {
+ nodes[i].textContent = text;
+ } while (++i < nodes.length);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/resources/styles/tracker.css Mon Aug 22 13:59:49 2011 -0400
@@ -0,0 +1,44 @@
+body { background-color: #6699ff; }
+section table { margin: auto; }
+section p { text-align: center;}
+.text { font-size: 150%; }
+button {
+ font-size: 175%;
+ padding-left: 1ex;
+ padding-right: 1ex;
+ margin: 0;
+}
+#log { font-size: 75%; }
+#errors { color: red }
+#discarded { color: #f88 }
+table { border-collapse: collapse; }
+th { text-align: left; border-right: 1px solid #ccc; padding-right: 0.5ex;}
+td:nth-child(2) { text-align: right; width: 8ex; padding-right: 0.5ex;}
+h1 { text-align: right; padding-right: 1ex; font-family: cursive; margin: 0;}
+#gps_data { display: none }
+
+nav #atab0 { color: #ccc; cursor: default; }
+#vtab0:target ~ #tab0 { display: block }
+#vtab0:target ~ #tab1 { display: none }
+#vtab0:target ~ nav #atab1 { color: #6699ff; cursor: pointer; }
+#vtab0:target ~ nav #atab0 { color: #ccc; cursor: default; }
+
+#tab1 { display: none; }
+#vtab1:target ~ #tab0 { display: none }
+#vtab1:target ~ #tab1 { display: block }
+#vtab1:target ~ nav #atab0 { color: #6699ff; cursor: pointer; }
+#vtab1:target ~ nav #atab1 { color: #ccc; cursor: default; }
+
+section.tab_anchor { display: none; }
+
+nav {
+ border-bottom: 1px solid white;
+ padding-bottom: 2px;
+ margin-bottom: 5px;
+}
+nav a {
+ border: 1px solid white;
+ background: white;
+ color: #6699ff;
+ padding: 2px;
+}
--- a/src/main/resources/templates/geolocation.ssp Mon Aug 22 11:49:39 2011 -0400
+++ b/src/main/resources/templates/geolocation.ssp Mon Aug 22 13:59:49 2011 -0400
@@ -7,440 +7,9 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel='icon' type='image/png' href='geolocation-icon.png'/>
<title>HTML5 Track</title>
- <script>
-<![CDATA[
-
-function buildMessage(data, boundary) {
- var CRLF = "\r\n";
- var parts = [];
- var iter = 0;
-
- while (iter < data.length) {
- var part = "";
- var type = "TEXT";
-
- part = 'Content-Disposition: form-data; ';
- part += 'name="' + data[iter][0] + '"' + CRLF + CRLF;
-
- part += data[iter][1] + CRLF;
-
- parts.push(part);
- iter++;
- }
-
- var request = "--" + boundary + CRLF;
- request+= parts.join("--" + boundary + CRLF);
- request+= "--" + boundary + "--" + CRLF;
-
- return request;
-}
-
-function send(user, data) {
- var boundary = "AJAX-----------------------" + Date.now();
- var xhr = new XMLHttpRequest;
-
- if (!("withCredentials" in xhr)) {
- return false;
- }
-
- try {
- xhr.open("POST", "http://teole.jfouffa.org/2011/07/html5track.php", true);
- xhr.setRequestHeader('X-HTML5TRACK', 'true');
- xhr.onreadystatechange = function() {
- switch (xhr.readyState) {
- case 4:
- document.getElementById("log").textContent = "xhr done " + xhr.status + " " + xhr.statusText;
- break;
- case 0:
- document.getElementById("log").textContent = "xhr unsent";
- break;
- case 1:
- document.getElementById("log").textContent = "xhr opened";
- break;
- case 2:
- document.getElementById("log").textContent = "xhr headers_received";
- break;
- case 3:
- document.getElementById("log").textContent = "xhr loading";
- break;
- }
- };
- var contentType = "multipart/form-data; boundary=" + boundary;
- xhr.setRequestHeader("Content-Type", contentType);
-
- var data = buildMessage([ ["user", user], ["gps_coords", data] ], boundary);
-
- xhr.sendAsBinary(data);
-
- } catch (e) {
- return false;
- }
- return true;
-}
-
-var storage = (function() {
- try {
- return !!window.localStorage.getItem;
- } catch (e) {
- return false;
- }
-})();
-
-
-
-var watchId = 0;
-var running = false;
-
-var duration = 0;
-var start_time = 0;
-var intervalId = 0;
-
-// wait for at least 5 consecutive GPS data before declaring the GPS ready
-var MAX_ERRORS = 2;
-var got_error = MAX_ERRORS;
-
-var discarded = 0;
-var locations = 0;
-
-var coordinates = [];
-
-var dst_unit = 1;
-
-function formatNumber(n) {
- return (n < 10)? "0" + n : n;
-}
-
-function formatTime(time) {
- t = parseInt(time);
- hours = parseInt(t / 3600);
- minutes = parseInt(t / 60);
- seconds = t - ((hours * 3600) + (minutes * 60));
- return ((hours > 0)? formatNumber(hours) + ":": "") + formatNumber(minutes) + ":" + formatNumber(seconds);
-}
-
-
-
-
-function pushCoordinates(position) {
- coordinates[coordinates.length] =
- [ position.timestamp, position.coords.longitude, position.coords.latitude, position.coords.altitude, position.coords.speed ];
-// [ position.timestamp, position.coords.longitude, position.coords.latitude, position.coords.altitude ];
-}
-
-function pause() {
- coordinates[coordinates.length] = [ Date.now(), "pause", 0, 0, 0, 0 ];
-}
-
-function getLastCoordinates() {
- return (coordinates.length > 0)? coordinates[coordinates.length - 1] : null;
-}
-
-function getCoordinates() {
- if (coordinates.length > 0 && !running) {
- var result = "";
- var i = 0;
- while (i < coordinates.length) {
- var position = coordinates[i];
- var j = 1;
- result += position[0];
- while (j < position.length) result += "," + position[j++];
- result += " ";
- i++;
- }
- return result;
- }
- return null;
-}
-
-function calculateDistance(lat1, lon1, lat2, lon2) {
- var R = 6371; // km
- var dLat = (lat2-lat1) * Math.PI / 180;
- var dLon = (lon2-lon1) * Math.PI / 180;
- var lat1 = lat1 * Math.PI / 180;
- var lat2 = lat2 * Math.PI / 180;
- var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
- Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
- var d = R * c;
- return d;
-}
-
-function calculateDistanceCoordinates() {
- var result = 0;
- if (coordinates.length > 0) {
- var i = 1;
- while (i < coordinates.length) {
- var position1 = coordinates[i-1];
- var position2 = coordinates[i];
- result += calculateDistance(position1[2], position1[1], position2[2], position2[1]);
- i++;
- }
- }
- return result;
-}
-
-function calculateDurationCoordinates() {
- var result = 0;
- if (coordinates.length > 0) {
- var i = 1;
- while (i < coordinates.length) {
- var position1 = coordinates[i-1];
- var position2 = coordinates[i];
- result += (position2[0]- position1[0]);
- i++;
- }
- }
- return result;
-}
-
-function repaint() {
- if (document.visibilityState == true && running) {
- document.getElementById("locations").textContent = String(locations);
- var d = calculateDistanceCoordinates() * dst_unit;
- var t = duration + (Date.now() - start_time);
- document.getElementById("distance").textContent = String(Math.round(d*100)/100);
- if (t != 0 && d != 0) {
- document.getElementById("speed").textContent = String(Math.round( (d / (t / 3600000)) * 100) / 100);
- document.getElementById("pace").textContent = String(Math.round( ((t / 60000)/d) * 100) / 100);
- }
- if (coordinates.length > 0) {
- document.getElementById("gps_text").style.display = "none";
- document.getElementById("gps_data").style.display = "inline";
- }
- }
-}
-
-function logGPS(position, startMsg) {
- document.getElementById("log").textContent =
- startMsg + position.timestamp
- + ": " + position.coords.latitude
- + ", " + position.coords.longitude
- + ", " + position.coords.altitude
- + ", " + position.coords.accuracy
- + ", " + position.coords.altitudeAccuracy
- + ", " + position.coords.heading
- + ", " + position.coords.speed;
-}
-
-function handleSuccess(position) {
- if (running) {
- logGPS(position, "GPS: ");
-
- // discard positions that have no altitude since they're likely inacurate
- if (position.coords.altitude != null) {
- pushCoordinates(position);
- locations++;
- repaint();
- } else {
- document.getElementById("discarded").textContent = String(discarded++);
- }
- } else {
-
-
- if (position.coords.altitude == null) {
- got_error++;
- if (got_error > MAX_ERRORS) got_error = MAX_ERRORS;
- logGPS(position, "[ERROR] GPS: ");
- } else {
- got_error--;
- logGPS(position, "GPS: ");
- }
- if (got_error <= 0) {
- got_error = 0;
- document.getElementById("gps_text").textContent = "ready";
- document.getElementById("waves").style.display = "block";
- } else {
- document.getElementById("gps_text").textContent = "not ready";
- document.getElementById("waves").style.display = "none";
- }
- }
-}
-
-function handleError(error) {
- var code = "unknown";
- switch(error.code) {
- case error.TIMEOUT:
- code = "timeout";
- break;
- case error.PERMISSION_DENIED:
- code = "permission denied";
- break;
- case error.POSITION_UNAVAILABLE:
- code = "position unavailable";
- break;
- }
- if (running) {
- document.getElementById("errors").textContent = String(++got_error);
- document.getElementById("log").textContent = "[ERROR] GPS: " + code;
- } else {
- document.getElementById("gps_text").textContent = code;
- // wait for 5 non-consecutive errors
- got_error = MAX_ERRORS;
- }
-}
-
-function timer() {
- if (document.visibilityState == true) {
- document.getElementById("realtime").textContent =
- formatTime(Math.round((duration+(Date.now()-start_time))/1000));
- }
-}
-
-function start() {
- if (!running) {
- running = true;
- start_time = Date.now();
- intervalId = setInterval(timer, 1000);
- document.getElementById("stop").disabled = false;
- document.getElementById("start").textContent = "Pause";
- } else {
- running = false;
- clearInterval(intervalId);
- duration += (Date.now() - start_time);
- document.getElementById("start").textContent = "Restart";
- pause();
- document.getElementById("gps_text").style.display = "inline";
- document.getElementById("gps_data").style.display = "none";
- }
-}
-
-function stop() {
- // navigator.geolocation.clearWatch(watchId);
- running = false;
- clearInterval(intervalId);
- got_error = 0;
- locations = 0;
- discarded = 0;
- duration = 0;
- document.getElementById("start").textContent = "Start";
- document.getElementById("stop").disabled = true;
- document.getElementById("log").textContent = "";
- var coords = getCoordinates();
- if (coords != null && storage) {
- try {
- window.localStorage.setItem("track_gps_app", coords);
- } catch (e) {
- document.getDocumentById("log").textContent = "[ERROR] Can't store the value " + e.code;
- }
- }
- if (coords != null) {
- if (!send("teole",coords)) {
- document.getElementById("gps_coords").value = coords;
- document.getElementById("xhr_failed").style.display = "inline";
- document.getElementById("xhr_failed").disabled = false;
- }
- }
- coordinates = [];
-}
-
-function init() {
- if (!!document.visibilityState)
- document.addEventListener("visibilitychange", repaint, false);
- else
- document.visibilityState = true;
-
- // @@ in the future, make sure this is empty
- if (storage) {
- window.localStorage.setItem("track_gps_app", "");
-
- if (window.localStorage.getItem("track_gps_app_dst_unit") === "mile") {
- dst_unit = 0.621371192;
- }
- setUnit();
- } else {
- document.getElementById("log").textContent = "[ERROR] no local storage";
- }
- if (!!navigator.geolocation) {
- watchId = navigator.geolocation.watchPosition(handleSuccess, handleError, {enableHighAccuracy:true, maximumAge:0, timeout:1000});
- } else {
- document.getElementById("gps_text").textContent = "not supported";
- document.getElementById("start").disabled = true;
- }
-
- var xhr = new XMLHttpRequest;
- if (!!xhr && !("withCredentials" in xhr)) {
- document.getElementById("xhr_failed").style.display = "inline";
- document.getElementById("xhr_failed").disabled = true;
- }
-}
-
-window.addEventListener("load", init, false);
-
-function km() {
- if (storage) {
- window.localStorage.setItem("track_gps_app_dst_unit", "km");
- }
- dst_unit = 1;
- setUnit();
- repaint();
-}
-
-function mile() {
- if (storage) {
- window.localStorage.setItem("track_gps_app_dst_unit", "mile");
- }
- dst_unit = 0.621371192;
- setUnit();
- repaint();
-}
-
-function setUnit() {
- var text = (dst_unit == 0.621371192)? "mile" : "km";
- var nodes = document.getElementsByClassName("dst_unit");
- i = 0;
- do {
- nodes[i].textContent = text;
- } while (++i < nodes.length);
-}
-
-]]>
+ <script src='/scripts/tracker.js'>
</script>
-<style>
-body { background-color: #6699ff; }
-section table { margin: auto; }
-section p { text-align: center;}
-.text { font-size: 150%; }
-button {
- font-size: 175%;
- padding-left: 1ex;
- padding-right: 1ex;
- margin: 0;
-}
-#log { font-size: 75%; }
-#errors { color: red }
-#discarded { color: #f88 }
-table { border-collapse: collapse; }
-th { text-align: left; border-right: 1px solid #ccc; padding-right: 0.5ex;}
-td:nth-child(2) { text-align: right; width: 8ex; padding-right: 0.5ex;}
-h1 { text-align: right; padding-right: 1ex; font-family: cursive; margin: 0;}
-#gps_data { display: none }
-
-nav #atab0 { color: #ccc; cursor: default; }
-#vtab0:target ~ #tab0 { display: block }
-#vtab0:target ~ #tab1 { display: none }
-#vtab0:target ~ nav #atab1 { color: #6699ff; cursor: pointer; }
-#vtab0:target ~ nav #atab0 { color: #ccc; cursor: default; }
-
-#tab1 { display: none; }
-#vtab1:target ~ #tab0 { display: none }
-#vtab1:target ~ #tab1 { display: block }
-#vtab1:target ~ nav #atab0 { color: #6699ff; cursor: pointer; }
-#vtab1:target ~ nav #atab1 { color: #ccc; cursor: default; }
-
-section.tab_anchor { display: none; }
-
-nav {
- border-bottom: 1px solid white;
- padding-bottom: 2px;
- margin-bottom: 5px;
-}
-nav a {
- border: 1px solid white;
- background: white;
- color: #6699ff;
- padding: 2px;
-}
-</style>
+ <link rel="stylesheet" href="/styles/tracker.css" type="text/css" />
</head>
<body>
<section id='vtab0' class='tab_anchor'></section>