ulogger-server/main.js

477 lines
14 KiB
JavaScript
Raw Normal View History

2017-01-30 21:36:44 +01:00
/* μlogger
2013-06-19 13:27:14 +02:00
*
2017-01-30 21:36:44 +01:00
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
2013-06-19 13:27:14 +02:00
*
* This is free software; you can redistribute it and/or modify it under
2017-04-07 00:05:28 +02:00
* the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
2013-06-19 13:27:14 +02:00
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
2017-04-07 00:05:28 +02:00
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
2013-06-19 13:27:14 +02:00
*/
2013-06-21 11:15:09 +02:00
// general stuff
2013-06-19 13:27:14 +02:00
if (units=='imperial') {
factor_kmh = 0.62; //to mph
unit_kmh = 'mph';
factor_m = 3.28; // to feet
unit_m = 'ft';
factor_km = 0.62; // to miles
unit_km = 'mi';
}
2013-06-19 13:27:14 +02:00
else {
factor_kmh = 1;
unit_kmh = 'km/h';
factor_m = 1;
unit_m = 'm';
factor_km = 1;
unit_km = 'km';
}
var latest = 0;
var latestTime = 0;
var live = 0;
var chart;
var altitudes = new Array();
var altTimeout;
function displayChart() {
if (chart) { google.visualization.events.removeAllListeners(chart); }
var data = new google.visualization.DataTable();
data.addColumn('number', 'id');
data.addColumn('number', 'altitude');
var altLen = altitudes.length;
for (var i=0; i<altLen; i++) {
data.addRow([(i+1),Math.round((altitudes[i]*factor_m))]);
}
var options = {
title: lang['altitude']+' ('+unit_m+')',
2013-06-19 13:27:14 +02:00
hAxis: { textPosition: 'none' },
legend: { position: 'none' }
};
chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(data, options);
2013-06-21 11:15:09 +02:00
addChartEvent(chart);
2013-06-19 13:27:14 +02:00
}
function toggleChart(i) {
var altLen = altitudes.length;
if (altLen<=1) { return; }
2013-06-19 13:27:14 +02:00
var e = document.getElementById('bottom');
if (arguments.length < 1) {
if (e.style.display == 'block') { i = 0 }
else { i = 1; }
}
2013-06-19 13:27:14 +02:00
if (i==0) {
chart.clearChart();
e.style.display = 'none';
}
else {
e.style.display = 'block';
displayChart();
}
}
function toggleMenu(i) {
2013-06-26 19:58:55 +02:00
var emenu = document.getElementById('menu');
var emain = document.getElementById('main');
var ebutton = document.getElementById('menu-close');
if (arguments.length < 1) {
if (ebutton.innerHTML == '»') { i = 0 }
else { i = 1; }
}
2013-06-26 19:58:55 +02:00
if (i==0) {
emenu.style.width = '0';
emain.style.marginRight = '0';
ebutton.style.right = '0';
ebutton.innerHTML = '«';
}
else {
emenu.style.width = '165px';
emain.style.marginRight = '165px';
ebutton.style.right = '165px';
ebutton.innerHTML = '»';
}
2013-06-26 19:58:55 +02:00
}
2013-06-19 13:27:14 +02:00
function getXHR() {
var xmlhttp = null;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
else {
xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
}
return xmlhttp;
}
function loadTrack(userid,trackid,update) {
if (latest==1) { trackid=0; }
var xhr = getXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
var xml = xhr.responseXML;
var positions = xml.getElementsByTagName('position');
if (positions.length>0) {
clearMap();
2013-06-19 13:27:14 +02:00
displayTrack(xml,update);
}
xhr = null;
}
}
xhr.open('GET','getpositions.php?trackid='+trackid+'&userid='+userid,true);
xhr.send();
}
function parsePosition(p) {
// read data
var latitude = getNode(p,'latitude');
var longitude = getNode(p,'longitude');
var altitude = getNode(p,'altitude'); // may be null
if (altitude != null) { altitude = parseInt(altitude); }
var speed = getNode(p,'speed'); // may be null
if (speed != null) { speed = parseInt(speed); }
2017-01-30 23:46:25 +01:00
var bearing = getNode(p,'bearing'); // may be null
if (bearing != null) { bearing = parseInt(bearing); }
2017-01-30 21:36:44 +01:00
var accuracy = getNode(p,'accuracy'); // may be null
if (accuracy != null) { accuracy = parseInt(accuracy); }
2017-04-09 14:03:43 +02:00
var provider = getNode(p,'provider'); // may be null
2013-07-25 23:34:13 +02:00
var comments = getNode(p,'comments'); // may be null
2013-06-19 13:27:14 +02:00
var username = getNode(p,'username');
var trackname = getNode(p,'trackname');
var tid = getNode(p,'trackid');
var dateoccured = getNode(p,'dateoccured');
var distance = parseInt(getNode(p,'distance'));
var seconds = parseInt(getNode(p,'seconds'));
return {
'latitude': latitude,
'longitude': longitude,
'altitude': altitude,
'speed': speed,
2017-01-30 23:46:25 +01:00
'bearing': bearing,
2017-01-30 21:36:44 +01:00
'accuracy': accuracy,
2017-04-09 14:03:43 +02:00
'provider': provider,
2013-07-25 23:34:13 +02:00
'comments': comments,
2013-06-19 13:27:14 +02:00
'username': username,
'trackname': trackname,
'tid': tid,
'dateoccured': dateoccured,
'distance': distance,
'seconds': seconds
};
2013-06-19 13:27:14 +02:00
}
2017-04-09 14:03:43 +02:00
function getPopupHtml(p, i, count) {
var dateTime = p.dateoccured.split(" ");
var date = dateTime[0];
var time = dateTime[1];
var provider = '';
if (p.provider == 'gps') {
provider = ' (<img class="icon" alt="'+lang['gps']+'" title="'+lang['gps']+'" src="images/gps_dark.svg" />)';
} else if (p.provider == 'network') {
provider = ' (<img class="icon" alt="'+lang['network']+'" title="'+lang['network']+'" src="images/network_dark.svg" />)';
}
popup =
'<div id="popup">'+
'<div id="pheader">'+
'<div><img alt="'+lang['user']+'" title="'+lang['user']+'" src="images/user_dark.svg" /> '+p.username+'</div>'+
'<div><img alt="'+lang['track']+'" title="'+lang['track']+'" src="images/route_dark.svg" /> '+p.trackname+'</div>'+
'</div>'+
'<div id="pbody">'+
((p.comments != null)?'<div id="pcomments">'+p.comments+'</div>':'')+
'<div id="pleft">'+
'<img class="icon" alt="'+lang['time']+'" title="'+lang['time']+'" src="images/calendar_dark.svg" /> '+date+'<br />'+
'<img class="icon" alt="'+lang['time']+'" title="'+lang['time']+'" src="images/clock_dark.svg" /> '+time+'<br />'+
((p.speed != null)?'<img class="icon" alt="'+lang['speed']+'" title="'+lang['speed']+'" src="images/speed_dark.svg" /> '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'<br />':'')+
((p.altitude != null)?'<img class="icon" alt="'+lang['altitude']+'" title="'+lang['altitude']+'" src="images/altitude_dark.svg" /> '+(p.altitude*factor_m).toFixed()+' '+unit_m+'<br />':'')+
((p.accuracy != null)?'<img class="icon" alt="'+lang['accuracy']+'" title="'+lang['accuracy']+'" src="images/accuracy_dark.svg" /> '+(p.accuracy*factor_m).toFixed()+' '+unit_m+provider+'<br />':'')+
'</div>'+
((latest==0)?
('<div id="pright">'+
'<img class="icon" src="images/stats_blue.svg" style="padding-left: 3em;" /><br />'+
'<img class="icon" alt="'+lang['ttime']+'" title="'+lang['ttime']+'" src="images/time_blue.svg" /> '+p.totalSeconds.toHMS()+'<br />'+
'<img class="icon" alt="'+lang['aspeed']+'" title="'+lang['aspeed']+'" src="images/speed_blue.svg" /> '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'<br />'+
'<img class="icon" alt="'+lang['tdistance']+'" title="'+lang['tdistance']+'" src="images/distance_blue.svg" /> '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+'</div>')
:
'')+
'<div id="pfooter">'+lang['point']+' '+(i + 1)+' '+lang['of']+' '+count+'</div>'+
'</div></div>';
return popup;
}
2013-06-19 13:27:14 +02:00
function load(type,userid,trackid) {
var url = 'download.php?type='+type+'&userid='+userid+'&trackid='+trackid;
window.location.assign(url);
}
function updateSummary(l,d,s) {
var t = document.getElementById('summary');
if (latest==0){
t.innerHTML = '<u>'+lang['summary']+'</u><br />'+
2017-04-09 14:03:43 +02:00
'<span><img class="icon" alt="'+lang['tdistance']+'" title="'+lang['tdistance']+'" src="images/distance.svg" /> '+(d.toKm()*factor_km).toFixed(2)+' '+unit_km+'</span>'+
'<span><img class="icon" alt="'+lang['ttime']+'" title="'+lang['ttime']+'" src="images/time.svg" /> '+s.toHMS()+'</span>';
2013-06-19 13:27:14 +02:00
}
else {
t.innerHTML = '<u>'+lang['latest']+':</u><br />'+l;
2013-06-19 13:27:14 +02:00
}
}
function getNode(p,name) {
return ((p.getElementsByTagName(name)[0].childNodes[0]) ? p.getElementsByTagName(name)[0].childNodes[0].nodeValue : null);
}
// seconds to (d) H:M:S
Number.prototype.toHMS = function(){
var s = this;
var d = Math.floor(s / 86400);
var h = Math.floor((s % 86400) / 3600);
var m = Math.floor(((s % 86400) % 3600) / 60);
s = ((s % 86400) % 3600) % 60;
return ((d>0)?(d + ' d '):'') + (('00'+h).slice(-2)) + ':' + (('00'+m).slice(-2)) + ':' + (('00'+s).slice(-2)) + '';
}
// meters to km
Number.prototype.toKm = function() {
return Math.round(this/10)/100;
}
// m/s to km/h
Number.prototype.toKmH = function() {
return Math.round(this*3600/10)/100;
}
// negate value
function toggleLatest() {
if (latest==0) {
latest = 1;
loadTrack(userid,0,1);
}
else {
latest = 0;
loadTrack(userid,trackid,1);
}
}
function setTrack(t) {
document.getElementsByName('track')[0].value = t;
}
function selectTrack(f) {
trackid=f.options[f.selectedIndex].value;
document.getElementById('latest').checked = false;
if (latest==1) { toggleLatest(); }
loadTrack(userid,trackid,1);
}
function selectUser(f) {
userid=f.options[f.selectedIndex].value;
if (f.options[0].disabled==false) {
f.options[0].disabled = true;
}
document.getElementById('latest').checked = false;
if (latest==1) { toggleLatest(); }
2017-01-30 21:36:44 +01:00
getTracks(userid);
2013-06-19 13:27:14 +02:00
}
2017-01-30 21:36:44 +01:00
function getTracks(userid) {
2013-06-19 13:27:14 +02:00
var xhr = getXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
var xml = xhr.responseXML;
2014-09-07 21:19:43 +02:00
var trackSelect = document.getElementsByName('track')[0];
clearOptions(trackSelect);
2017-01-30 21:36:44 +01:00
var tracks = xml.getElementsByTagName('track');
if (tracks.length>0) {
2013-06-19 13:27:14 +02:00
fillOptions(xml);
2014-09-07 21:19:43 +02:00
} else {
clearMap();
2013-06-19 13:27:14 +02:00
}
xhr = null;
}
}
2017-01-30 21:36:44 +01:00
xhr.open('GET','gettracks.php?userid='+userid,true);
xhr.send();
2013-06-19 13:27:14 +02:00
}
function fillOptions(xml) {
var trackSelect = document.getElementsByName('track')[0];
2017-01-30 21:36:44 +01:00
var tracks = xml.getElementsByTagName('track');
var trackLen = tracks.length;
for (var i=0; i<trackLen; i++) {
var trackid = getNode(tracks[i],'trackid');
var trackname = getNode(tracks[i],'trackname');
2013-06-19 13:27:14 +02:00
var option = document.createElement("option");
option.value = trackid;
option.innerHTML = trackname;
trackSelect.appendChild(option);
}
2017-01-30 21:36:44 +01:00
var defaultTrack = getNode(tracks[0],'trackid');
2013-06-19 13:27:14 +02:00
loadTrack(userid,defaultTrack,1);
}
function clearOptions(el){
if (el.options) {
while (el.options.length) {
el.remove(0);
}
}
}
var auto;
function autoReload() {
if (live==0) {
live = 1;
auto = setInterval(function() { loadTrack(userid,trackid,0); },interval*1000);
}
else {
live = 0;
clearInterval(auto);
}
}
function setTime() {
var i = parseInt(prompt(lang['newinterval']));
2013-06-19 13:27:14 +02:00
if (!isNaN(i) && i!=interval) {
interval = i;
document.getElementById('auto').innerHTML = interval;
// if live tracking on, reload with new interval
if (live==1) {
2013-06-19 13:27:14 +02:00
live = 0;
clearInterval(auto);
autoReload();
}
2013-06-23 23:43:09 +02:00
// save current state as default
setCookie('interval',interval,30);
}
2013-06-21 11:15:09 +02:00
}
// dynamic change of map api
var savedBounds;
2013-06-21 11:15:09 +02:00
function loadMapAPI(api) {
savedBounds = getBounds();
document.getElementById("map-canvas").innerHTML = '';
var url = new Array();
if (api=='gmaps') {
url.push('api_gmaps.js');
url.push('//maps.googleapis.com/maps/api/js?'+((gkey!==null)?('key='+gkey+'&'):'')+'callback=init');
}
else {
url.push('api_openlayers.js');
url.push('//openlayers.org/api/OpenLayers.js');
}
addScript(url[0]);
waitAndLoad(api,url);
2013-06-21 11:15:09 +02:00
}
var loadTime = 0;
function waitAndLoad(api,url) {
// wait till first script loaded
if (loadTime>5000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; }
if (loadedAPI!==api) {
setTimeout(function() { loadTime += 50; waitAndLoad(api,url); }, 50);
return;
}
if(!isScriptLoaded(url[1])){
addScript(url[1]);
}
loadTime = 0;
waitAndInit(api);
2013-06-21 11:15:09 +02:00
}
function waitAndInit(api) {
// wait till main api loads
if (loadTime>10000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; }
try {
init();
}
catch(e) {
setTimeout(function() { loadTime += 50; waitAndInit(api); }, 50);
return;
}
loadTime = 0;
zoomToBounds(savedBounds);
loadTrack(userid,trackid,0);
// save current api as default
setCookie('api',api,30);
2013-06-21 11:15:09 +02:00
}
function addScript(url) {
var tag = document.createElement('script');
tag.setAttribute('type','text/javascript');
tag.setAttribute('src', url);
if (typeof tag!='undefined') {
document.getElementsByTagName('head')[0].appendChild(tag);
}
2013-06-21 11:15:09 +02:00
}
function isScriptLoaded(url) {
scripts = document.getElementsByTagName('script');
for (var i = scripts.length; i--;) {
// check if url matches src
var scriptUrl = scripts[i].src.replace(/https?:/,'');
if (scriptUrl != '' && url.indexOf(scriptUrl) !== -1) return true;
}
return false;
2013-06-19 13:27:14 +02:00
}
2013-06-23 23:43:09 +02:00
function setCookie(name,value,days) {
if (days) {
2013-06-23 23:43:09 +02:00
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = '; expires='+date.toGMTString();
}
else {
var expires = '';
}
2017-01-30 21:36:44 +01:00
document.cookie = 'ulogger_'+name+'='+value+expires+'; path=/';
2013-06-23 23:43:09 +02:00
}
function setLang(lang) {
setCookie('lang',lang,30);
location.reload();
}
function setUnits(unit) {
units = unit;
setCookie('units',unit,30);
location.reload();
}
function showModal(contentHTML) {
2017-04-06 23:23:25 +02:00
var div = document.createElement('div');
div.setAttribute('id', 'modal');
2017-04-07 22:26:47 +02:00
div.innerHTML = '<div id="modal-header"><button type="button" onclick="removeModal()"><img src="images/close.svg" \></button></div><div id="modal-body"></div>';
document.body.appendChild(div);
var modalBody = document.getElementById('modal-body');
modalBody.innerHTML = contentHTML;
}
function removeModal() {
document.body.removeChild(document.getElementById('modal'));
2017-04-06 23:23:25 +02:00
}
function userMenu() {
var dropdown = document.getElementById('user_dropdown');
if (dropdown.classList.contains('show')) {
dropdown.classList.remove('show');
} else {
dropdown.classList.add('show');
window.addEventListener('click', removeOnClick, true);
}
}
function removeOnClick(event) {
var parent = event.target.parentElement;
var dropdown = document.getElementById('user_dropdown');
dropdown.classList.remove('show');
window.removeEventListener('click', removeOnClick, true);
if (!parent.classList.contains('dropdown')) {
event.stopPropagation();
}
}