reorganize, document, clean javascript code
This commit is contained in:
parent
7acc3df67d
commit
7f1170187c
21
css/main.css
21
css/main.css
@ -28,6 +28,7 @@ body {
|
||||
a {
|
||||
color: #bce;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
:link, :visited {
|
||||
color: #bce;
|
||||
@ -105,9 +106,19 @@ select {
|
||||
border-radius: 11px 0 0 11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#user, #track, #summary, #export, #import, #other, #units {
|
||||
label[for=user] {
|
||||
padding-top: 1em;
|
||||
display: block;
|
||||
}
|
||||
.section {
|
||||
padding-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
.section:first-child {
|
||||
padding-top: 1em;
|
||||
}
|
||||
#inputFile {
|
||||
display: none;
|
||||
}
|
||||
#summary div {
|
||||
padding-top: .3em;
|
||||
@ -190,16 +201,14 @@ select {
|
||||
background-color: white;
|
||||
opacity: 0.8;
|
||||
}
|
||||
#close {
|
||||
#chart_close {
|
||||
position: fixed;
|
||||
bottom: 175px;
|
||||
right: 175px;
|
||||
z-index: 10001;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
#close a, #close:link, #close:visited {
|
||||
color: #5070af;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mi {
|
||||
|
@ -27,7 +27,9 @@
|
||||
*/
|
||||
class uAuth {
|
||||
|
||||
/** @var bool Is user authenticated */
|
||||
private $isAuthenticated = false;
|
||||
/** @var uUser|null User */
|
||||
public $user = null;
|
||||
|
||||
public function __construct() {
|
||||
@ -107,7 +109,7 @@
|
||||
/**
|
||||
* Process log in request
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkLogin($login, $pass) {
|
||||
if (!is_null($login) && !is_null($pass)) {
|
||||
|
@ -27,59 +27,108 @@
|
||||
* Handles config values
|
||||
*/
|
||||
class uConfig {
|
||||
// version number
|
||||
/**
|
||||
* @var string Version number
|
||||
*/
|
||||
static $version = "1.0-beta";
|
||||
|
||||
// default map drawing framework
|
||||
/**
|
||||
* @var string Default map drawing framework
|
||||
*/
|
||||
static $mapapi = "openlayers";
|
||||
|
||||
// gmaps key
|
||||
/**
|
||||
* @var string|null Google maps key
|
||||
*/
|
||||
static $gkey = null;
|
||||
|
||||
// openlayers additional map layers
|
||||
/**
|
||||
* @var array Openlayers additional map layers
|
||||
*/
|
||||
static $ol_layers = [];
|
||||
|
||||
// default coordinates for initial map
|
||||
/**
|
||||
* @var float Default latitude for initial map
|
||||
*/
|
||||
static $init_latitude = 52.23;
|
||||
/**
|
||||
* @var float Default longitude for initial map
|
||||
*/
|
||||
static $init_longitude = 21.01;
|
||||
|
||||
// MySQL config
|
||||
static $dbdsn = ""; // database dsn
|
||||
static $dbuser = ""; // database user
|
||||
static $dbpass = ""; // database pass
|
||||
static $dbprefix = ""; // optional table names prefix, eg. "ulogger_"
|
||||
/**
|
||||
* @var string Database dsn
|
||||
*/
|
||||
static $dbdsn = "";
|
||||
/**
|
||||
* @var string Database user
|
||||
*/
|
||||
static $dbuser = "";
|
||||
/**
|
||||
* @var string Database pass
|
||||
*/
|
||||
static $dbpass = "";
|
||||
/**
|
||||
* @var string Optional table names prefix, eg. "ulogger_"
|
||||
*/
|
||||
static $dbprefix = "";
|
||||
|
||||
// require login/password authentication
|
||||
/**
|
||||
* @var bool Require login/password authentication
|
||||
*/
|
||||
static $require_authentication = true;
|
||||
|
||||
// all users tracks are visible to authenticated user
|
||||
/**
|
||||
* @var bool All users tracks are visible to authenticated user
|
||||
*/
|
||||
static $public_tracks = false;
|
||||
|
||||
// admin user who has access to all users locations
|
||||
// none if empty
|
||||
/**
|
||||
* @var string Admin user who has access to all users locations
|
||||
* none if empty
|
||||
*/
|
||||
static $admin_user = "";
|
||||
|
||||
// miniumum required length of user password
|
||||
/**
|
||||
* @var int Miniumum required length of user password
|
||||
*/
|
||||
static $pass_lenmin = 12;
|
||||
|
||||
// required strength of user password
|
||||
// 0 = no requirements,
|
||||
// 1 = require mixed case letters (lower and upper),
|
||||
// 2 = require mixed case and numbers
|
||||
// 3 = require mixed case, numbers and non-alphanumeric characters
|
||||
/**
|
||||
* @var int Required strength of user password
|
||||
* 0 = no requirements,
|
||||
* 1 = require mixed case letters (lower and upper),
|
||||
* 2 = require mixed case and numbers
|
||||
* 3 = require mixed case, numbers and non-alphanumeric characters
|
||||
*/
|
||||
static $pass_strength = 2;
|
||||
|
||||
// Default interval in seconds for live auto reload
|
||||
/**
|
||||
* @var int Default interval in seconds for live auto reload
|
||||
*/
|
||||
static $interval = 10;
|
||||
|
||||
// Default language
|
||||
/**
|
||||
* @var string Default language code
|
||||
*/
|
||||
static $lang = "en";
|
||||
|
||||
// units
|
||||
/**
|
||||
* @var string Default units
|
||||
*/
|
||||
static $units = "metric";
|
||||
|
||||
/**
|
||||
* @var int Stroke weight
|
||||
*/
|
||||
static $strokeWeight = 2;
|
||||
/**
|
||||
* @var string Stroke color
|
||||
*/
|
||||
static $strokeColor = '#ff0000';
|
||||
/**
|
||||
* @var int Stroke opacity
|
||||
*/
|
||||
static $strokeOpacity = 1;
|
||||
|
||||
private static $fileLoaded = false;
|
||||
@ -109,7 +158,7 @@
|
||||
include_once($configFile);
|
||||
|
||||
if (isset($mapapi)) { self::$mapapi = $mapapi; }
|
||||
if (isset($gkey)) { self::$gkey = $gkey; }
|
||||
if (isset($gkey) && !empty($gkey)) { self::$gkey = $gkey; }
|
||||
if (isset($ol_layers)) { self::$ol_layers = $ol_layers; }
|
||||
if (isset($init_latitude)) { self::$init_latitude = $init_latitude; }
|
||||
if (isset($init_longitude)) { self::$init_longitude = $init_longitude; }
|
||||
|
144
index.php
144
index.php
@ -73,51 +73,79 @@
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="<?= uConfig::$lang ?>">
|
||||
<head>
|
||||
<title><?= $lang["title"] ?></title>
|
||||
<?php include("meta.php"); ?>
|
||||
<script>
|
||||
var interval = '<?= uConfig::$interval ?>';
|
||||
var userid = '<?= ($displayUserId) ? $displayUserId : -1 ?>';
|
||||
var trackid = '<?= ($displayTrackId) ? $displayTrackId : -1 ?>';
|
||||
var units = '<?= uConfig::$units ?>';
|
||||
var mapapi = '<?= uConfig::$mapapi ?>';
|
||||
var gkey = '<?= !empty(uConfig::$gkey) ? uConfig::$gkey : "null" ?>';
|
||||
var ol_layers = <?= json_encode(uConfig::$ol_layers) ?>;
|
||||
var init_latitude = <?= uConfig::$init_latitude ?>;
|
||||
var init_longitude = <?= uConfig::$init_longitude ?>;
|
||||
var lang = <?= json_encode($lang) ?>;
|
||||
var admin = <?= json_encode($auth->isAdmin()) ?>;
|
||||
var auth = '<?= ($auth->isAuthenticated()) ? $auth->user->login : "null" ?>';
|
||||
var pass_regex = <?= uConfig::passRegex() ?>;
|
||||
var strokeWeight = <?= uConfig::$strokeWeight ?>;
|
||||
var strokeColor = '<?= uConfig::$strokeColor ?>';
|
||||
var strokeOpacity = <?= uConfig::$strokeOpacity ?>;
|
||||
/** @namespace uLogger */
|
||||
var uLogger = window.uLogger || {};
|
||||
/** @type {number} userId */
|
||||
uLogger.userId = <?= json_encode($displayUserId ? $displayUserId : -1) ?>;
|
||||
/** @type {number} trackId */
|
||||
uLogger.trackId = <?= json_encode($displayTrackId ? $displayTrackId : -1) ?>;
|
||||
|
||||
/** @type {uLogger.config} */
|
||||
uLogger.config = {
|
||||
/** @type {number} */
|
||||
interval: <?= json_encode(uConfig::$interval) ?>,
|
||||
/** @type {string} */
|
||||
units: <?= json_encode(uConfig::$units) ?>,
|
||||
/** @type {string} */
|
||||
mapapi: <?= json_encode(uConfig::$mapapi) ?>,
|
||||
/** @type {?string} */
|
||||
gkey: <?= json_encode(uConfig::$gkey) ?>,
|
||||
/** @type {Object.<string, string>} */
|
||||
ol_layers: <?= json_encode(uConfig::$ol_layers) ?>,
|
||||
/** @type {number} */
|
||||
init_latitude: <?= json_encode(uConfig::$init_latitude) ?>,
|
||||
/** @type {number} */
|
||||
init_longitude: <?= json_encode(uConfig::$init_longitude) ?>,
|
||||
/** @type {boolean} */
|
||||
admin: <?= json_encode($auth->isAdmin()) ?>,
|
||||
/** @type {?string} */
|
||||
auth: <?= json_encode($auth->isAuthenticated() ? $auth->user->login : NULL) ?>,
|
||||
/** @type {RegExp} */
|
||||
pass_regex: <?= uConfig::passRegex() ?>,
|
||||
/** @type {number} */
|
||||
strokeWeight: <?= json_encode(uConfig::$strokeWeight) ?>,
|
||||
/** @type {string} */
|
||||
strokeColor: <?= json_encode(uConfig::$strokeColor) ?>,
|
||||
/** @type {number} */
|
||||
strokeOpacity: <?= json_encode(uConfig::$strokeOpacity) ?>
|
||||
};
|
||||
|
||||
/** @type {uLogger.lang} */
|
||||
uLogger.lang = {
|
||||
/** @type {Object.<string, string>} */
|
||||
strings: <?= json_encode($lang) ?>
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="js/main.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
<?php if ($auth->isAdmin()): ?>
|
||||
<script type="text/javascript" src="js/admin.js"></script>
|
||||
<script src="js/admin.js"></script>
|
||||
<?php endif; ?>
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<script type="text/javascript" src="js/track.js"></script>
|
||||
<script src="js/track.js"></script>
|
||||
<?php endif; ?>
|
||||
<script type="text/javascript" src="js/pass.js"></script>
|
||||
<script type="text/javascript" src="//www.google.com/jsapi"></script>
|
||||
<script type="text/javascript">
|
||||
<script src="js/pass.js"></script>
|
||||
<script src="js/api_gmaps.js"></script>
|
||||
<script src="js/api_openlayers.js"></script>
|
||||
<script src="//www.google.com/jsapi"></script>
|
||||
<script>
|
||||
google.load('visualization', '1', { packages:['corechart'] });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="loadMapAPI();">
|
||||
<body>
|
||||
<div id="menu">
|
||||
<div id="menu-content">
|
||||
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<div id="user_menu">
|
||||
<a href="javascript:void(0);" onclick="userMenu()"><img class="icon" alt="<?= $lang["user"] ?>" src="images/user.svg"> <?= htmlspecialchars($auth->user->login) ?></a>
|
||||
<a id="menu_head"><img class="icon" alt="<?= $lang["user"] ?>" src="images/user.svg"> <?= htmlspecialchars($auth->user->login) ?></a>
|
||||
<div id="user_dropdown" class="dropdown">
|
||||
<a href="javascript:void(0)" onclick="changePass()"><img class="icon" alt="<?= $lang["changepass"] ?>" src="images/lock.svg"> <?= $lang["changepass"] ?></a>
|
||||
<a id="menu_pass"><img class="icon" alt="<?= $lang["changepass"] ?>" src="images/lock.svg"> <?= $lang["changepass"] ?></a>
|
||||
<a href="utils/logout.php"><img class="icon" alt="<?= $lang["logout"] ?>" src="images/poweroff.svg"> <?= $lang["logout"] ?></a>
|
||||
</div>
|
||||
</div>
|
||||
@ -125,11 +153,11 @@
|
||||
<a href="login.php"><img class="icon" alt="<?= $lang["login"] ?>" src="images/key.svg"> <?= $lang["login"] ?></a>
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="user">
|
||||
<div class="section">
|
||||
<?php if (!empty($usersArr)): ?>
|
||||
<div class="menutitle" style="padding-top: 1em"><?= $lang["user"] ?></div>
|
||||
<label for="user" class="menutitle"><?= $lang["user"] ?></label>
|
||||
<form>
|
||||
<select name="user" onchange="selectUser(this);">
|
||||
<select id="user" name="user">
|
||||
<option value="0" disabled><?= $lang["suser"] ?></option>
|
||||
<?php foreach ($usersArr as $aUser): ?>
|
||||
<option <?= ($aUser->id == $displayUserId) ? "selected " : "" ?>value="<?= $aUser->id ?>"><?= htmlspecialchars($aUser->login) ?></option>
|
||||
@ -139,40 +167,40 @@
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div id="track">
|
||||
<div class="menutitle"><?= $lang["track"] ?></div>
|
||||
<div class="section">
|
||||
<label for="track" class="menutitle"><?= $lang["track"] ?></label>
|
||||
<form>
|
||||
<select name="track" onchange="selectTrack(this)">
|
||||
<select id="track" name="track">
|
||||
<?php foreach ($tracksArr as $aTrack): ?>
|
||||
<option value="<?= $aTrack->id ?>"><?= htmlspecialchars($aTrack->name) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input id="latest" type="checkbox" onchange="toggleLatest();"> <?= $lang["latest"] ?><br>
|
||||
<input type="checkbox" onchange="autoReload();"> <?= $lang["autoreload"] ?> (<a href="javascript:void(0);" onclick="setTime();"><span id="auto"><?= uConfig::$interval ?></span></a> s)<br>
|
||||
<input id="latest" type="checkbox"> <label for="latest"><?= $lang["latest"] ?></label><br>
|
||||
<input id="auto_reload" type="checkbox"> <label for="auto_reload"><?= $lang["autoreload"] ?></label> (<a id="set_time"><span id="auto"><?= uConfig::$interval ?></span></a> s)<br>
|
||||
</form>
|
||||
<a href="javascript:void(0);" onclick="reload(userid, trackid);"> <?= $lang["reload"] ?></a><br>
|
||||
<a id="force_reload"> <?= $lang["reload"] ?></a><br>
|
||||
</div>
|
||||
|
||||
<div id="summary"></div>
|
||||
<div id="summary" class="section"></div>
|
||||
|
||||
<div id="other">
|
||||
<a id="altitudes" href="javascript:void(0);" onclick="toggleChart();"><?= $lang["chart"] ?></a>
|
||||
<div id="other" class="section">
|
||||
<a id="altitudes"><?= $lang["chart"] ?></a>
|
||||
</div>
|
||||
|
||||
<div id="api">
|
||||
<div class="menutitle"><?= $lang["api"] ?></div>
|
||||
<div>
|
||||
<label for="api" class="menutitle"><?= $lang["api"] ?></label>
|
||||
<form>
|
||||
<select name="api" onchange="loadMapAPI(this.options[this.selectedIndex].value);">
|
||||
<select id="api" name="api">
|
||||
<option value="gmaps"<?= (uConfig::$mapapi == "gmaps") ? " selected" : "" ?>>Google Maps</option>
|
||||
<option value="openlayers"<?= (uConfig::$mapapi == "openlayers") ? " selected" : "" ?>>OpenLayers</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="lang">
|
||||
<div class="menutitle"><?= $lang["language"] ?></div>
|
||||
<div>
|
||||
<label for="lang" class="menutitle"><?= $lang["language"] ?></label>
|
||||
<form>
|
||||
<select name="units" onchange="setLang(this.options[this.selectedIndex].value);">
|
||||
<select id="lang" name="lang">
|
||||
<?php foreach ($langsArr as $langCode => $langName): ?>
|
||||
<option value="<?= $langCode ?>"<?= (uConfig::$lang == $langCode) ? " selected" : "" ?>><?= $langName ?></option>
|
||||
<?php endforeach; ?>
|
||||
@ -180,10 +208,10 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="units">
|
||||
<div class="menutitle"><?= $lang["units"] ?></div>
|
||||
<div class="section">
|
||||
<label for="units" class="menutitle"><?= $lang["units"] ?></label>
|
||||
<form>
|
||||
<select name="units" onchange="setUnits(this.options[this.selectedIndex].value);">
|
||||
<select id="units" name="units">
|
||||
<option value="metric"<?= (uConfig::$units == "metric") ? " selected" : "" ?>><?= $lang["metric"] ?></option>
|
||||
<option value="imperial"<?= (uConfig::$units == "imperial") ? " selected" : "" ?>><?= $lang["imperial"] ?></option>
|
||||
<option value="nautical"<?= (uConfig::$units == "nautical") ? " selected" : "" ?>><?= $lang["nautical"] ?></option>
|
||||
@ -191,34 +219,34 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="export">
|
||||
<div id="export" class="section">
|
||||
<div class="menutitle u"><?= $lang["export"] ?></div>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="exportFile('kml', userid, trackid);">kml</a>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="exportFile('gpx', userid, trackid);">gpx</a>
|
||||
<a id="export_kml" class="menulink">kml</a>
|
||||
<a id="export_gpx" class="menulink">gpx</a>
|
||||
</div>
|
||||
|
||||
<?php if ($auth->isAuthenticated()): ?>
|
||||
<div id="import">
|
||||
<div id="import" class="section">
|
||||
<div class="menutitle u"><?= $lang["import"] ?></div>
|
||||
<form id="importForm" enctype="multipart/form-data" method="post">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="<?= uUtils::getUploadMaxSize() ?>" />
|
||||
<input type="file" id="inputFile" name="gpx" style="display:none" onchange="importFile(this)" />
|
||||
<input type="file" id="inputFile" name="gpx" />
|
||||
</form>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="document.getElementById('inputFile').click();">gpx</a>
|
||||
<a id="import_gpx" class="menulink">gpx</a>
|
||||
</div>
|
||||
|
||||
<div id="admin_menu">
|
||||
<div class="menutitle u"><?= $lang["adminmenu"] ?></div>
|
||||
<?php if ($auth->isAdmin()): ?>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="addUser()"><?= $lang["adduser"] ?></a>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="editUser()"><?= $lang["edituser"] ?></a>
|
||||
<a id="adduser" class="menulink"><?= $lang["adduser"] ?></a>
|
||||
<a id="edituser" class="menulink"><?= $lang["edituser"] ?></a>
|
||||
<?php endif; ?>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="editTrack()"><?= $lang["edittrack"] ?></a>
|
||||
<a id="edittrack" class="menulink"><?= $lang["edittrack"] ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
<div id="menu-close" onclick="toggleMenu();">»</div>
|
||||
<div id="menu-close">»</div>
|
||||
<div id="footer"><a target="_blank" href="https://github.com/bfabiszewski/ulogger-server"><span class="mi">μ</span>logger</a> <?= uConfig::$version ?></div>
|
||||
</div>
|
||||
|
||||
@ -226,7 +254,7 @@
|
||||
<div id="map-canvas"></div>
|
||||
<div id="bottom">
|
||||
<div id="chart"></div>
|
||||
<div id="close"><a href="javascript:void(0);" onclick="toggleChart(0);"><?= $lang["close"] ?></a></div>
|
||||
<div id="chart_close"><?= $lang["close"] ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
162
js/admin.js
162
js/admin.js
@ -16,104 +16,126 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function addUser() {
|
||||
var form = '<form id="userForm" method="post" onsubmit="submitUser(\'add\'); return false">';
|
||||
form += '<label><b>' + lang['username'] + '</b></label><input type="text" placeholder="' + lang['usernameenter'] + '" name="login" required>';
|
||||
form += '<label><b>' + lang['password'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + lang['passwordrepeat'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="removeModal()">' + lang['cancel'] + '</button><button type="submit">' + lang['submit'] + '</button></div>';
|
||||
form += '</form>';
|
||||
showModal(form);
|
||||
}
|
||||
/** @namespace */
|
||||
var uLogger = window.uLogger || {};
|
||||
(function (ul) {
|
||||
|
||||
function editUser() {
|
||||
var userForm = document.getElementsByName('user')[0];
|
||||
var userLogin = (userForm !== undefined) ? userForm.options[userForm.selectedIndex].text : auth;
|
||||
if (userLogin == auth) {
|
||||
alert(lang['selfeditwarn']);
|
||||
/**
|
||||
* @typedef uLogger.admin
|
||||
* @memberOf uLogger
|
||||
* @type {Object}
|
||||
* @property {function} addUser
|
||||
* @property {function} editUser
|
||||
* @property {function} submitUser
|
||||
*/
|
||||
ul.admin = (function (ns) {
|
||||
|
||||
/**
|
||||
* Show add user dialog
|
||||
*/
|
||||
function addUser() {
|
||||
var form = '<form id="userForm" method="post" onsubmit="uLogger.admin.submitUser(\'add\'); return false">';
|
||||
form += '<label><b>' + ns.lang.strings['username'] + '</b></label><input type="text" placeholder="' + ns.lang.strings['usernameenter'] + '" name="login" required>';
|
||||
form += '<label><b>' + ns.lang.strings['password'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + ns.lang.strings['passwordrepeat'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="uLogger.ui.removeModal()">' + ns.lang.strings['cancel'] + '</button><button type="submit">' + ns.lang.strings['submit'] + '</button></div>';
|
||||
form += '</form>';
|
||||
ns.ui.showModal(form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show edit user dialog
|
||||
*/
|
||||
function editUser() {
|
||||
var userForm = ns.ui.userSelect;
|
||||
var userLogin = (userForm) ? userForm.options[userForm.selectedIndex].text : ns.config.auth;
|
||||
if (userLogin === ns.config.auth) {
|
||||
alert(ns.lang.strings['selfeditwarn']);
|
||||
return;
|
||||
}
|
||||
var message = '<div style="float:left">' + sprintf(lang['editinguser'], '<b>' + htmlEncode(userLogin) + '</b>') + '</div>';
|
||||
message += '<div class="red-button"><b><a href="javascript:void(0);" onclick="submitUser(\'delete\'); return false">' + lang['deluser'] + '</a></b></div>';
|
||||
var message = '<div style="float:left">' + ns.sprintf(ns.lang.strings['editinguser'], '<b>' + ns.htmlEncode(userLogin) + '</b>') + '</div>';
|
||||
message += '<div class="red-button"><b><a href="javascript:void(0);" onclick="uLogger.admin.submitUser(\'delete\'); return false">' + ns.lang.strings['deluser'] + '</a></b></div>';
|
||||
message += '<div style="clear: both; padding-bottom: 1em;"></div>';
|
||||
|
||||
var form = '<form id="userForm" method="post" onsubmit="submitUser(\'update\'); return false">';
|
||||
form += '<input type="hidden" name="login" value="' + htmlEncode(userLogin) + '">';
|
||||
form += '<label><b>' + lang['password'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + lang['passwordrepeat'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="removeModal()">' + lang['cancel'] + '</button><button type="submit">' + lang['submit'] + '</button></div>';
|
||||
var form = '<form id="userForm" method="post" onsubmit="uLogger.admin.submitUser(\'update\'); return false">';
|
||||
form += '<input type="hidden" name="login" value="' + ns.htmlEncode(userLogin) + '">';
|
||||
form += '<label><b>' + ns.lang.strings['password'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + ns.lang.strings['passwordrepeat'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="uLogger.ui.removeModal()">' + ns.lang.strings['cancel'] + '</button><button type="submit">' + ns.lang.strings['submit'] + '</button></div>';
|
||||
form += '</form>';
|
||||
showModal(message + form);
|
||||
}
|
||||
ns.ui.showModal(message + form);
|
||||
}
|
||||
|
||||
function confirmedDelete(login) {
|
||||
return confirm(sprintf(lang['userdelwarn'], '"' + login + '"'));
|
||||
}
|
||||
/**
|
||||
* Show confirmation dialog
|
||||
* @param {string} login
|
||||
* @returns {boolean} True if confirmed
|
||||
*/
|
||||
function confirmedDelete(login) {
|
||||
return confirm(ns.sprintf(ns.lang.strings['userdelwarn'], '"' + login + '"'));
|
||||
}
|
||||
|
||||
function submitUser(action) {
|
||||
/**
|
||||
* Submit user form
|
||||
* @param {string} action Add, delete, update
|
||||
*/
|
||||
function submitUser(action) {
|
||||
var form = document.getElementById('userForm');
|
||||
var login = form.elements['login'].value.trim();
|
||||
if (!login) {
|
||||
alert(lang['allrequired']);
|
||||
alert(ns.lang.strings['allrequired']);
|
||||
return;
|
||||
}
|
||||
var pass = null;
|
||||
var pass2 = null;
|
||||
if (action != 'delete') {
|
||||
if (action !== 'delete') {
|
||||
pass = form.elements['pass'].value;
|
||||
pass2 = form.elements['pass2'].value;
|
||||
if (!pass || !pass2) {
|
||||
alert(lang['allrequired']);
|
||||
alert(ns.lang.strings['allrequired']);
|
||||
return;
|
||||
}
|
||||
if (pass != pass2) {
|
||||
alert(lang['passnotmatch']);
|
||||
if (pass !== pass2) {
|
||||
alert(ns.lang.strings['passnotmatch']);
|
||||
return;
|
||||
}
|
||||
if (!pass_regex.test(pass)) {
|
||||
alert(lang['passlenmin'] + '\n' + lang['passrules']);
|
||||
if (!ns.config.pass_regex.test(pass)) {
|
||||
alert(ns.lang.strings['passlenmin'] + '\n' + ns.lang.strings['passrules']);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!confirmedDelete(login)) {
|
||||
} else if (!confirmedDelete(login)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
var error = true;
|
||||
var message = '';
|
||||
if (xhr.status == 200) {
|
||||
var xml = xhr.responseXML;
|
||||
if (xml) {
|
||||
var root = xml.getElementsByTagName('root');
|
||||
if (root.length && getNode(root[0], 'error') == 0) {
|
||||
removeModal();
|
||||
alert(lang['actionsuccess']);
|
||||
if (action == 'delete') {
|
||||
// select current user in users form
|
||||
var f = document.getElementsByName('user')[0];
|
||||
|
||||
ns.post('utils/handleuser.php',
|
||||
{
|
||||
action: action,
|
||||
login: login,
|
||||
pass: pass
|
||||
},
|
||||
{
|
||||
success: function () {
|
||||
ns.ui.removeModal();
|
||||
alert(ns.lang.strings['actionsuccess']);
|
||||
if (action === 'delete') {
|
||||
var f = ns.ui.userSelect;
|
||||
f.remove(f.selectedIndex);
|
||||
selectUser(f);
|
||||
ns.selectUser(f);
|
||||
}
|
||||
error = false;
|
||||
} else if (root.length) {
|
||||
errorMsg = getNode(root[0], 'message');
|
||||
if (errorMsg) { message = errorMsg; }
|
||||
},
|
||||
fail: function (message) {
|
||||
alert(ns.lang.strings['actionfailure'] + '\n' + message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
return {
|
||||
addUser: addUser,
|
||||
editUser: editUser,
|
||||
submitUser: submitUser
|
||||
}
|
||||
if (error) {
|
||||
alert(lang['actionfailure'] + '\n' + message);
|
||||
}
|
||||
xhr = null;
|
||||
}
|
||||
}
|
||||
xhr.open('POST', 'utils/handleuser.php', true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var params = 'action=' + action + '&login=' + encodeURIComponent(login) + '&pass=' + encodeURIComponent(pass);
|
||||
params = params.replace(/%20/g, '+');
|
||||
xhr.send(params);
|
||||
return;
|
||||
}
|
||||
|
||||
})(ul);
|
||||
|
||||
})(uLogger);
|
||||
|
288
js/api_gmaps.js
288
js/api_gmaps.js
@ -17,44 +17,90 @@
|
||||
*/
|
||||
|
||||
// google maps
|
||||
var map;
|
||||
var polies = [];
|
||||
var markers = [];
|
||||
var popups = [];
|
||||
var popup;
|
||||
var polyOptions;
|
||||
var mapOptions;
|
||||
var loadedAPI = 'gmaps';
|
||||
/** @namespace */
|
||||
var uLogger = uLogger || {};
|
||||
/** @namespace */
|
||||
uLogger.mapAPI = uLogger.mapAPI || {};
|
||||
/** @namespace */
|
||||
uLogger.mapAPI.gmaps = (function(ns) {
|
||||
|
||||
function init() {
|
||||
if (gm_error) { return gm_authFailure(); }
|
||||
google.maps.visualRefresh = true;
|
||||
polyOptions = {
|
||||
strokeColor: strokeColor,
|
||||
strokeOpacity: strokeOpacity,
|
||||
strokeWeight: strokeWeight
|
||||
/** @type {google.maps.Map} */
|
||||
var map;
|
||||
/** @type {google.maps.Polyline[]} */
|
||||
var polies = [];
|
||||
/** @type {google.maps.Marker[]} */
|
||||
var markers = [];
|
||||
/** @type {google.maps.InfoWindow[]} */
|
||||
var popups = [];
|
||||
/** @type {google.maps.InfoWindow} */
|
||||
var popup;
|
||||
/** @type {google.maps.PolylineOptions} */
|
||||
var polyOptions;
|
||||
/** @type {google.maps.MapOptions} */
|
||||
var mapOptions;
|
||||
/** @type {number} */
|
||||
var timeoutHandle;
|
||||
var name = 'gmaps';
|
||||
var isLoaded = false;
|
||||
var authError = false;
|
||||
|
||||
/**
|
||||
* Initialize map
|
||||
*/
|
||||
function init() {
|
||||
var url = '//maps.googleapis.com/maps/api/js?' + ((ns.config.gkey != null) ? ('key=' + ns.config.gkey + '&') : '') + 'callback=uLogger.mapAPI.gmaps.setLoaded';
|
||||
ns.addScript(url, 'mapapi_gmaps');
|
||||
if (!isLoaded) {
|
||||
throw new Error("Google Maps API not ready");
|
||||
}
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start map engine when loaded
|
||||
*/
|
||||
function start() {
|
||||
if (authError) {
|
||||
gm_authFailure();
|
||||
return;
|
||||
}
|
||||
google.maps.visualRefresh = true;
|
||||
// noinspection JSValidateTypes
|
||||
polyOptions = {
|
||||
strokeColor: ns.config.strokeColor,
|
||||
strokeOpacity: ns.config.strokeOpacity,
|
||||
strokeWeight: ns.config.strokeWeight
|
||||
};
|
||||
// noinspection JSValidateTypes
|
||||
mapOptions = {
|
||||
center: new google.maps.LatLng(init_latitude, init_longitude),
|
||||
center: new google.maps.LatLng(ns.config.init_latitude, ns.config.init_longitude),
|
||||
zoom: 8,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
||||
scaleControl: true
|
||||
};
|
||||
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
|
||||
}
|
||||
function cleanup() {
|
||||
map = undefined;
|
||||
polies = undefined;
|
||||
markers = undefined;
|
||||
popups = undefined;
|
||||
popup = undefined;
|
||||
polyOptions = undefined;
|
||||
mapOptions = undefined;
|
||||
document.getElementById('map-canvas').innerHTML = '';
|
||||
}
|
||||
map = new google.maps.Map(ns.ui.map, mapOptions);
|
||||
}
|
||||
|
||||
function displayTrack(xml, update) {
|
||||
altitudes = {};
|
||||
/**
|
||||
* Clean up API
|
||||
*/
|
||||
function cleanup() {
|
||||
polies = [];
|
||||
markers = [];
|
||||
popups = [];
|
||||
map = null;
|
||||
polyOptions = null;
|
||||
mapOptions = null;
|
||||
popup = null;
|
||||
ns.clearMapCanvas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display track
|
||||
* @param {HTMLCollection} positions XML element
|
||||
* @param {boolean} update Should fit bounds if true
|
||||
*/
|
||||
function displayTrack(positions, update) {
|
||||
var totalMeters = 0;
|
||||
var totalSeconds = 0;
|
||||
// init polyline
|
||||
@ -62,27 +108,26 @@ function displayTrack(xml, update) {
|
||||
poly.setMap(map);
|
||||
var path = poly.getPath();
|
||||
var latlngbounds = new google.maps.LatLngBounds();
|
||||
var positions = xml.getElementsByTagName('position');
|
||||
var posLen = positions.length;
|
||||
for (var i = 0; i < posLen; i++) {
|
||||
var p = parsePosition(positions[i], i);
|
||||
var p = ns.parsePosition(positions[i], i);
|
||||
totalMeters += p.distance;
|
||||
totalSeconds += p.seconds;
|
||||
p.totalMeters = totalMeters;
|
||||
p.totalSeconds = totalSeconds;
|
||||
p.coordinates = new google.maps.LatLng(p.latitude, p.longitude);
|
||||
// set marker
|
||||
setMarker(p, i, posLen);
|
||||
// update polyline
|
||||
path.push(p.coordinates);
|
||||
latlngbounds.extend(p.coordinates);
|
||||
var coordinates = new google.maps.LatLng(p.latitude, p.longitude);
|
||||
path.push(coordinates);
|
||||
latlngbounds.extend(coordinates);
|
||||
}
|
||||
if (update) {
|
||||
map.fitBounds(latlngbounds);
|
||||
if (i == 1) {
|
||||
if (i === 1) {
|
||||
// only one point, zoom out
|
||||
zListener =
|
||||
google.maps.event.addListenerOnce(map, 'bounds_changed', function (event) {
|
||||
var zListener =
|
||||
google.maps.event.addListenerOnce(map, 'bounds_changed', function () {
|
||||
if (this.getZoom()) {
|
||||
this.setZoom(15);
|
||||
}
|
||||
@ -92,117 +137,160 @@ function displayTrack(xml, update) {
|
||||
}
|
||||
polies.push(poly);
|
||||
|
||||
updateSummary(p.timestamp, totalMeters, totalSeconds);
|
||||
if (p.tid != trackid) {
|
||||
trackid = p.tid;
|
||||
setTrack(trackid);
|
||||
ns.updateSummary(p.timestamp, totalMeters, totalSeconds);
|
||||
if (p.tid !== ns.config.trackid) {
|
||||
ns.config.trackid = p.tid;
|
||||
ns.setTrack(ns.config.trackid);
|
||||
}
|
||||
if (document.getElementById('bottom').style.display == 'block') {
|
||||
// update altitudes chart
|
||||
chart.clearChart();
|
||||
displayChart();
|
||||
ns.updateChart();
|
||||
}
|
||||
}
|
||||
|
||||
function clearMap() {
|
||||
/**
|
||||
* Clear map
|
||||
*/
|
||||
function clearMap() {
|
||||
if (polies) {
|
||||
for (var i = 0; i < polies.length; i++) {
|
||||
polies[i].setMap(null);
|
||||
}
|
||||
}
|
||||
if (markers) {
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
google.maps.event.removeListener(popups[i].listener);
|
||||
popups[i].setMap(null);
|
||||
markers[i].setMap(null);
|
||||
for (var j = 0; j < markers.length; j++) {
|
||||
google.maps.event.removeListener(popups[j].listener);
|
||||
popups[j].setMap(null);
|
||||
markers[j].setMap(null);
|
||||
}
|
||||
}
|
||||
markers.length = 0;
|
||||
polies.length = 0;
|
||||
popups.lentgth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function setMarker(p, i, posLen) {
|
||||
/**
|
||||
* Set marker
|
||||
* @param {uLogger.Position} pos
|
||||
* @param {number} id
|
||||
* @param {number} posLen
|
||||
*/
|
||||
function setMarker(pos, id, posLen) {
|
||||
// marker
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: new google.maps.LatLng(p.latitude, p.longitude),
|
||||
title: (new Date(p.timestamp * 1000)).toLocaleString()
|
||||
position: new google.maps.LatLng(pos.latitude, pos.longitude),
|
||||
title: (new Date(pos.timestamp * 1000)).toLocaleString(),
|
||||
map: map
|
||||
});
|
||||
if (latest == 1) { marker.setIcon('images/marker-red.png') }
|
||||
else if (i == 0) { marker.setIcon('images/marker-green.png') }
|
||||
else if (i == posLen - 1) { marker.setIcon('images/marker-red.png') }
|
||||
else { marker.setIcon('images/marker-white.png') }
|
||||
if (ns.isLatest()) {
|
||||
marker.setIcon('images/marker-red.png');
|
||||
} else if (id === 0) {
|
||||
marker.setIcon('images/marker-green.png');
|
||||
} else if (id === posLen - 1) {
|
||||
marker.setIcon('images/marker-red.png');
|
||||
} else {
|
||||
marker.setIcon('images/marker-white.png');
|
||||
}
|
||||
// popup
|
||||
var content = getPopupHtml(p, i, posLen);
|
||||
var content = ns.getPopupHtml(pos, id, posLen);
|
||||
popup = new google.maps.InfoWindow();
|
||||
popup.listener = google.maps.event.addListener(marker, 'click', (function (marker, content) {
|
||||
// noinspection JSUndefinedPropertyAssignment
|
||||
popup.listener = google.maps.event.addListener(marker, 'click', (function (_marker, _content) {
|
||||
return function () {
|
||||
popup.setContent(content);
|
||||
popup.open(map, marker);
|
||||
if (document.getElementById('bottom').style.display == 'block') {
|
||||
var index = 0;
|
||||
for (var key in altitudes) {
|
||||
if (altitudes.hasOwnProperty(key) && key == i) {
|
||||
chart.setSelection([{ row: index, column: null }]);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
popup.setContent(_content);
|
||||
popup.open(map, _marker);
|
||||
ns.chartShowPosition(id);
|
||||
}
|
||||
})(marker, content));
|
||||
markers.push(marker);
|
||||
popups.push(popup);
|
||||
}
|
||||
}
|
||||
|
||||
function addChartEvent(chart, data) {
|
||||
/**
|
||||
* Add listener on chart to show position on map
|
||||
* @param {google.visualization.LineChart} chart
|
||||
* @param {google.visualization.DataTable} data
|
||||
*/
|
||||
function addChartEvent(chart, data) {
|
||||
google.visualization.events.addListener(chart, 'select', function () {
|
||||
if (popup) { popup.close(); clearTimeout(altTimeout); }
|
||||
if (popup) { popup.close(); clearTimeout(timeoutHandle); }
|
||||
var selection = chart.getSelection()[0];
|
||||
if (selection) {
|
||||
var id = data.getValue(selection.row, 0) - 1;
|
||||
var icon = markers[id].getIcon();
|
||||
markers[id].setIcon('images/marker-gold.png');
|
||||
altTimeout = setTimeout(function () { markers[id].setIcon(icon); }, 2000);
|
||||
timeoutHandle = setTimeout(function () { markers[id].setIcon(icon); }, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//((52.20105108685229, 20.789387865580238), (52.292069558807135, 21.172192736185707))
|
||||
function getBounds() {
|
||||
/**
|
||||
* Get map bounds
|
||||
* eg. ((52.20105108685229, 20.789387865580238), (52.292069558807135, 21.172192736185707))
|
||||
* @returns {number[]} Bounds
|
||||
*/
|
||||
function getBounds() {
|
||||
var bounds = map.getBounds();
|
||||
var lat_sw = bounds.getSouthWest().lat();
|
||||
var lon_sw = bounds.getSouthWest().lng();
|
||||
var lat_ne = bounds.getNorthEast().lat();
|
||||
var lon_ne = bounds.getNorthEast().lng();
|
||||
return [lon_sw, lat_sw, lon_ne, lat_ne];
|
||||
}
|
||||
}
|
||||
|
||||
function zoomToExtent() {
|
||||
/**
|
||||
* Zoom to track extent
|
||||
*/
|
||||
function zoomToExtent() {
|
||||
var latlngbounds = new google.maps.LatLngBounds();
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
var coordinates = new google.maps.LatLng(markers[i].position.lat(), markers[i].position.lng());
|
||||
latlngbounds.extend(coordinates);
|
||||
}
|
||||
map.fitBounds(latlngbounds);
|
||||
}
|
||||
}
|
||||
|
||||
function zoomToBounds(b) {
|
||||
var sw = new google.maps.LatLng(b[1], b[0]);
|
||||
var ne = new google.maps.LatLng(b[3], b[2]);
|
||||
var bounds = new google.maps.LatLngBounds(sw, ne);
|
||||
map.fitBounds(bounds);
|
||||
}
|
||||
/**
|
||||
* Zoom to bounds
|
||||
* @param {number[]} bounds
|
||||
*/
|
||||
function zoomToBounds(bounds) {
|
||||
var sw = new google.maps.LatLng(bounds[1], bounds[0]);
|
||||
var ne = new google.maps.LatLng(bounds[3], bounds[2]);
|
||||
var latLngBounds = new google.maps.LatLngBounds(sw, ne);
|
||||
map.fitBounds(latLngBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update size
|
||||
*/
|
||||
function updateSize() {
|
||||
// ignore for google API
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
init: init,
|
||||
setLoaded: function () { isLoaded = true; },
|
||||
cleanup: cleanup,
|
||||
displayTrack: displayTrack,
|
||||
clearMap: clearMap,
|
||||
setMarker: setMarker,
|
||||
addChartEvent: addChartEvent,
|
||||
getBounds: getBounds,
|
||||
zoomToExtent: zoomToExtent,
|
||||
zoomToBounds: zoomToBounds,
|
||||
updateSize: updateSize
|
||||
}
|
||||
|
||||
})(uLogger);
|
||||
|
||||
/**
|
||||
* Callback for Google Maps API
|
||||
* It will be called when authentication fails
|
||||
*/
|
||||
function gm_authFailure() {
|
||||
gm_error = true;
|
||||
message = sprintf(lang['apifailure'], 'Google Maps');
|
||||
message += '<br><br>' + lang['gmauthfailure'];
|
||||
message += '<br><br>' + lang['gmapilink'];
|
||||
showModal(message);
|
||||
};
|
||||
|
||||
function updateSize() {
|
||||
// ignore
|
||||
uLogger.mapAPI.gmaps.authError = true;
|
||||
var message = uLogger.sprintf(uLogger.lang.strings['apifailure'], 'Google Maps');
|
||||
message += '<br><br>' + uLogger.lang.strings['gmauthfailure'];
|
||||
message += '<br><br>' + uLogger.lang.strings['gmapilink'];
|
||||
uLogger.ui.showModal(message);
|
||||
}
|
||||
|
@ -16,27 +16,49 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// openlayers 3+
|
||||
var map;
|
||||
var layerTrack;
|
||||
var layerMarkers;
|
||||
var selectedLayer;
|
||||
var olStyles;
|
||||
var loadedAPI = 'openlayers';
|
||||
|
||||
function init() {
|
||||
// openlayers 3+
|
||||
/** @namespace */
|
||||
var uLogger = uLogger || {};
|
||||
/** @namespace */
|
||||
uLogger.mapAPI = uLogger.mapAPI || {};
|
||||
/** @namespace */
|
||||
uLogger.mapAPI.ol = (function(ns) {
|
||||
|
||||
addCss('css/ol.css', 'ol_css');
|
||||
/** @type {ol.Map} */
|
||||
var map;
|
||||
/** @type {ol.layer.Vector} */
|
||||
var layerTrack;
|
||||
/** @type {ol.layer.Vector} */
|
||||
var layerMarkers;
|
||||
/** @type {ol.layer.Base} */
|
||||
var selectedLayer;
|
||||
/** @type {ol.style.Style|{}} */
|
||||
var olStyles;
|
||||
var name = 'openlayers';
|
||||
|
||||
/**
|
||||
* Initialize map
|
||||
*/
|
||||
function init() {
|
||||
var urls = [];
|
||||
urls.push('//cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList');
|
||||
urls.push('js/ol.js');
|
||||
for (var i = 0; i < urls.length; i++) {
|
||||
ns.addScript(urls[i], 'mapapi_openlayers' + '_' + i);
|
||||
}
|
||||
|
||||
ns.addCss('css/ol.css', 'ol_css');
|
||||
|
||||
var controls = [
|
||||
new ol.control.Zoom(),
|
||||
new ol.control.Rotate(),
|
||||
new ol.control.ScaleLine(),
|
||||
new ol.control.ZoomToExtent({ label: getExtentImg() }),
|
||||
new ol.control.ZoomToExtent({label: getExtentImg()})
|
||||
];
|
||||
|
||||
var view = new ol.View({
|
||||
center: ol.proj.fromLonLat([init_longitude, init_latitude]),
|
||||
center: ol.proj.fromLonLat([ns.config.init_longitude, ns.config.init_latitude]),
|
||||
zoom: 8
|
||||
});
|
||||
|
||||
@ -56,9 +78,9 @@ function init() {
|
||||
selectedLayer = osm;
|
||||
|
||||
// add extra layers
|
||||
for (var layerName in ol_layers) {
|
||||
if (ol_layers.hasOwnProperty(layerName)) {
|
||||
var layerUrl = ol_layers[layerName];
|
||||
for (var layerName in ns.config.ol_layers) {
|
||||
if (ns.config.ol_layers.hasOwnProperty(layerName)) {
|
||||
var layerUrl = ns.config.ol_layers[layerName];
|
||||
var ol_layer = new ol.layer.Tile({
|
||||
name: layerName,
|
||||
visible: false,
|
||||
@ -73,8 +95,8 @@ function init() {
|
||||
// init layers
|
||||
var lineStyle = new ol.style.Style({
|
||||
stroke: new ol.style.Stroke({
|
||||
color: hexToRGBA(strokeColor, strokeOpacity),
|
||||
width: strokeWeight
|
||||
color: ns.hexToRGBA(ns.config.strokeColor, ns.config.strokeOpacity),
|
||||
width: ns.config.strokeWeight
|
||||
})
|
||||
});
|
||||
layerTrack = new ol.layer.Vector({
|
||||
@ -94,20 +116,20 @@ function init() {
|
||||
// styles
|
||||
olStyles = {};
|
||||
var iconRed = new ol.style.Icon({
|
||||
anchor: [ 0.5, 1 ],
|
||||
anchor: [0.5, 1],
|
||||
src: 'images/marker-red.png'
|
||||
});
|
||||
var iconGreen = new ol.style.Icon({
|
||||
anchor: [ 0.5, 1 ],
|
||||
anchor: [0.5, 1],
|
||||
src: 'images/marker-green.png'
|
||||
});
|
||||
var iconWhite = new ol.style.Icon({
|
||||
anchor: [ 0.5, 1 ],
|
||||
anchor: [0.5, 1],
|
||||
opacity: 0.7,
|
||||
src: 'images/marker-white.png'
|
||||
});
|
||||
var iconGold = new ol.style.Icon({
|
||||
anchor: [ 0.5, 1 ],
|
||||
anchor: [0.5, 1],
|
||||
src: 'images/marker-gold.png'
|
||||
});
|
||||
olStyles['red'] = new ol.style.Style({
|
||||
@ -127,7 +149,7 @@ function init() {
|
||||
var popupContainer = document.createElement('div');
|
||||
popupContainer.id = 'popup';
|
||||
popupContainer.className = 'ol-popup';
|
||||
document.getElementsByTagName('body')[0].appendChild(popupContainer);
|
||||
document.body.appendChild(popupContainer);
|
||||
var popupCloser = document.createElement('a');
|
||||
popupCloser.id = 'popup-closer';
|
||||
popupCloser.className = 'ol-popup-closer';
|
||||
@ -145,53 +167,43 @@ function init() {
|
||||
}
|
||||
});
|
||||
|
||||
popupCloser.onclick = function() {
|
||||
popupCloser.onclick = function () {
|
||||
// eslint-disable-next-line no-undefined
|
||||
popup.setPosition(undefined);
|
||||
popupCloser.blur();
|
||||
return false;
|
||||
};
|
||||
|
||||
// add click handler to map to show popup
|
||||
map.on('click', function(e) {
|
||||
map.on('click', function (e) {
|
||||
var coordinate = e.coordinate;
|
||||
var feature = map.forEachFeatureAtPixel(e.pixel,
|
||||
function(feature, layer) {
|
||||
if (layer.get('name') == 'Markers') {
|
||||
return feature;
|
||||
function (_feature, _layer) {
|
||||
if (_layer.get('name') === 'Markers') {
|
||||
return _feature;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (feature) {
|
||||
var p = feature.get('p');
|
||||
var i = feature.getId();
|
||||
var pos = feature.get('p');
|
||||
var id = feature.getId();
|
||||
var posLen = feature.get('posLen');
|
||||
// popup show
|
||||
popup.setPosition(coordinate);
|
||||
popupContent.innerHTML = getPopupHtml(p, i, posLen);
|
||||
popupContent.innerHTML = ns.getPopupHtml(pos, id, posLen);
|
||||
map.addOverlay(popup);
|
||||
if (document.getElementById('bottom').style.display == 'block') {
|
||||
var index = 0;
|
||||
for (var key in altitudes) {
|
||||
if (altitudes.hasOwnProperty(key) && key == i) {
|
||||
chart.setSelection([{ row: index, column: null }]);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
ns.chartShowPosition(id);
|
||||
} else {
|
||||
// popup destroy
|
||||
// eslint-disable-next-line no-undefined
|
||||
popup.setPosition(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
// change mouse cursor when over marker
|
||||
map.on('pointermove', function(e) {
|
||||
var hit = map.forEachFeatureAtPixel(e.pixel, function(feature, layer) {
|
||||
if (layer.get('name') == 'Markers') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
map.on('pointermove', function (e) {
|
||||
var hit = map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
|
||||
return layer.get('name') === 'Markers';
|
||||
});
|
||||
if (hit) {
|
||||
this.getTargetElement().style.cursor = 'pointer';
|
||||
@ -204,7 +216,7 @@ function init() {
|
||||
var switcher = document.createElement('div');
|
||||
switcher.id = 'switcher';
|
||||
switcher.className = 'ol-control';
|
||||
document.getElementsByTagName('body')[0].appendChild(switcher);
|
||||
document.body.appendChild(switcher);
|
||||
var switcherContent = document.createElement('div');
|
||||
switcherContent.id = 'switcher-content';
|
||||
switcherContent.className = 'ol-layerswitcher';
|
||||
@ -232,9 +244,9 @@ function init() {
|
||||
});
|
||||
|
||||
function switchLayer() {
|
||||
var layerName = this.value;
|
||||
var targetName = this.value;
|
||||
map.getLayers().forEach(function (layer) {
|
||||
if (layer.get('name') === layerName) {
|
||||
if (layer.get('name') === targetName) {
|
||||
if (layer.get('type') === 'data') {
|
||||
if (layer.getVisible()) {
|
||||
layer.setVisible(false);
|
||||
@ -246,10 +258,9 @@ function init() {
|
||||
selectedLayer = layer;
|
||||
layer.setVisible(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
var switcherButton = document.createElement('button');
|
||||
var layerImg = document.createElement('img');
|
||||
@ -257,7 +268,8 @@ function init() {
|
||||
layerImg.style.width = '60%';
|
||||
switcherButton.appendChild(layerImg);
|
||||
|
||||
var switcherHandle = function() {
|
||||
// eslint-disable-next-line func-style
|
||||
var switcherHandle = function () {
|
||||
var el = document.getElementById('switcher');
|
||||
if (el.style.display === 'block') {
|
||||
el.style.display = 'none';
|
||||
@ -277,29 +289,34 @@ function init() {
|
||||
element: element
|
||||
});
|
||||
map.addControl(switcherControl);
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
map = undefined;
|
||||
layerTrack = undefined;
|
||||
layerMarkers = undefined;
|
||||
selectedLayer = undefined;
|
||||
olStyles = undefined;
|
||||
removeElementById('popup');
|
||||
removeElementById('switcher');
|
||||
document.getElementById('map-canvas').innerHTML = '';
|
||||
}
|
||||
/**
|
||||
* Clean up API
|
||||
*/
|
||||
function cleanup() {
|
||||
map = null;
|
||||
layerTrack = null;
|
||||
layerMarkers = null;
|
||||
selectedLayer = null;
|
||||
olStyles = null;
|
||||
ns.removeElementById('popup');
|
||||
ns.removeElementById('switcher');
|
||||
ns.clearMapCanvas();
|
||||
}
|
||||
|
||||
|
||||
function displayTrack(xml, update) {
|
||||
altitudes = {};
|
||||
/**
|
||||
* Display track
|
||||
* @param {HTMLCollection} positions XML element
|
||||
* @param {boolean} update Should fit bounds if true
|
||||
*/
|
||||
function displayTrack(positions, update) {
|
||||
var totalMeters = 0;
|
||||
var totalSeconds = 0;
|
||||
var points = [];
|
||||
var positions = xml.getElementsByTagName('position');
|
||||
var posLen = positions.length;
|
||||
for (var i = 0; i < posLen; i++) {
|
||||
var p = parsePosition(positions[i], i);
|
||||
var p = ns.parsePosition(positions[i], i);
|
||||
totalMeters += p.distance;
|
||||
totalSeconds += p.seconds;
|
||||
p.totalMeters = totalMeters;
|
||||
@ -313,7 +330,7 @@ function displayTrack(xml, update) {
|
||||
var lineString = new ol.geom.LineString(points);
|
||||
|
||||
var lineFeature = new ol.Feature({
|
||||
geometry: lineString,
|
||||
geometry: lineString
|
||||
});
|
||||
|
||||
layerTrack.getSource().addFeature(lineFeature);
|
||||
@ -341,66 +358,82 @@ function displayTrack(xml, update) {
|
||||
});
|
||||
map.addControl(zoomToExtentControl);
|
||||
|
||||
updateSummary(p.timestamp, totalMeters, totalSeconds);
|
||||
if (p.tid != trackid) {
|
||||
trackid = p.tid;
|
||||
setTrack(trackid);
|
||||
ns.updateSummary(p.timestamp, totalMeters, totalSeconds);
|
||||
if (p.tid !== ns.config.trackid) {
|
||||
ns.config.trackid = p.tid;
|
||||
ns.setTrack(ns.config.trackid);
|
||||
}
|
||||
if (document.getElementById('bottom').style.display == 'block') {
|
||||
// update altitudes chart
|
||||
chart.clearChart();
|
||||
displayChart();
|
||||
ns.updateChart();
|
||||
}
|
||||
}
|
||||
|
||||
function clearMap() {
|
||||
/**
|
||||
* Clear map
|
||||
*/
|
||||
function clearMap() {
|
||||
if (layerTrack) {
|
||||
layerTrack.getSource().clear();
|
||||
}
|
||||
if (layerMarkers) {
|
||||
layerMarkers.getSource().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setMarker(p, i, posLen) {
|
||||
/**
|
||||
* Set marker
|
||||
* @param {uLogger.Position} pos
|
||||
* @param {number} id
|
||||
* @param {number} posLen
|
||||
*/
|
||||
function setMarker(pos, id, posLen) {
|
||||
// marker
|
||||
var marker = new ol.Feature({
|
||||
geometry: new ol.geom.Point(ol.proj.fromLonLat([p.longitude, p.latitude]))
|
||||
geometry: new ol.geom.Point(ol.proj.fromLonLat([pos.longitude, pos.latitude]))
|
||||
});
|
||||
|
||||
if (latest == 1) {
|
||||
var iconStyle = olStyles['red'];
|
||||
} else if (i == 0) {
|
||||
var iconStyle = olStyles['green'];
|
||||
} else if (i == posLen - 1) {
|
||||
var iconStyle = olStyles['red'];
|
||||
var iconStyle;
|
||||
if (ns.isLatest()) {
|
||||
iconStyle = olStyles['red'];
|
||||
} else if (id === 0) {
|
||||
iconStyle = olStyles['green'];
|
||||
} else if (id === posLen - 1) {
|
||||
iconStyle = olStyles['red'];
|
||||
} else {
|
||||
var iconStyle = olStyles['white'];
|
||||
iconStyle = olStyles['white'];
|
||||
}
|
||||
marker.setStyle(iconStyle);
|
||||
marker.setId(i);
|
||||
marker.set('p', p);
|
||||
marker.setId(id);
|
||||
marker.set('p', pos);
|
||||
marker.set('posLen', posLen);
|
||||
layerMarkers.getSource().addFeature(marker);
|
||||
}
|
||||
}
|
||||
|
||||
function addChartEvent(chart, data) {
|
||||
/**
|
||||
* Add listener on chart to show position on map
|
||||
* @param {google.visualization.LineChart} chart
|
||||
* @param {google.visualization.DataTable} data
|
||||
*/
|
||||
function addChartEvent(chart, data) {
|
||||
google.visualization.events.addListener(chart, 'select', function () {
|
||||
var selection = chart.getSelection()[0];
|
||||
if (selection) {
|
||||
var id = data.getValue(selection.row, 0) - 1;
|
||||
var marker = layerMarkers.getSource().getFeatureById(id);
|
||||
var url = marker.get('src');
|
||||
var initStyle = marker.getStyle();
|
||||
var iconStyle = olStyles['gold'];
|
||||
marker.setStyle(iconStyle);
|
||||
altTimeout = setTimeout(function () { marker.setStyle(initStyle); }, 2000);
|
||||
setTimeout(function () {
|
||||
marker.setStyle(initStyle);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//20.597985430276808,52.15547181298076,21.363595171488573,52.33750879522563
|
||||
function getBounds() {
|
||||
/**
|
||||
* Get map bounds
|
||||
* eg. (20.597985430276808, 52.15547181298076, 21.363595171488573, 52.33750879522563)
|
||||
* @returns {number[]} Bounds
|
||||
*/
|
||||
function getBounds() {
|
||||
var extent = map.getView().calculateExtent(map.getSize());
|
||||
var bounds = ol.proj.transformExtent(extent, 'EPSG:900913', 'EPSG:4326');
|
||||
var lon_sw = bounds[0];
|
||||
@ -408,24 +441,54 @@ function getBounds() {
|
||||
var lon_ne = bounds[2];
|
||||
var lat_ne = bounds[3];
|
||||
return [lon_sw, lat_sw, lon_ne, lat_ne];
|
||||
}
|
||||
}
|
||||
|
||||
function zoomToExtent() {
|
||||
map.getView().fit(layerMarkers.getSource().getExtent())
|
||||
}
|
||||
/**
|
||||
* Zoom to track extent
|
||||
*/
|
||||
function zoomToExtent() {
|
||||
map.getView().fit(layerMarkers.getSource().getExtent());
|
||||
}
|
||||
|
||||
function zoomToBounds(b) {
|
||||
var bounds = ol.proj.transformExtent(b, 'EPSG:4326', 'EPSG:900913');
|
||||
map.getView().fit(bounds);
|
||||
}
|
||||
/**
|
||||
* Zoom to bounds
|
||||
* @param {number[]} bounds
|
||||
*/
|
||||
function zoomToBounds(bounds) {
|
||||
var extent = ol.proj.transformExtent(bounds, 'EPSG:4326', 'EPSG:900913');
|
||||
map.getView().fit(extent);
|
||||
}
|
||||
|
||||
function updateSize() {
|
||||
/**
|
||||
* Update size
|
||||
*/
|
||||
function updateSize() {
|
||||
map.updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
function getExtentImg() {
|
||||
/**
|
||||
* Get extent image
|
||||
* @returns {HTMLImageElement}
|
||||
*/
|
||||
function getExtentImg() {
|
||||
var extentImg = document.createElement('img');
|
||||
extentImg.src = 'images/extent.svg';
|
||||
extentImg.style.width = '60%';
|
||||
return extentImg;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
init: init,
|
||||
cleanup: cleanup,
|
||||
displayTrack: displayTrack,
|
||||
clearMap: clearMap,
|
||||
setMarker: setMarker,
|
||||
addChartEvent: addChartEvent,
|
||||
getBounds: getBounds,
|
||||
zoomToExtent: zoomToExtent,
|
||||
zoomToBounds: zoomToBounds,
|
||||
updateSize: updateSize
|
||||
}
|
||||
|
||||
})(uLogger);
|
||||
|
1332
js/main.js
1332
js/main.js
File diff suppressed because it is too large
Load Diff
89
js/pass.js
89
js/pass.js
@ -16,63 +16,62 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function changePass() {
|
||||
var form = '<form id="passForm" method="post" onsubmit="submitPass(); return false">';
|
||||
form += '<label><b>' + lang['oldpassword'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="oldpass" required>';
|
||||
form += '<label><b>' + lang['newpassword'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + lang['newpasswordrepeat'] + '</b></label><input type="password" placeholder="' + lang['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<button type="button" onclick="removeModal()">' + lang['cancel'] + '</button><button type="submit">' + lang['submit'] + '</button>';
|
||||
form += '</form>';
|
||||
showModal(form);
|
||||
}
|
||||
/** @namespace */
|
||||
var uLogger = window.uLogger || {};
|
||||
(function (ns) {
|
||||
|
||||
function submitPass() {
|
||||
/**
|
||||
* Show change password dialog
|
||||
*/
|
||||
function changePass() {
|
||||
var form = '<form id="passForm" method="post" onsubmit="uLogger.submitPass(); return false">';
|
||||
form += '<label><b>' + ns.lang.strings['oldpassword'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="oldpass" required>';
|
||||
form += '<label><b>' + ns.lang.strings['newpassword'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass" required>';
|
||||
form += '<label><b>' + ns.lang.strings['newpasswordrepeat'] + '</b></label><input type="password" placeholder="' + ns.lang.strings['passwordenter'] + '" name="pass2" required>';
|
||||
form += '<button type="button" onclick="uLogger.ui.removeModal()">' + ns.lang.strings['cancel'] + '</button><button type="submit">' + ns.lang.strings['submit'] + '</button>';
|
||||
form += '</form>';
|
||||
ns.ui.showModal(form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit password form
|
||||
*/
|
||||
function submitPass() {
|
||||
var form = document.getElementById('passForm');
|
||||
var oldpass = form.elements['oldpass'].value;
|
||||
var pass = form.elements['pass'].value;
|
||||
var pass2 = form.elements['pass2'].value;
|
||||
if (!oldpass || !pass || !pass2) {
|
||||
alert(lang['allrequired']);
|
||||
alert(ns.lang.strings['allrequired']);
|
||||
return;
|
||||
}
|
||||
if (pass != pass2) {
|
||||
alert(lang['passnotmatch']);
|
||||
if (pass !== pass2) {
|
||||
alert(ns.lang.strings['passnotmatch']);
|
||||
return;
|
||||
}
|
||||
if (!pass_regex.test(pass)) {
|
||||
alert(lang['passlenmin'] + '\n' + lang['passrules']);
|
||||
if (!ns.config.pass_regex.test(pass)) {
|
||||
alert(ns.lang.strings['passlenmin'] + '\n' + ns.lang.strings['passrules']);
|
||||
return;
|
||||
}
|
||||
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4) {
|
||||
var error = true;
|
||||
var message = '';
|
||||
if (xhr.status == 200) {
|
||||
var xml = xhr.responseXML;
|
||||
if (xml) {
|
||||
var root = xml.getElementsByTagName('root');
|
||||
if (root.length && getNode(root[0], 'error') == 0) {
|
||||
removeModal();
|
||||
alert(lang['actionsuccess']);
|
||||
error = false;
|
||||
} else if (root.length) {
|
||||
errorMsg = getNode(root[0], 'message');
|
||||
if (errorMsg) { message = errorMsg; }
|
||||
ns.post('utils/changepass.php',
|
||||
{
|
||||
oldpass: oldpass,
|
||||
pass: pass
|
||||
},
|
||||
{
|
||||
success: function () {
|
||||
ns.ui.removeModal();
|
||||
alert(ns.lang.strings['actionsuccess']);
|
||||
},
|
||||
fail: function (message) {
|
||||
alert(ns.lang.strings['actionfailure'] + '\n' + message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
alert(lang['actionfailure'] + '\n' + message);
|
||||
}
|
||||
xhr = null;
|
||||
}
|
||||
}
|
||||
xhr.open('POST', 'utils/changepass.php', true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var params = 'oldpass=' + encodeURIComponent(oldpass) + '&pass=' + encodeURIComponent(pass);
|
||||
params = params.replace(/%20/g, '+');
|
||||
xhr.send(params);
|
||||
return;
|
||||
}
|
||||
|
||||
// exports
|
||||
ns.changePass = changePass;
|
||||
ns.submitPass = submitPass;
|
||||
|
||||
})(uLogger);
|
||||
|
127
js/track.js
127
js/track.js
@ -16,91 +16,94 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function editTrack() {
|
||||
var userForm = document.getElementsByName('user')[0];
|
||||
var trackUser = (userForm !== undefined) ? userForm.options[userForm.selectedIndex].text : auth;
|
||||
if (trackUser != auth && !admin) {
|
||||
alert(lang['owntrackswarn']);
|
||||
/** @namespace */
|
||||
var uLogger = window.uLogger || {};
|
||||
(function (ns) {
|
||||
|
||||
/**
|
||||
* Show edit track dialog
|
||||
*/
|
||||
function editTrack() {
|
||||
var userForm = ns.ui.userSelect;
|
||||
var trackUser = (userForm) ? userForm.options[userForm.selectedIndex].text : ns.config.auth;
|
||||
if (trackUser !== ns.config.auth && !ns.config.admin) {
|
||||
alert(ns.lang.strings['owntrackswarn']);
|
||||
return;
|
||||
}
|
||||
var trackForm = document.getElementsByName('track')[0];
|
||||
var trackForm = ns.ui.trackSelect;
|
||||
if (trackForm.selectedIndex < 0) {
|
||||
return;
|
||||
}
|
||||
var trackId = trackForm.options[trackForm.selectedIndex].value;
|
||||
var trackName = trackForm.options[trackForm.selectedIndex].text;
|
||||
var message = '<div style="float:left">' + sprintf(lang['editingtrack'], '<b>' + htmlEncode(trackName) + '</b>') + '</div>';
|
||||
message += '<div class="red-button"><b><a href="javascript:void(0);" onclick="submitTrack(\'delete\'); return false">' + lang['deltrack'] + '</a></b></div>';
|
||||
var message = '<div style="float:left">' + ns.sprintf(ns.lang.strings['editingtrack'], '<b>' + ns.htmlEncode(trackName) + '</b>') + '</div>';
|
||||
message += '<div class="red-button"><b><a href="javascript:void(0);" onclick="uLogger.submitTrack(\'delete\'); return false">' + ns.lang.strings['deltrack'] + '</a></b></div>';
|
||||
message += '<div style="clear: both; padding-bottom: 1em;"></div>';
|
||||
|
||||
var form = '<form id="trackForm" method="post" onsubmit="submitTrack(\'update\'); return false">';
|
||||
var form = '<form id="trackForm" method="post" onsubmit="uLogger.submitTrack(\'update\'); return false">';
|
||||
form += '<input type="hidden" name="trackid" value="' + trackId + '">';
|
||||
form += '<label><b>' + lang['trackname'] + '</b></label><input type="text" placeholder="' + lang['trackname'] + '" name="trackname" value="' + htmlEncode(trackName) + '" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="removeModal()">' + lang['cancel'] + '</button><button type="submit">' + lang['submit'] + '</button></div>';
|
||||
form += '<label><b>' + ns.lang.strings['trackname'] + '</b></label><input type="text" placeholder="' + ns.lang.strings['trackname'] + '" name="trackname" value="' + ns.htmlEncode(trackName) + '" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="uLogger.ui.removeModal()">' + ns.lang.strings['cancel'] + '</button><button type="submit">' + ns.lang.strings['submit'] + '</button></div>';
|
||||
form += '</form>';
|
||||
showModal(message + form);
|
||||
}
|
||||
ns.ui.showModal(message + form);
|
||||
}
|
||||
|
||||
function confirmedDelete(name) {
|
||||
return confirm(sprintf(lang['trackdelwarn'], '"' + name + '"'));
|
||||
}
|
||||
/**
|
||||
* Show confirmation dialog
|
||||
* @param {string} name
|
||||
* @returns {boolean} True if confirmed
|
||||
*/
|
||||
function confirmedDelete(name) {
|
||||
return confirm(ns.sprintf(ns.lang.strings['trackdelwarn'], '"' + name + '"'));
|
||||
}
|
||||
|
||||
function submitTrack(action) {
|
||||
/**
|
||||
* Submit form dialog
|
||||
* @param action
|
||||
*/
|
||||
function submitTrack(action) {
|
||||
var form = document.getElementById('trackForm');
|
||||
var trackId = parseInt(form.elements['trackid'].value);
|
||||
var trackName = form.elements['trackname'].value.trim();
|
||||
if (isNaN(trackId)) {
|
||||
alert(lang['allrequired']);
|
||||
alert(ns.lang.strings['allrequired']);
|
||||
return;
|
||||
}
|
||||
if (action != 'delete') {
|
||||
if (action !== 'delete') {
|
||||
if (!trackName) {
|
||||
alert(lang['allrequired']);
|
||||
alert(ns.lang.strings['allrequired']);
|
||||
return;
|
||||
}
|
||||
} else if (!confirmedDelete(trackName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns.post('utils/handletrack.php',
|
||||
{
|
||||
action: action,
|
||||
trackid: trackId,
|
||||
trackname: trackName
|
||||
},
|
||||
{
|
||||
success: function () {
|
||||
ns.ui.removeModal();
|
||||
alert(ns.lang.strings['actionsuccess']);
|
||||
var el = ns.ui.trackSelect;
|
||||
if (action === 'delete') {
|
||||
el.remove(el.selectedIndex);
|
||||
ns.map.clearMap();
|
||||
ns.selectTrack();
|
||||
} else {
|
||||
if (!confirmedDelete(trackName)) {
|
||||
return;
|
||||
el.options[el.selectedIndex].innerHTML = ns.htmlEncode(trackName);
|
||||
}
|
||||
},
|
||||
fail: function (message) {
|
||||
alert(ns.lang.strings['actionfailure'] + '\n' + message);
|
||||
}
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
var error = true;
|
||||
var message = '';
|
||||
if (xhr.status == 200) {
|
||||
var xml = xhr.responseXML;
|
||||
if (xml) {
|
||||
var root = xml.getElementsByTagName('root');
|
||||
if (root.length && getNode(root[0], 'error') == 0) {
|
||||
removeModal();
|
||||
alert(lang['actionsuccess']);
|
||||
var f = document.getElementsByName('track')[0];
|
||||
if (action == 'delete') {
|
||||
// select current track in tracks form
|
||||
f.remove(f.selectedIndex);
|
||||
clearMap();
|
||||
selectTrack(f);
|
||||
} else {
|
||||
f.options[f.selectedIndex].innerHTML = htmlEncode(trackName);
|
||||
});
|
||||
}
|
||||
error = false;
|
||||
} else if (root.length) {
|
||||
errorMsg = getNode(root[0], 'message');
|
||||
if (errorMsg) { message = errorMsg; }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
alert(lang['actionfailure'] + '\n' + message);
|
||||
}
|
||||
xhr = null;
|
||||
}
|
||||
}
|
||||
xhr.open('POST', 'utils/handletrack.php', true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var params = 'action=' + action + '&trackid=' + trackId + '&trackname=' + encodeURIComponent(trackName);
|
||||
params = params.replace(/%20/g, '+');
|
||||
xhr.send(params);
|
||||
return;
|
||||
}
|
||||
|
||||
ns.editTrack = editTrack;
|
||||
ns.submitTrack = submitTrack;
|
||||
|
||||
})(uLogger);
|
||||
|
60
js/typedefs.js
Normal file
60
js/typedefs.js
Normal file
@ -0,0 +1,60 @@
|
||||
/* μlogger
|
||||
*
|
||||
* Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net)
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef uLogger.config
|
||||
* @memberOf uLogger
|
||||
* @type {Object}
|
||||
* @property {number} interval
|
||||
* @property {string} units
|
||||
* @property {string} mapapi
|
||||
* @property {?string} gkey
|
||||
* @property {Object.<string, string>} ol_layers
|
||||
* @property {number} init_latitude
|
||||
* @property {number} init_longitude
|
||||
* @property {boolean} admin
|
||||
* @property {?string} auth
|
||||
* @property {RegExp} pass_regex
|
||||
* @property {number} strokeWeight
|
||||
* @property {string} strokeColor
|
||||
* @property {number} strokeOpacity
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef uLogger.lang
|
||||
* @memberOf uLogger
|
||||
* @type {Object}
|
||||
* @property {Object.<string, string>} strings
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} uLogger.mapAPI.api
|
||||
* @memberOf uLogger
|
||||
* @type {Object}
|
||||
* @property {string} name
|
||||
* @property {function} init
|
||||
* @property {function} cleanup
|
||||
* @property {function(HTMLCollection, boolean)} displayTrack
|
||||
* @property {function} clearMap
|
||||
* @property {function(uLogger.Position, number, number)} setMarker
|
||||
* @property {function} addChartEvent
|
||||
* @property {function} getBounds
|
||||
* @property {function} zoomToExtent
|
||||
* @property {function} zoomToBounds
|
||||
* @property {function} updateSize
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user