diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/index.html | 7 | ||||
| -rw-r--r-- | web/js/nms-data.js | 3 | ||||
| -rw-r--r-- | web/js/nms-map.js | 14 | ||||
| -rw-r--r-- | web/js/nms-time.js | 150 | ||||
| -rw-r--r-- | web/js/nms.js | 273 | 
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.   *  | 
