2013-05-21 22:28:16 +02:00
|
|
|
// Define our global variables
|
|
|
|
var GoogleMap = null;
|
|
|
|
var Planes = {};
|
2015-01-06 21:15:25 +01:00
|
|
|
var PlanesOrdered = [];
|
2013-05-21 22:28:16 +02:00
|
|
|
var SelectedPlane = null;
|
2013-05-18 23:54:59 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
var EmergencySquawks = {
|
|
|
|
'7500' : 'Aircraft Hijacking',
|
|
|
|
'7600' : 'Radio Failure',
|
|
|
|
'7700' : 'General Emergency'
|
|
|
|
};
|
2013-05-09 16:59:26 +02:00
|
|
|
|
2013-05-25 10:56:32 +02:00
|
|
|
// Get current map settings
|
|
|
|
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
|
|
|
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
|
|
|
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
|
|
|
|
2014-12-10 18:05:22 +01:00
|
|
|
Dump1090Version = "unknown version";
|
|
|
|
RefreshInterval = 1000;
|
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
PlaneRowTemplate = null;
|
|
|
|
|
|
|
|
TrackedAircraft = 0
|
|
|
|
TrackedPositions = 0
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
function fetchData() {
|
2014-11-23 17:02:11 +01:00
|
|
|
$.getJSON('data/aircraft.json', function(data) {
|
2013-05-21 22:28:16 +02:00
|
|
|
// Loop through all the planes in the data packet
|
2015-01-06 00:20:03 +01:00
|
|
|
var now = data.now;
|
|
|
|
var acs = data.aircraft;
|
|
|
|
for (var j=0; j < acs.length; j++) {
|
|
|
|
var ac = acs[j];
|
2015-01-06 21:15:25 +01:00
|
|
|
var hex = ac.hex;
|
|
|
|
var plane = null;
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Do we already have this plane object in Planes?
|
|
|
|
// If not make it.
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
if (Planes[hex]) {
|
|
|
|
plane = Planes[hex];
|
2013-05-21 22:28:16 +02:00
|
|
|
} else {
|
2015-01-06 21:15:25 +01:00
|
|
|
plane = jQuery.extend(true, {}, planeObject);
|
|
|
|
|
|
|
|
plane.tr = PlaneRowTemplate.cloneNode(true);
|
|
|
|
plane.tr.cells[0].textContent = hex; // this won't change
|
|
|
|
plane.tr.addEventListener('click', $.proxy(plane.selectPlane, plane));
|
|
|
|
plane.sitedist = null;
|
|
|
|
|
|
|
|
Planes[hex] = plane;
|
|
|
|
PlanesOrdered.push(plane);
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2013-06-02 15:51:38 +02:00
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Call the function update
|
2015-01-07 02:19:05 +01:00
|
|
|
plane.updateData(now, ac);
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2015-01-07 02:19:05 +01:00
|
|
|
|
|
|
|
// update timestamps, visibility, history track for all planes - not only those updated
|
|
|
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
|
|
|
var plane = PlanesOrdered[i];
|
|
|
|
plane.updateTick(now);
|
|
|
|
}
|
2014-12-10 18:05:22 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
refreshTableInfo();
|
|
|
|
refreshSelected();
|
2013-05-21 22:28:16 +02:00
|
|
|
});
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
function initialize() {
|
2015-01-06 21:15:25 +01:00
|
|
|
PlaneRowTemplate = document.getElementById("plane_row_template");
|
|
|
|
|
|
|
|
if (!ShowClocks) {
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#timestamps').css('display','none');
|
2015-01-06 21:15:25 +01:00
|
|
|
}
|
|
|
|
|
2014-12-10 18:05:22 +01:00
|
|
|
// Get receiver metadata, reconfigure using it, then continue
|
|
|
|
// with initialization
|
|
|
|
$.getJSON('data/receiver.json')
|
|
|
|
.done(function(data) {
|
2014-12-10 22:34:05 +01:00
|
|
|
if (typeof data.lat !== "undefined") {
|
2014-12-10 18:05:22 +01:00
|
|
|
SiteShow = true;
|
2014-12-10 22:34:05 +01:00
|
|
|
SiteLat = data.lat;
|
|
|
|
SiteLon = data.lon;
|
2015-01-02 23:48:27 +01:00
|
|
|
CONST_CENTERLAT = data.lat;
|
|
|
|
CONST_CENTERLON = data.lon;
|
2014-12-10 18:05:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Dump1090Version = data.version;
|
|
|
|
RefreshInterval = data.refresh;
|
|
|
|
})
|
|
|
|
.always(initialize_after_config);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initalizes the map and starts up our timers to call various functions
|
|
|
|
function initialize_after_config() {
|
2015-01-06 21:15:25 +01:00
|
|
|
// Set SitePosition, initialize sorting
|
|
|
|
|
|
|
|
if (SiteShow && (typeof SiteLat !== 'undefined') && (typeof SiteLon !== 'undefined')) {
|
|
|
|
SitePosition = new google.maps.LatLng(SiteLat, SiteLon);
|
|
|
|
sortByDistance();
|
|
|
|
} else {
|
|
|
|
SitePosition = null;
|
2015-01-07 02:19:05 +01:00
|
|
|
PlaneRowTemplate.cells[5].style.display = 'none'; // hide distance column
|
|
|
|
document.getElementById("distance").style.display = 'none'; // hide distance header
|
2015-01-06 21:15:25 +01:00
|
|
|
sortByAltitude();
|
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Make a list of all the available map IDs
|
|
|
|
var mapTypeIds = [];
|
|
|
|
for(var type in google.maps.MapTypeId) {
|
|
|
|
mapTypeIds.push(google.maps.MapTypeId[type]);
|
|
|
|
}
|
|
|
|
// Push OSM on to the end
|
|
|
|
mapTypeIds.push("OSM");
|
|
|
|
mapTypeIds.push("dark_map");
|
|
|
|
|
|
|
|
// Styled Map to outline airports and highways
|
|
|
|
var styles = [
|
|
|
|
{
|
2013-05-22 05:26:40 +02:00
|
|
|
"featureType": "administrative",
|
2013-05-21 22:28:16 +02:00
|
|
|
"stylers": [
|
2013-05-22 05:26:40 +02:00
|
|
|
{ "visibility": "off" }
|
|
|
|
]
|
|
|
|
},{
|
|
|
|
"featureType": "landscape",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "off" }
|
|
|
|
]
|
|
|
|
},{
|
|
|
|
"featureType": "poi",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "off" }
|
2013-05-21 22:28:16 +02:00
|
|
|
]
|
|
|
|
},{
|
|
|
|
"featureType": "road",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "off" }
|
|
|
|
]
|
|
|
|
},{
|
|
|
|
"featureType": "transit",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "off" }
|
|
|
|
]
|
2013-05-22 05:26:40 +02:00
|
|
|
},{
|
|
|
|
"featureType": "landscape",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "on" },
|
|
|
|
{ "weight": 8 },
|
|
|
|
{ "color": "#000000" }
|
|
|
|
]
|
|
|
|
},{
|
|
|
|
"featureType": "water",
|
|
|
|
"stylers": [
|
|
|
|
{ "lightness": -74 }
|
|
|
|
]
|
2013-05-21 22:28:16 +02:00
|
|
|
},{
|
|
|
|
"featureType": "transit.station.airport",
|
|
|
|
"stylers": [
|
|
|
|
{ "visibility": "on" },
|
2013-05-22 05:26:40 +02:00
|
|
|
{ "weight": 8 },
|
2013-05-21 22:28:16 +02:00
|
|
|
{ "invert_lightness": true },
|
2013-05-22 05:26:40 +02:00
|
|
|
{ "lightness": 27 }
|
2013-05-21 22:28:16 +02:00
|
|
|
]
|
|
|
|
},{
|
2013-05-22 05:26:40 +02:00
|
|
|
"featureType": "road.highway",
|
2013-05-21 22:28:16 +02:00
|
|
|
"stylers": [
|
2013-05-22 05:26:40 +02:00
|
|
|
{ "visibility": "simplified" },
|
|
|
|
{ "invert_lightness": true },
|
|
|
|
{ "gamma": 0.3 }
|
2013-05-21 22:28:16 +02:00
|
|
|
]
|
|
|
|
},{
|
2013-05-22 05:26:40 +02:00
|
|
|
"featureType": "road",
|
|
|
|
"elementType": "labels",
|
2013-05-21 22:28:16 +02:00
|
|
|
"stylers": [
|
2013-05-22 05:26:40 +02:00
|
|
|
{ "visibility": "off" }
|
2013-05-21 22:28:16 +02:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
// Add our styled map
|
|
|
|
var styledMap = new google.maps.StyledMapType(styles, {name: "Dark Map"});
|
|
|
|
|
|
|
|
// Define the Google Map
|
|
|
|
var mapOptions = {
|
|
|
|
center: new google.maps.LatLng(CenterLat, CenterLon),
|
|
|
|
zoom: ZoomLvl,
|
|
|
|
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
2014-08-07 04:31:05 +02:00
|
|
|
mapTypeControl: true,
|
|
|
|
streetViewControl: false,
|
2013-05-21 22:28:16 +02:00
|
|
|
mapTypeControlOptions: {
|
2014-08-07 04:31:05 +02:00
|
|
|
mapTypeIds: mapTypeIds,
|
|
|
|
position: google.maps.ControlPosition.TOP_LEFT,
|
|
|
|
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
GoogleMap = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
|
|
|
|
|
|
|
|
//Define OSM map type pointing at the OpenStreetMap tile server
|
|
|
|
GoogleMap.mapTypes.set("OSM", new google.maps.ImageMapType({
|
|
|
|
getTileUrl: function(coord, zoom) {
|
|
|
|
return "http://tile.openstreetmap.org/" + zoom + "/" + coord.x + "/" + coord.y + ".png";
|
|
|
|
},
|
|
|
|
tileSize: new google.maps.Size(256, 256),
|
|
|
|
name: "OpenStreetMap",
|
|
|
|
maxZoom: 18
|
|
|
|
}));
|
|
|
|
|
|
|
|
GoogleMap.mapTypes.set("dark_map", styledMap);
|
2013-05-26 22:34:38 +02:00
|
|
|
|
2013-05-31 09:04:11 +02:00
|
|
|
// Listeners for newly created Map
|
|
|
|
google.maps.event.addListener(GoogleMap, 'center_changed', function() {
|
|
|
|
localStorage['CenterLat'] = GoogleMap.getCenter().lat();
|
|
|
|
localStorage['CenterLon'] = GoogleMap.getCenter().lng();
|
|
|
|
});
|
|
|
|
|
|
|
|
google.maps.event.addListener(GoogleMap, 'zoom_changed', function() {
|
|
|
|
localStorage['ZoomLvl'] = GoogleMap.getZoom();
|
|
|
|
});
|
|
|
|
|
2013-05-26 22:34:38 +02:00
|
|
|
// Add home marker if requested
|
2015-01-06 21:15:25 +01:00
|
|
|
if (SitePosition) {
|
2013-05-30 11:22:52 +02:00
|
|
|
var markerImage = new google.maps.MarkerImage(
|
|
|
|
'http://maps.google.com/mapfiles/kml/pal4/icon57.png',
|
2013-05-26 22:34:38 +02:00
|
|
|
new google.maps.Size(32, 32), // Image size
|
|
|
|
new google.maps.Point(0, 0), // Origin point of image
|
|
|
|
new google.maps.Point(16, 16)); // Position where marker should point
|
|
|
|
var marker = new google.maps.Marker({
|
2015-01-06 21:15:25 +01:00
|
|
|
position: SitePosition,
|
2013-05-26 22:34:38 +02:00
|
|
|
map: GoogleMap,
|
|
|
|
icon: markerImage,
|
2013-06-02 19:49:45 +02:00
|
|
|
title: 'My Radar Site',
|
|
|
|
zIndex: -99999
|
2013-05-30 11:22:52 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
if (SiteCircles) {
|
|
|
|
for (var i=0;i<SiteCirclesDistances.length;i++) {
|
|
|
|
drawCircle(marker, SiteCirclesDistances[i]); // in meters
|
|
|
|
}
|
|
|
|
}
|
2013-05-26 22:34:38 +02:00
|
|
|
}
|
2013-06-02 12:45:53 +02:00
|
|
|
|
|
|
|
// These will run after page is complitely loaded
|
|
|
|
$(window).load(function() {
|
|
|
|
$('#dialog-modal').css('display', 'inline'); // Show hidden settings-windows content
|
|
|
|
});
|
2013-05-21 22:28:16 +02:00
|
|
|
|
2013-05-30 23:26:16 +02:00
|
|
|
// Load up our options page
|
|
|
|
optionsInitalize();
|
2013-05-30 19:45:10 +02:00
|
|
|
|
2013-05-24 04:15:37 +02:00
|
|
|
// Did our crafty user need some setup?
|
|
|
|
extendedInitalize();
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Setup our timer to poll from the server.
|
2015-01-06 21:15:25 +01:00
|
|
|
window.setInterval(fetchData, RefreshInterval);
|
|
|
|
window.setInterval(reaper, 60000);
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// This looks for planes to reap out of the master Planes variable
|
|
|
|
function reaper() {
|
2015-01-07 02:19:05 +01:00
|
|
|
//console.log("Reaping started..");
|
2015-01-06 21:15:25 +01:00
|
|
|
|
2015-01-07 02:19:05 +01:00
|
|
|
// Look for planes where we have seen no messages for >300 seconds
|
2015-01-06 21:15:25 +01:00
|
|
|
var newPlanes = [];
|
|
|
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
|
|
|
var plane = PlanesOrdered[i];
|
2015-01-07 02:19:05 +01:00
|
|
|
if (plane.seen > 300) {
|
2015-01-06 21:15:25 +01:00
|
|
|
// Reap it.
|
2015-01-07 02:19:05 +01:00
|
|
|
//console.log("Reaping " + plane.icao);
|
|
|
|
//console.log("parent " + plane.tr.parentNode);
|
|
|
|
plane.tr.parentNode.removeChild(plane.tr);
|
|
|
|
plane.tr = null;
|
2015-01-06 21:15:25 +01:00
|
|
|
delete Planes[plane.icao];
|
2015-01-07 02:19:05 +01:00
|
|
|
plane.destroy();
|
2015-01-06 21:15:25 +01:00
|
|
|
} else {
|
|
|
|
// Keep it.
|
|
|
|
newPlanes.push(plane);
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
|
|
|
};
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
PlanesOrdered = newPlanes;
|
|
|
|
refreshTableInfo();
|
|
|
|
refreshSelected();
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Refresh the detail window about the plane
|
|
|
|
function refreshSelected() {
|
2015-01-06 21:15:25 +01:00
|
|
|
var selected = false;
|
2013-05-26 14:19:38 +02:00
|
|
|
if (typeof SelectedPlane !== 'undefined' && SelectedPlane != "ICAO" && SelectedPlane != null) {
|
2015-01-06 21:15:25 +01:00
|
|
|
selected = Planes[SelectedPlane];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!selected) {
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#selected_infoblock').css('display','none');
|
|
|
|
$('#dump1090_infoblock').css('display','block');
|
2015-01-06 21:15:25 +01:00
|
|
|
$('#dump1090_version').text(Dump1090Version);
|
|
|
|
$('#dump1090_total_ac').text(TrackedAircraft);
|
|
|
|
$('#dump1090_total_ac_positions').text(TrackedAircraftPositions);
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#dump1090_total_history').text(TrackedHistorySize);
|
2015-01-06 21:15:25 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#dump1090_infoblock').css('display','none');
|
|
|
|
$('#selected_infoblock').css('display','block');
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
if (selected.flight !== null && selected.flight !== "") {
|
|
|
|
$('#selected_callsign').text(selected.flight);
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#selected_links').css('display','inline');
|
2015-01-06 21:15:25 +01:00
|
|
|
$('#selected_fr24_link').attr('href','http://fr24.com/'+selected.flight);
|
|
|
|
$('#selected_flightstats_link').attr('href','http://www.flightstats.com/go/FlightStatus/flightStatusByFlight.do?flightNumber='+selected.flight);
|
|
|
|
$('#selected_flightaware_link').attr('href','http://flightaware.com/live/flight/'+selected.flight);
|
2013-05-28 11:15:18 +02:00
|
|
|
} else {
|
2015-01-06 21:15:25 +01:00
|
|
|
$('#selected_callsign').text('n/a (' + selected.icao + ')');
|
2015-01-07 02:19:05 +01:00
|
|
|
$('#selected_links').css('display','none');
|
2015-01-06 21:15:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var emerg = document.getElementById('selected_emergency');
|
|
|
|
if (selected.squawk in EmergencySquawks) {
|
|
|
|
emerg.className = 'squawk' + selected.squawk;
|
|
|
|
emerg.textContent = '\u00a0Squawking: ' + EmergencySquawks[selected.squawk] + '\u00a0';
|
|
|
|
} else {
|
|
|
|
emerg.className = 'hidden';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selected.altitude === null)
|
|
|
|
$("#selected_altitude").text("n/a");
|
|
|
|
else if (selected.altitude === "ground")
|
|
|
|
$("#selected_altitude").text("on ground");
|
|
|
|
else if (Metric)
|
|
|
|
$("#selected_altitude").text(Math.round(selected.altitude / 3.2828) + ' m');
|
|
|
|
else
|
|
|
|
$("#selected_altitude").text(Math.round(selected.altitude) + ' ft');
|
|
|
|
|
|
|
|
if (selected.squawk === null || selected.squawk === '0000') {
|
|
|
|
$('#selected_squawk').text('n/a');
|
|
|
|
} else {
|
|
|
|
$('#selected_squawk').text(selected.squawk);
|
2013-05-28 11:15:18 +02:00
|
|
|
}
|
2013-05-26 14:19:38 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
if (selected.speed === null) {
|
|
|
|
$('#selected_speed').text('n/a');
|
|
|
|
} else if (Metric) {
|
|
|
|
$('#selected_speed').text(Math.round(selected.speed * 1.852) + ' km/h');
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
2015-01-06 21:15:25 +01:00
|
|
|
$('#selected_speed').text(Math.round(selected.speed) + ' kt');
|
2013-05-26 14:19:38 +02:00
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
$('#selected_icao').text(selected.icao);
|
|
|
|
|
|
|
|
if (selected.track === null) {
|
|
|
|
$('#selected_track').text('n/a');
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
2015-01-06 21:15:25 +01:00
|
|
|
$('#selected_track').text(selected.track + '\u00b0' + ' (' + trackLongName(selected.track) + ')');
|
2013-05-26 14:19:38 +02:00
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
if (selected.seen <= 1) {
|
|
|
|
$('#selected_seen').text('now');
|
|
|
|
} else {
|
|
|
|
$('#selected_seen').text(selected.seen + 's ago');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selected.latitude === null) {
|
|
|
|
$('#selected_position').text('n/a');
|
|
|
|
} else {
|
|
|
|
if (selected.seen_pos > 1) {
|
|
|
|
$('#selected_position').text(selected.latitude + ', ' + selected.longitude + " (" + selected.seen_pos + "s ago)");
|
|
|
|
} else {
|
|
|
|
$('#selected_position').text(selected.latitude + ', ' + selected.longitude);
|
|
|
|
}
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2013-05-27 10:36:23 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
if (selected.sitedist !== null) {
|
|
|
|
var dist = selected.sitedist;
|
|
|
|
if (Metric) {
|
|
|
|
dist /= 1000;
|
|
|
|
} else {
|
|
|
|
dist /= 1852;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist = (Math.round((dist)*10)/10).toFixed(1);
|
|
|
|
|
|
|
|
$('#selected_sitedist').text(dist + (Metric ? ' km' : ' NM'));
|
|
|
|
} else {
|
|
|
|
$('#selected_sitedist').text("n/a");
|
|
|
|
}
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2013-05-11 12:15:09 +02:00
|
|
|
|
2015-01-06 00:20:03 +01:00
|
|
|
function trackShortName(track) {
|
2015-01-06 21:15:25 +01:00
|
|
|
var trackIndex = Math.floor((360 + track % 360 + 22.5) / 45) % 8;
|
2015-01-06 00:20:03 +01:00
|
|
|
return ["N","NE","E","SE","S","SW","W","NW"][trackIndex];
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 00:20:03 +01:00
|
|
|
function trackLongName(track) {
|
2015-01-06 21:15:25 +01:00
|
|
|
var trackIndex = Math.floor((360 + track % 360 + 22.5) / 45) % 8;
|
2015-01-06 00:20:03 +01:00
|
|
|
return ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"][trackIndex];
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Refeshes the larger table of all the planes
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
function format_altitude(alt) {
|
|
|
|
if (alt === null)
|
|
|
|
return "";
|
|
|
|
else if (alt === "ground")
|
|
|
|
return "ground";
|
|
|
|
else if (Metric)
|
|
|
|
return Math.round(alt / 3.2828);
|
|
|
|
else
|
|
|
|
return Math.round(alt);
|
|
|
|
}
|
|
|
|
|
|
|
|
function format_speed(speed) {
|
|
|
|
if (speed === null)
|
|
|
|
return "";
|
|
|
|
else if (Metric)
|
|
|
|
return Math.round(speed * 1.852);
|
|
|
|
else
|
|
|
|
return Math.round(speed);
|
|
|
|
}
|
|
|
|
|
|
|
|
function format_distance(dist) {
|
|
|
|
if (Metric) {
|
|
|
|
return (Math.round(dist/100) / 10).toFixed(1);
|
|
|
|
} else {
|
|
|
|
return (Math.round(dist/185.2) / 10).toFixed(1);
|
2014-07-17 03:42:02 +02:00
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function refreshTableInfo() {
|
|
|
|
var show_squawk_warning = false;
|
|
|
|
|
|
|
|
TrackedAircraft = 0
|
|
|
|
TrackedAircraftPositions = 0
|
2015-01-07 02:19:05 +01:00
|
|
|
TrackedHistorySize = 0
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
|
|
|
var tableplane = PlanesOrdered[i];
|
2015-01-07 02:19:05 +01:00
|
|
|
TrackedHistorySize += tableplane.historySize;
|
|
|
|
if (!tableplane.visible) {
|
|
|
|
tableplane.tr.className = "plane_table_row hidden";
|
2015-01-06 21:15:25 +01:00
|
|
|
} else {
|
|
|
|
TrackedAircraft++;
|
|
|
|
var classes = "plane_table_row";
|
2015-01-07 02:19:05 +01:00
|
|
|
|
2015-01-06 00:20:03 +01:00
|
|
|
if (tableplane.latitude !== null)
|
2015-01-07 02:19:05 +01:00
|
|
|
classes += " vPosition";
|
2015-01-06 21:15:25 +01:00
|
|
|
if (tableplane.icao == SelectedPlane)
|
2015-01-07 02:19:05 +01:00
|
|
|
classes += " selected";
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
if (tableplane.squawk in EmergencySquawks) {
|
2015-01-07 02:19:05 +01:00
|
|
|
classes += (" squawk" + tableplane.squawk);
|
2015-01-06 21:15:25 +01:00
|
|
|
show_squawk_warning = true;
|
2015-01-07 02:19:05 +01:00
|
|
|
}
|
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
// ICAO doesn't change
|
|
|
|
tableplane.tr.cells[1].textContent = (tableplane.flight !== null ? tableplane.flight : "");
|
|
|
|
tableplane.tr.cells[2].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
|
|
|
|
tableplane.tr.cells[3].textContent = format_altitude(tableplane.altitude);
|
|
|
|
tableplane.tr.cells[4].textContent = format_speed(tableplane.speed);
|
|
|
|
|
|
|
|
if (tableplane.latitude !== null)
|
|
|
|
++TrackedAircraftPositions;
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2014-07-17 03:42:02 +02:00
|
|
|
// Add distance column to table if site coordinates are provided
|
2015-01-06 21:15:25 +01:00
|
|
|
if (SitePosition !== null && tableplane.latitude !== null) {
|
|
|
|
var planeLatLon = new google.maps.LatLng(tableplane.latitude, tableplane.longitude);
|
|
|
|
var dist = google.maps.geometry.spherical.computeDistanceBetween (SitePosition, planeLatLon);
|
|
|
|
tableplane.tr.cells[5].textContent = format_distance(dist);
|
|
|
|
tableplane.sitedist = dist;
|
|
|
|
} else {
|
|
|
|
tableplane.tr.cells[5].textContent = "";
|
2014-07-17 03:42:02 +02:00
|
|
|
}
|
2013-05-28 11:15:18 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
tableplane.tr.cells[6].textContent = (tableplane.track !== null ? tableplane.track : "");
|
|
|
|
tableplane.tr.cells[7].textContent = tableplane.messages;
|
|
|
|
tableplane.tr.cells[8].textContent = tableplane.seen;
|
2015-01-07 02:19:05 +01:00
|
|
|
|
|
|
|
tableplane.tr.className = classes;
|
|
|
|
|
2013-05-18 23:54:59 +02:00
|
|
|
}
|
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
if (show_squawk_warning) {
|
2015-01-07 02:19:05 +01:00
|
|
|
$("#SpecialSquawkWarning").css('display','block');
|
2015-01-06 00:20:03 +01:00
|
|
|
} else {
|
2015-01-07 02:19:05 +01:00
|
|
|
$("#SpecialSquawkWarning").css('display','none');
|
2015-01-06 00:20:03 +01:00
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
resortTable();
|
2013-05-18 23:54:59 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
//
|
|
|
|
// ---- table sorting ----
|
|
|
|
//
|
|
|
|
|
|
|
|
function compareAlpha(xa,xo,ya,yo) {
|
|
|
|
if (xa === ya)
|
|
|
|
return xo - yo;
|
|
|
|
if (xa === null)
|
|
|
|
return 1;
|
|
|
|
if (ya === null)
|
|
|
|
return -1;
|
|
|
|
if (xa < ya)
|
|
|
|
return -1;
|
|
|
|
return 1;
|
|
|
|
}
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
function compareNumeric(xf,xo,yf,yo) {
|
|
|
|
if (xf === null) xf = 1e9;
|
|
|
|
if (yf === null) yf = 1e9;
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
if (Math.abs(xf - yf) < 1e-9)
|
|
|
|
return xo - yo;
|
|
|
|
|
|
|
|
return xf - yf;
|
2013-05-18 23:54:59 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
function compareAltitude(xf,xo,yf,yo) {
|
|
|
|
if (xf === null) xf = 1e9;
|
|
|
|
else if (xf === "ground") xf = -1e9;
|
|
|
|
if (yf === null) yf = 1e9;
|
|
|
|
else if (yf === "ground") yf = -1e9;
|
|
|
|
|
|
|
|
if (Math.abs(xf - yf) < 1e-9)
|
|
|
|
return xo - yo;
|
|
|
|
|
|
|
|
return xf - yf;
|
2015-01-06 00:20:03 +01:00
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
function sortByICAO() { sortBy('icao', function(x,y){return compareAlpha(x.icao, x.sort_pos, y.icao, y.sort_pos)}); }
|
|
|
|
function sortByFlight() { sortBy('flight', function(x,y){return compareAlpha(x.flight, x.sort_pos, y.flight, y.sort_pos)}); }
|
|
|
|
function sortBySquawk() { sortBy('squawk', function(x,y){return compareAlpha(x.squawk, x.sort_pos, y.squawk, y.sort_pos)}); }
|
|
|
|
function sortByAltitude() { sortBy('altitude',function(x,y){return compareAltitude(x.altitude, x.sort_pos, y.altitude, y.sort_pos)}); }
|
|
|
|
function sortBySpeed() { sortBy('speed', function(x,y){return compareNumeric(x.speed, x.sort_pos, y.speed, y.sort_pos)}); }
|
|
|
|
function sortByDistance() { sortBy('sitedist',function(x,y){return compareNumeric(x.sitedist, x.sort_pos, y.sitedist, y.sort_pos)}); }
|
|
|
|
function sortByTrack() { sortBy('track', function(x,y){return compareNumeric(x.track, x.sort_pos, y.track, y.sort_pos)}); }
|
|
|
|
function sortByMsgs() { sortBy('msgs', function(x,y){return compareNumeric(x.msgs, x.sort_pos, y.msgs, y.sort_pos)}); }
|
|
|
|
function sortBySeen() { sortBy('seen', function(x,y){return compareNumeric(x.seen, x.sort_pos, y.seen, y.sort_pos)}); }
|
|
|
|
|
|
|
|
sortId = '';
|
|
|
|
sortByFunc = null;
|
|
|
|
sortAscending = true;
|
|
|
|
|
|
|
|
function resortTable() {
|
|
|
|
// make it a stable sort
|
|
|
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
|
|
|
PlanesOrdered[i].sort_pos = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlanesOrdered.sort(sortByFunc);
|
2015-01-06 00:20:03 +01:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
var tbody = document.getElementById('tableinfo').tBodies[0];
|
|
|
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
|
|
|
tbody.appendChild(PlanesOrdered[i].tr);
|
|
|
|
}
|
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
function sortBy(id,sortfunc) {
|
|
|
|
if (id === sortId) {
|
|
|
|
sortAscending = !sortAscending;
|
|
|
|
} else {
|
|
|
|
sortAscending = true;
|
|
|
|
}
|
2013-05-12 14:15:18 +02:00
|
|
|
|
2015-01-06 21:15:25 +01:00
|
|
|
if (sortAscending)
|
|
|
|
sortByFunc = sortfunc;
|
|
|
|
else
|
|
|
|
sortByFunc = function(x,y){return sortfunc(y,x);}
|
|
|
|
|
|
|
|
sortId = id;
|
|
|
|
resortTable();
|
2013-05-11 12:15:09 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
function selectPlaneByHex(hex) {
|
2015-01-06 21:15:25 +01:00
|
|
|
//console.log("select: " + hex);
|
2013-05-24 04:15:37 +02:00
|
|
|
// If SelectedPlane has something in it, clear out the selected
|
2013-05-22 19:09:12 +02:00
|
|
|
if (SelectedPlane != null) {
|
2013-05-24 04:15:37 +02:00
|
|
|
Planes[SelectedPlane].is_selected = false;
|
2015-01-07 02:19:05 +01:00
|
|
|
Planes[SelectedPlane].clearLines();
|
|
|
|
Planes[SelectedPlane].updateMarker();
|
|
|
|
$(Planes[SelectedPlane].tr).removeClass("selected");
|
2013-05-22 19:09:12 +02:00
|
|
|
}
|
2013-05-22 05:26:40 +02:00
|
|
|
|
2013-05-24 04:15:37 +02:00
|
|
|
// If we are clicking the same plane, we are deselected it.
|
2015-01-07 02:19:05 +01:00
|
|
|
if (SelectedPlane === hex) {
|
|
|
|
hex = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hex !== null) {
|
2013-05-24 04:15:37 +02:00
|
|
|
// Assign the new selected
|
|
|
|
SelectedPlane = hex;
|
|
|
|
Planes[SelectedPlane].is_selected = true;
|
2015-01-07 02:19:05 +01:00
|
|
|
Planes[SelectedPlane].updateLines();
|
|
|
|
Planes[SelectedPlane].updateMarker();
|
|
|
|
$(Planes[SelectedPlane].tr).addClass("selected");
|
2013-05-25 17:53:56 +02:00
|
|
|
} else {
|
2013-05-25 22:57:10 +02:00
|
|
|
SelectedPlane = null;
|
2013-05-24 04:15:37 +02:00
|
|
|
}
|
2015-01-06 21:15:25 +01:00
|
|
|
|
|
|
|
refreshSelected();
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
2013-05-30 19:32:36 +02:00
|
|
|
|
|
|
|
function resetMap() {
|
2013-05-31 09:04:11 +02:00
|
|
|
// Reset localStorage values
|
|
|
|
localStorage['CenterLat'] = CONST_CENTERLAT;
|
|
|
|
localStorage['CenterLon'] = CONST_CENTERLON;
|
|
|
|
localStorage['ZoomLvl'] = CONST_ZOOMLVL;
|
|
|
|
|
|
|
|
// Try to read values from localStorage else use CONST_s
|
|
|
|
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
|
|
|
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
|
|
|
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
|
|
|
|
|
|
|
// Set and refresh
|
|
|
|
GoogleMap.setZoom(parseInt(ZoomLvl));
|
|
|
|
GoogleMap.setCenter(new google.maps.LatLng(parseFloat(CenterLat), parseFloat(CenterLon)));
|
2013-05-31 09:29:51 +02:00
|
|
|
|
|
|
|
if (SelectedPlane) {
|
|
|
|
selectPlaneByHex(SelectedPlane);
|
|
|
|
}
|
|
|
|
|
2013-05-30 19:32:36 +02:00
|
|
|
refreshSelected();
|
2013-05-31 09:04:11 +02:00
|
|
|
refreshTableInfo();
|
2013-05-30 19:32:36 +02:00
|
|
|
}
|
|
|
|
|
2013-05-30 11:22:52 +02:00
|
|
|
function drawCircle(marker, distance) {
|
|
|
|
if (typeof distance === 'undefined') {
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(!isNaN(parseFloat(distance)) && isFinite(distance)) || distance < 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
distance *= 1000.0;
|
|
|
|
if (!Metric) {
|
|
|
|
distance *= 1.852;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add circle overlay and bind to marker
|
|
|
|
var circle = new google.maps.Circle({
|
|
|
|
map: GoogleMap,
|
|
|
|
radius: distance, // In meters
|
|
|
|
fillOpacity: 0.0,
|
|
|
|
strokeWeight: 1,
|
|
|
|
strokeOpacity: 0.3
|
|
|
|
});
|
|
|
|
circle.bindTo('center', marker, 'position');
|
|
|
|
}
|