aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/index.html7
-rw-r--r--web/js/nms-data.js3
-rw-r--r--web/js/nms-map.js14
-rw-r--r--web/js/nms-time.js150
-rw-r--r--web/js/nms.js273
5 files changed, 197 insertions, 250 deletions
diff --git a/web/index.html b/web/index.html
index 1bb9f91..593452b 100644
--- a/web/index.html
+++ b/web/index.html
@@ -56,8 +56,8 @@
<li><a href="#disco" onclick="setUpdater(handler_disco)">DISCO</a></li>
<li class="divider"> </li>
<li class="dropdown-header">Time</li>
- <li><a href="#" onclick="toggleLayer('nowPickerBox');startNowPicker();">Travel in time</a></li>
- <li><a href="#" onclick="nms.playback.startReplay('2016-03-21T09:00:00','2016-03-27T12:00:00');" title="Replay from opening 120 minutes per second">Replay TG</a></li>
+ <li><a href="#" onclick="toggleLayer('nowPickerBox');nmsTime.startNowPicker();">Travel in time</a></li>
+ <li><a href="#" onclick="nmsTime.replayEvent();" title="Replay from opening 120 minutes per second">Replay event</a></li>
<li class="divider"> </li>
<li class="dropdown-header">View</li>
<li><a href="#" onclick="toggleNightMode()">Toggle Night Mode</a></li>
@@ -235,7 +235,7 @@
<div class="form-group">
<input type="text" class="form-control" placeholder="YYYY-MM-DDThh:mm:ss" id="nowPicker">
<div class="button-group">
- <button class="btn btn-primary" onclick="nms.playback.setNow(document.getElementById('nowPicker').dataset.iso);hideLayer('nowPickerBox');">Travel</button>
+ <button class="btn btn-primary" onclick="nmsTime.setNow(document.getElementById('nowPicker').dataset.iso);hideLayer('nowPickerBox');nmsTime.updateData();">Travel</button>
<button class="btn btn-danger" onclick="startNowPicker(Date.now());nms.playback.setNow(false);nms.playback.play();">Back to reality</button>
<button class="btn btn-info" data-toggle="button" onclick="toggleLayer('nowPickerInfo');">Info</button>
</div>
@@ -301,6 +301,7 @@
<script type="text/javascript" src="js/nms-admin-pane.js"></script>
<script type="text/javascript" src="js/nms-oplog.js"></script>
<script type="text/javascript" src="js/nms-search.js"></script>
+ <script type="text/javascript" src="js/nms-time.js"></script>
<script src="js/jquery.datetimepicker.full.js" type="text/javascript"></script>
<script type="text/javascript">
initNMS();
diff --git a/web/js/nms-data.js b/web/js/nms-data.js
index 14e5fed..e3c4106 100644
--- a/web/js/nms-data.js
+++ b/web/js/nms-data.js
@@ -231,7 +231,8 @@ nmsData._genericUpdater = function(name, cacheok) {
dataType: "json",
success: function (data, textStatus, jqXHR) {
if (nmsData[name] == undefined || nmsData[name]['hash'] != data['hash']) {
- nmsData._last = data['time'];
+ if (name == "ping")
+ nmsData._last = data['time'];
nmsData.old[name] = nmsData[name];
nmsData[name] = data;
nmsMap.drawNow();
diff --git a/web/js/nms-map.js b/web/js/nms-map.js
index ef86102..26782f8 100644
--- a/web/js/nms-map.js
+++ b/web/js/nms-map.js
@@ -180,6 +180,19 @@ nmsMap._resizeEvent = function() {
nmsMap.drawNow = function ()
{
var now = nmsData.now;
+ var ctx = nmsMap._c.top.ctx;
+ if (nmsTime.isRealTime()) {
+ if (!nmsMap._nowCleared) {
+ ctx.save();
+ ctx.scale(this.scale, this.scale);
+ ctx.clearRect(0,0,800,100);
+ ctx.restore();
+ nmsMap._nowCleared = true;
+ nmsMap._lastNow = undefined;
+ }
+ return true;
+ }
+ nmsMap._nowCleared = false;
if(String(now).indexOf('T') == -1) { //If now does not contain 'T' we assume its in epoch format
now = new Date(nmsData.now * 1000);
} else {
@@ -192,7 +205,6 @@ nmsMap.drawNow = function ()
}
nmsMap.stats.nows++;
- var ctx = nmsMap._c.top.ctx;
ctx.save();
ctx.scale(this.scale, this.scale);
ctx.font = (2 * this._settings.fontSize) + "px " + this._settings.fontFace;
diff --git a/web/js/nms-time.js b/web/js/nms-time.js
new file mode 100644
index 0000000..e857956
--- /dev/null
+++ b/web/js/nms-time.js
@@ -0,0 +1,150 @@
+"use strict";
+
+/*
+ * Deals with controlling time.
+ *
+ * More specifically: replaying of past events, fast forwarding, pausing,
+ * etc.
+ *
+ * The interface is a bit bloated at the moment, though.
+ */
+var nmsTime = nmsTime || {
+ _now: undefined,
+ _handle: undefined
+}
+
+nmsTime.replayEvent = function() {
+ throw "Not yet implemented.";
+}
+
+nmsTime.isRealTime = function() {
+ if (nmsTime._now == undefined && nmsTime._handle == undefined)
+ return true;
+ return false;
+}
+
+nmsTime.startNowPicker = function () {
+ $.datetimepicker.setLocale('no');
+ $('#nowPicker').datetimepicker('destroy');
+ var now;
+ if (nmsTime._now == undefined)
+ now = new Date();
+ else
+ now = nmsTime._now;
+ now.setSeconds(0);
+ now.setMilliseconds(0);
+ var datepicker = $('#nowPicker').datetimepicker({
+ value: now,
+ step: 5,
+ mask:false,
+ inline:true,
+ todayButton: true,
+ validateOnBlur:false,
+ dayOfWeekStart:1,
+ maxDate:'+1970/01/01',
+ onSelectDate: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ },
+ onSelectTime: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ },
+ onGenerate: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ }
+ });
+}
+
+nmsTime.setNow = function(now) {
+ var newDate = new Date(now);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ newDate.setMinutes(newDate.getMinutes() - newDate.getMinutes()%5);
+ nmsTime._now = newDate;
+}
+
+nmsTime._updateData = function() {
+ nmsData.now = nmsTime._now.getTime() / 1000;
+}
+
+nmsTime.realTime = function() {
+ nmsTime.stopPlayback();
+ nmsTime._now = undefined;
+ nmsData.now = undefined;
+}
+
+/*
+ * Step a fixed amount of time, measured in minutes.
+ *
+ * Try to align this to whole 5 minutes. It will be enforced in future
+ * backend versions to avoid bloating the cache and thus also stressing the
+ * database
+ */
+nmsTime.step = function(amount) {
+ if (nmsTime._now == null)
+ throw "Stepping without nmsTime._now";
+ if (amount == 0 || amount == undefined)
+ throw "Invalid step";
+ if (nmsTime._now.getTime() + (amount * 1000 * 60 ) > Date.now()) {
+ nmsTime.realTime();
+ return;
+ }
+ nmsTime._now.setMinutes(nmsTime._now.getMinutes() + amount);
+ nmsTime._updateData();
+}
+
+/*
+ * Step based on key-press. Same as step() but stops playback if it's
+ * active and allows you to rewind from a "live" map.
+ */
+nmsTime.stepKey = function(amount) {
+ nmsTime.stopPlayback();
+ if (nmsTime._now == undefined) {
+ nmsTime.setNow(Date.now());
+ }
+ nmsTime.step(amount);
+}
+
+/*
+ * Target of setInterval() when replaying.
+ */
+nmsTime._tick = function() {
+ nmsTime.step(nmsTime._speed);
+}
+
+/*
+ * We now have a time (presumably), start playback.
+ *
+ * Aborts if the time provided is greater than real time.
+ *
+ * Gondul does not _yet_ support fast forwarding into the future.
+ */
+nmsTime.startPlayback = function(speed) {
+ if (nmsTime._handle)
+ nmsTime.stopPlayback();
+ if (nmsTime._now.getTime() > Date.now()) {
+ nmsTime.stopPlayback();
+ return;
+ }
+ nmsTime._speed = speed;
+ nmsTime._handle = setInterval(nmsTime._tick,1000);
+}
+
+nmsTime.togglePause = function() {
+ if (nmsTime._handle) {
+ nmsTime.stopPlayback();
+ } else {
+ if (nmsTime.isRealTime()) {
+ nmsTime.setNow(Date.now());
+ nmsTime._updateData();
+ } else {
+ nmsTime.startPlayback(nmsTime._speed ? nmsTime._speed : 5);
+ }
+ }
+}
+
+nmsTime.stopPlayback = function() {
+ if (nmsTime._handle)
+ clearInterval(nmsTime._handle);
+ nmsTime._handle = undefined;
+}
+
diff --git a/web/js/nms.js b/web/js/nms.js
index eb0942a..9727c09 100644
--- a/web/js/nms.js
+++ b/web/js/nms.js
@@ -11,8 +11,6 @@
* - Move all pure UI stuff into nmsUi: nightMode, vertical mode,
* menushowing,
* - Get rid of "tvmode". As in: complete the merge
- * - Move all time-travel related code out into a separate entity.
- * - Remove nms.now: it belongs in nmsData.
* - nms.timers probably also deserves to die. It used to do a lot more,
* now it's just leftovers.
*/
@@ -21,24 +19,16 @@ var nms = {
get nightMode() { return this._nightMode; },
set nightMode(val) { if (val != this._nightMode) { this._nightMode = val; setNightMode(val); } },
/*
- * FIXME: This should be slightly smarter.
- */
- _now: false,
- get now() { return this._now },
- set now(v) { this._now = v; nmsData.now = v; },
- /*
* Various setInterval() handlers. See nmsTimer() for how they are
* used.
*
* FIXME: Should just stop using these.
*/
timers: {
- playback:false,
tvmode: false
},
menuShowing:true,
- _startTime:0,
get uptime() {
return (Date.now() - this._startTime)/1000;
},
@@ -94,16 +84,6 @@ var nms = {
'Escape':hideWindow,
'?':toggleHelp
},
- /*
- * Playback controllers and variables
- */
- playback:{
- startTime: false,
- stopTime: false,
- playing: false,
- replayTime: 0,
- replayIncrement: 60 * 60
- },
tvmode: {
handlers: [],
currentIndex: 0,
@@ -116,8 +96,8 @@ var nms = {
/*
* Returns a handler object.
*
- * This might seem a bit much for 'setInterval()' etc, but it's really more
- * about self-documentation and predictable ways of configuring timers.
+ * FIXME: This is legacy-stuff, should get rid of it. DO NOT use this for
+ * new code.
*/
function nmsTimer(handler, interval, name, description) {
this.handler = handler;
@@ -174,193 +154,8 @@ function toggleNightMode()
}
/*
- * Parse 'now' from user-input.
- *
- * Should probably just use stringToEpoch() instead, but alas, not yet.
- */
-function parseNow(now)
-{
- if (Date.parse(now)) {
- // Adjust for timezone when converting from epoch (UTC) to string (local)
- var d = new Date(now);
- var timezoneOffset = d.getTimezoneOffset() * -60000;
- var d = new Date(Date.parse(now) - timezoneOffset);
- var str = d.getFullYear() + "-" + ("00" + (parseInt(d.getMonth())+1)).slice(-2) + "-" + ("00" + d.getDate()).slice(-2) + "T";
- str += ("00" + d.getHours()).slice(-2) + ":" + ("00" + d.getMinutes()).slice(-2) + ":" + ("00" + d.getSeconds()).slice(-2);
- return str;
-
- }
- if (now == "")
- return "";
- return false;
-}
-
-/*
- * Convert back and forth between epoch.
- *
- * There's no particular reason why I use seconds instead of javascript
- * microseconds, except to leave the mark of a C coder on this javascript
- * project.
- */
-function stringToEpoch(t)
-{
- var foo = t.toString();
-// foo = foo.replace('T',' ');
- var ret = new Date(Date.parse(foo));
- return parseInt(parseInt(ret.valueOf()) / 1000);
-}
-
-/*
- * Have to pad with zeroes to avoid "17:5:0" instead of the conventional
- * and more readable "17:05:00". I'm sure there's a better way, but this
- * works just fine.
- */
-function epochToString(t)
-{
- // Adjust for timezone when converting from epoch (UTC) to string (local)
- var date = new Date(parseInt(t) * parseInt(1000));
- var timezoneOffset = date.getTimezoneOffset() * -60;
- t = t - timezoneOffset;
-
- date = new Date(parseInt(t) * parseInt(1000));
- var str = date.getFullYear() + "-";
- if (parseInt(date.getMonth()) < 9)
- str += "0";
- str += (parseInt(date.getMonth())+1) + "-";
- if (date.getDate() < 10)
- str += "0";
- str += date.getDate() + "T";
- if (date.getHours() < 10)
- str += "0";
- str += date.getHours() + ":";
- if (date.getMinutes() < 10)
- str += "0";
- str += date.getMinutes() + ":";
- if (date.getSeconds() < 10)
- str += "0";
- str += date.getSeconds();
-
- return str;
-}
-
-function localEpochToString(t) {
- var d = new Date(parseInt(t) * parseInt(1000));
- var timezoneOffset = d.getTimezoneOffset() * -60;
- t = t + timezoneOffset;
-
- return epochToString(t);
-}
-
-/*
- * Start replaying historical data.
- */
-nms.playback.startReplay = function(startTime,stopTime) {
- if(!startTime || !stopTime)
- return false;
-
- nms.playback.pause();
- nms.playback.startTime = stringToEpoch(startTime);
- nms.playback.stopTime = stringToEpoch(stopTime);
- nms.now = epochToString(nms.playback.startTime);
- nms.playback.play();
-};
-
-/*
- * Pause playback
- */
-nms.playback.pause = function() {
- nms.timers.playback.stop();
- nms.playback.playing = false;
-};
-
-/*
- * Start playback
- */
-nms.playback.play = function() {
- nms.playback.tick();
- nms.timers.playback.start();
- nms.playback.playing = true;
-};
-
-/*
- * Toggle playback
- */
-nms.playback.toggle = function() {
- if(nms.playback.playing) {
- nms.playback.pause();
- } else {
- nms.playback.play();
- }
-};
-
-/*
- * Jump to place in time
- */
-nms.playback.setNow = function(now) {
- nms.now = parseNow(now);
-
- nms.playback.stopTime = false;
- nms.playback.startTime = false;
- nms.playback.tick();
-};
-
-/*
- * Step forwards or backwards in timer
- */
-nms.playback.stepTime = function(n)
-{
- var now = getNowEpoch();
- var newtime = parseInt(now) + parseInt(n);
- nms.now = epochToString(parseInt(newtime));
-
- if(!nms.playback.playing)
- nms.playback.tick();
-};
-
-/*
- * Ticker to trigger updates, and advance time if replaying
- *
- * This is run on a timer (nms.timers.tick) every second while unpaused
- */
-nms.playback.tick = function()
-{
- nms.playback.replayTime = getNowEpoch();
-
- // If outside start-/stopTime, remove limits and pause playback
- if (nms.playback.stopTime && (nms.playback.replayTime >= nms.playback.stopTime || nms.playback.replayTime < nms.playback.startTime)) {
- nms.playback.stopTime = false;
- nms.playback.startTime = false;
- nms.playback.pause();
- return;
- }
-
- // If past actual datetime, go live
- if (nms.playback.replayTime > parseInt(Date.now() / 1000)) {
- nms.now = false;
- }
-
- // If we are still replaying, advance time
- if(nms.now !== false && nms.playback.playing) {
- nms.playback.stepTime(nms.playback.replayIncrement);
- }
-};
-
-/*
- * Helper function for safely getting a valid now-epoch
- */
-function getNowEpoch() {
- if (nms.now && nms.now != 0)
- return stringToEpoch(nms.now);
- else
- return parseInt(Date.now() / 1000);
-}
-
-/*
* There are 4 legend-bars. This is a helper-function to set the color and
* description/name for each one. Used from handler init-functions.
- *
- * FIXME: Should be smarter, possibly use a canvas-writer so we can get
- * proper text (e.g.: not black text on dark blue).
*/
function setLegend(x,color,name)
{
@@ -379,7 +174,10 @@ function setLegend(x,color,name)
* Start TV-mode
*
* Loops trough a list of views/updaters at a set interval.
- * Arguments: array of views, interval in seconds, use nightmode, hide menus
+ * Arguments: array of views, interval in seconds
+ *
+ * FIXME: this is getting gradually stripped down from the original, so far
+ * we're not quite there yet with merging it with the regular code paths.
*/
nms.tvmode.start = function(views,interval) {
nms.tvmode.handlers = [];
@@ -413,6 +211,11 @@ nms.tvmode.stop = function() {
}
}
+/*
+ * Used when changing handler to ensure that the new handler is listed in
+ * the anchor. The anchor can contain a comma-separated list of views and
+ * we only overwrite it if the new view isn't present.
+ */
function ensureAnchorHas(view) {
try {
var views = document.location.hash.slice(1);
@@ -424,8 +227,12 @@ function ensureAnchorHas(view) {
document.location.hash = view;
return false;
}
+
/*
* Change map handler (e.g., change from uplink map to ping map)
+ *
+ * stopTv esnures that we don't conflict with the tvmode thing. If a
+ * user-initiated map is selected, tvmode is disabled.
*/
function setUpdater(fo, stopTv = true)
{
@@ -457,6 +264,12 @@ function toggleLayer(layer) {
l.style.display = 'none';
}
+function hideLayer(layer) {
+ var l = document.getElementById(layer);
+ l.style.display = 'none';
+}
+
+
function toggleConnect() {
toggleLayer("linkCanvas");
}
@@ -550,7 +363,7 @@ function getInitialConfig() {
* yet.
*/
function initNMS() {
- nms.timers.playback = new nmsTimer(nms.playback.tick, 1000, "Playback ticker", "Handler used to advance time");
+ // Only used for dev-purposes now. Accessible through nms.uptime.
nms._startTime = Date.now();
// Public
@@ -583,7 +396,6 @@ function initNMS() {
restoreSettings();
nmsMap.init();
detectHandler();
- nms.playback.play();
setupKeyhandler();
nmsSearch.init();
}
@@ -675,23 +487,22 @@ function moveTimeFromKey(e,key)
{
switch(key) {
case 'h':
- nms.playback.stepTime(-3600);
+ nmsTime.stepKey(-60);
break;
case 'j':
- nms.playback.stepTime(-300);
+ nmsTime.stepKey(-5);
break;
case 'k':
- nms.playback.stepTime(300);
+ nmsTime.stepKey(5);
break;
case 'l':
- nms.playback.stepTime(3600);
+ nmsTime.stepKey(60);
break;
case 'p':
- nms.playback.toggle();
+ nmsTime.togglePause();
break;
case 'r':
- nms.playback.setNow();
- nms.playback.play();
+ nmsTime.realTime();
break;
}
return true;
@@ -795,34 +606,6 @@ function restoreSettings()
}
/*
- * Time travel gui
- */
-function startNowPicker(now) {
- $.datetimepicker.setLocale('no');
- $('#nowPicker').datetimepicker('destroy');
- if(!now && nms.now)
- now = nms.now;
- var datepicker = $('#nowPicker').datetimepicker({
- value: now,
- mask:false,
- inline:true,
- todayButton: false,
- validateOnBlur:false,
- dayOfWeekStart:1,
- maxDate:'+1970/01/01',
- onSelectDate: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- },
- onSelectTime: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- },
- onGenerate: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- }
- });
-}
-
-/*
* Test if the entire path specified in the arrary "ar" exists under the
* specified root.
*