Load history when the map is initialized.
This can take a few seconds, so add a loading spinny while it loads. (cherry picked from commit 8d3fdcc1625278a25a289dee33ef6b8eaccfd0ff)
This commit is contained in:
parent
1db63ebc65
commit
6458cfd2fe
|
@ -15,9 +15,10 @@
|
||||||
<title>DUMP1090</title>
|
<title>DUMP1090</title>
|
||||||
</head>
|
</head>
|
||||||
<body onload="initialize()">
|
<body onload="initialize()">
|
||||||
<div id="dialog-modal" title="Basic modal dialog" style="display:none;">
|
<div id="loader" class="hidden">
|
||||||
<p>The settings feature is coming soon. Keep checking GitHub.</p>
|
<img src="spinny.gif" id="spinny">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="map_container">
|
<div id="map_container">
|
||||||
<div id="map_canvas"></div>
|
<div id="map_canvas"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -75,8 +75,10 @@ function PlaneObject(icao) {
|
||||||
|
|
||||||
// Appends data to the running track so we can get a visual tail on the plane
|
// Appends data to the running track so we can get a visual tail on the plane
|
||||||
// Only useful for a long running browser session.
|
// Only useful for a long running browser session.
|
||||||
PlaneObject.prototype.updateTrack = function() {
|
PlaneObject.prototype.updateTrack = function(estimate_time) {
|
||||||
var here = this.position;
|
var here = this.position;
|
||||||
|
if (!here)
|
||||||
|
return;
|
||||||
|
|
||||||
if (this.track_linesegs.length == 0) {
|
if (this.track_linesegs.length == 0) {
|
||||||
// Brand new track
|
// Brand new track
|
||||||
|
@ -98,7 +100,7 @@ PlaneObject.prototype.updateTrack = function() {
|
||||||
var elapsed = (this.last_position_time - lastseg.head_update);
|
var elapsed = (this.last_position_time - lastseg.head_update);
|
||||||
|
|
||||||
var new_data = (here !== lastpos);
|
var new_data = (here !== lastpos);
|
||||||
var est_track = (elapsed > 5);
|
var est_track = (elapsed > estimate_time);
|
||||||
var ground_track = (this.altitude === "ground");
|
var ground_track = (this.altitude === "ground");
|
||||||
|
|
||||||
if (!new_data)
|
if (!new_data)
|
||||||
|
@ -256,7 +258,7 @@ PlaneObject.prototype.updateTick = function(receiver_timestamp) {
|
||||||
} else {
|
} else {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
if (this.position !== null) {
|
if (this.position !== null) {
|
||||||
if (this.updateTrack()) {
|
if (this.updateTrack(5)) {
|
||||||
this.updateLines();
|
this.updateLines();
|
||||||
this.updateMarker(true);
|
this.updateMarker(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -41,6 +41,48 @@ var MessageCountHistory = [];
|
||||||
var NBSP='\u00a0';
|
var NBSP='\u00a0';
|
||||||
var DEGREES='\u00b0'
|
var DEGREES='\u00b0'
|
||||||
|
|
||||||
|
function processReceiverUpdate(data) {
|
||||||
|
// Loop through all the planes in the data packet
|
||||||
|
var now = data.now;
|
||||||
|
var acs = data.aircraft;
|
||||||
|
|
||||||
|
// Detect stats reset
|
||||||
|
if (MessageCountHistory.length > 0 && MessageCountHistory[MessageCountHistory.length-1].messages > data.messages) {
|
||||||
|
MessageCountHistory = [{'time' : MessageCountHistory[MessageCountHistory.length-1].time,
|
||||||
|
'messages' : 0}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note the message count in the history
|
||||||
|
MessageCountHistory.push({ 'time' : now, 'messages' : data.messages});
|
||||||
|
// .. and clean up any old values
|
||||||
|
if ((now - MessageCountHistory[0].time) > 30)
|
||||||
|
MessageCountHistory.shift();
|
||||||
|
|
||||||
|
for (var j=0; j < acs.length; j++) {
|
||||||
|
var ac = acs[j];
|
||||||
|
var hex = ac.hex;
|
||||||
|
var plane = null;
|
||||||
|
|
||||||
|
// Do we already have this plane object in Planes?
|
||||||
|
// If not make it.
|
||||||
|
|
||||||
|
if (Planes[hex]) {
|
||||||
|
plane = Planes[hex];
|
||||||
|
} else {
|
||||||
|
plane = new PlaneObject(hex);
|
||||||
|
plane.tr = PlaneRowTemplate.cloneNode(true);
|
||||||
|
plane.tr.cells[0].textContent = hex; // this won't change
|
||||||
|
plane.tr.addEventListener('click', selectPlaneByHex.bind(undefined,hex));
|
||||||
|
|
||||||
|
Planes[hex] = plane;
|
||||||
|
PlanesOrdered.push(plane);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function update
|
||||||
|
plane.updateData(now, ac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fetchData() {
|
function fetchData() {
|
||||||
if (FetchPending !== null && FetchPending.state() == 'pending') {
|
if (FetchPending !== null && FetchPending.state() == 'pending') {
|
||||||
// don't double up on fetches, let the last one resolve
|
// don't double up on fetches, let the last one resolve
|
||||||
|
@ -52,45 +94,9 @@ function fetchData() {
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: 'json' });
|
dataType: 'json' });
|
||||||
FetchPending.done(function(data) {
|
FetchPending.done(function(data) {
|
||||||
// Loop through all the planes in the data packet
|
|
||||||
var now = data.now;
|
var now = data.now;
|
||||||
var acs = data.aircraft;
|
|
||||||
|
|
||||||
// Detect stats reset
|
processReceiverUpdate(data);
|
||||||
if (MessageCountHistory.length > 0 && MessageCountHistory[MessageCountHistory.length-1].messages > data.messages) {
|
|
||||||
MessageCountHistory = [{'time' : MessageCountHistory[MessageCountHistory.length-1].time,
|
|
||||||
'messages' : 0}];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note the message count in the history
|
|
||||||
MessageCountHistory.push({ 'time' : now, 'messages' : data.messages});
|
|
||||||
// .. and clean up any old values
|
|
||||||
if ((now - MessageCountHistory[0].time) > 30)
|
|
||||||
MessageCountHistory.shift();
|
|
||||||
|
|
||||||
for (var j=0; j < acs.length; j++) {
|
|
||||||
var ac = acs[j];
|
|
||||||
var hex = ac.hex;
|
|
||||||
var plane = null;
|
|
||||||
|
|
||||||
// Do we already have this plane object in Planes?
|
|
||||||
// If not make it.
|
|
||||||
|
|
||||||
if (Planes[hex]) {
|
|
||||||
plane = Planes[hex];
|
|
||||||
} else {
|
|
||||||
plane = new PlaneObject(hex);
|
|
||||||
plane.tr = PlaneRowTemplate.cloneNode(true);
|
|
||||||
plane.tr.cells[0].textContent = hex; // this won't change
|
|
||||||
plane.tr.addEventListener('click', selectPlaneByHex.bind(undefined,hex));
|
|
||||||
|
|
||||||
Planes[hex] = plane;
|
|
||||||
PlanesOrdered.push(plane);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the function update
|
|
||||||
plane.updateData(now, ac);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update timestamps, visibility, history track for all planes - not only those updated
|
// update timestamps, visibility, history track for all planes - not only those updated
|
||||||
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
||||||
|
@ -126,6 +132,7 @@ function fetchData() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var PositionHistorySize = 0;
|
||||||
function initialize() {
|
function initialize() {
|
||||||
PlaneRowTemplate = document.getElementById("plane_row_template");
|
PlaneRowTemplate = document.getElementById("plane_row_template");
|
||||||
|
|
||||||
|
@ -173,12 +180,102 @@ function initialize() {
|
||||||
|
|
||||||
Dump1090Version = data.version;
|
Dump1090Version = data.version;
|
||||||
RefreshInterval = data.refresh;
|
RefreshInterval = data.refresh;
|
||||||
|
PositionHistorySize = data.history;
|
||||||
})
|
})
|
||||||
.always(initialize_after_config);
|
.always(function() {
|
||||||
|
initialize_map();
|
||||||
|
start_load_history();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var CurrentHistoryFetch = null;
|
||||||
|
var PositionHistoryBuffer = []
|
||||||
|
function start_load_history() {
|
||||||
|
if (PositionHistorySize > 0) {
|
||||||
|
console.log("Starting to load history");
|
||||||
|
$("#loader").removeClass("hidden");
|
||||||
|
load_history_item(0);
|
||||||
|
} else {
|
||||||
|
endLoadHistory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_history_item(i) {
|
||||||
|
if (i >= PositionHistorySize) {
|
||||||
|
end_load_history();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Loading history #" + i);
|
||||||
|
|
||||||
|
$.ajax({ url: 'data/history_' + i + '.json',
|
||||||
|
timeout: 5000,
|
||||||
|
cache: false,
|
||||||
|
dataType: 'json' })
|
||||||
|
|
||||||
|
.done(function(data) {
|
||||||
|
PositionHistoryBuffer.push(data);
|
||||||
|
load_history_item(i+1);
|
||||||
|
})
|
||||||
|
|
||||||
|
.fail(function(jqxhr, status, error) {
|
||||||
|
// No more history
|
||||||
|
end_load_history();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function end_load_history() {
|
||||||
|
$("#loader").addClass("hidden");
|
||||||
|
|
||||||
|
console.log("Done loading history");
|
||||||
|
|
||||||
|
if (PositionHistoryBuffer.length > 0) {
|
||||||
|
var now, last=0;
|
||||||
|
|
||||||
|
// Sort history by timestamp
|
||||||
|
console.log("Sorting history");
|
||||||
|
PositionHistoryBuffer.sort(function(x,y) { return (x.now - y.now); });
|
||||||
|
|
||||||
|
// Process history
|
||||||
|
for (var h = 0; h < PositionHistoryBuffer.length; ++h) {
|
||||||
|
now = PositionHistoryBuffer[h].now;
|
||||||
|
console.log("Applying history " + h + "/" + PositionHistoryBuffer.length + " at: " + now);
|
||||||
|
processReceiverUpdate(PositionHistoryBuffer[h]);
|
||||||
|
|
||||||
|
// update track
|
||||||
|
console.log("Updating tracks at: " + now);
|
||||||
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
||||||
|
var plane = PlanesOrdered[i];
|
||||||
|
plane.updateTrack((now - last) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final pass to update all planes to their latest state
|
||||||
|
console.log("Final history cleanup pass");
|
||||||
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
||||||
|
var plane = PlanesOrdered[i];
|
||||||
|
plane.updateTick(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PositionHistoryBuffer = null;
|
||||||
|
|
||||||
|
console.log("Completing init");
|
||||||
|
|
||||||
|
refreshTableInfo();
|
||||||
|
refreshSelected();
|
||||||
|
reaper();
|
||||||
|
|
||||||
|
// Setup our timer to poll from the server.
|
||||||
|
window.setInterval(fetchData, RefreshInterval);
|
||||||
|
window.setInterval(reaper, 60000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initalizes the map and starts up our timers to call various functions
|
// Initalizes the map and starts up our timers to call various functions
|
||||||
function initialize_after_config() {
|
function initialize_map() {
|
||||||
// Load stored map settings if present
|
// Load stored map settings if present
|
||||||
CenterLat = Number(localStorage['CenterLat']) || DefaultCenterLat;
|
CenterLat = Number(localStorage['CenterLat']) || DefaultCenterLat;
|
||||||
CenterLon = Number(localStorage['CenterLon']) || DefaultCenterLon;
|
CenterLon = Number(localStorage['CenterLon']) || DefaultCenterLon;
|
||||||
|
@ -329,15 +426,6 @@ function initialize_after_config() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These will run after page is complitely loaded
|
|
||||||
$(window).load(function() {
|
|
||||||
$('#dialog-modal').css('display', 'inline'); // Show hidden settings-windows content
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setup our timer to poll from the server.
|
|
||||||
window.setInterval(fetchData, RefreshInterval);
|
|
||||||
window.setInterval(reaper, 60000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This looks for planes to reap out of the master Planes variable
|
// This looks for planes to reap out of the master Planes variable
|
||||||
|
|
|
@ -15,6 +15,9 @@ div#update_error { position: absolute; bottom: 25px; left: 25px; border: 2px sol
|
||||||
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
||||||
text-align: center; }
|
text-align: center; }
|
||||||
|
|
||||||
|
div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right: 0; background: #000; opacity: 0.8; filter: alpha(opacity=80); }
|
||||||
|
#spinny { width: 128px; height: 128px; position: absolute; top: 50%; left: 50%; margin: -64px 0 0 -64px; }
|
||||||
|
|
||||||
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
|
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
|
||||||
|
|
||||||
.vPosition { font-weight: bold; background-color: #d5ffd5; }
|
.vPosition { font-weight: bold; background-color: #d5ffd5; }
|
||||||
|
|
Loading…
Reference in a new issue