2013-05-21 22:28:16 +02:00
|
|
|
// Define our global variables
|
|
|
|
var GoogleMap = null;
|
|
|
|
var Planes = {};
|
|
|
|
var PlanesOnMap = 0;
|
|
|
|
var PlanesOnTable = 0;
|
|
|
|
var PlanesToReap = 0;
|
|
|
|
var SelectedPlane = null;
|
2013-09-26 13:59:46 +02:00
|
|
|
var SpecialSquawk = false;
|
2013-05-18 23:54:59 +02:00
|
|
|
|
|
|
|
var iSortCol=-1;
|
|
|
|
var bSortASC=true;
|
|
|
|
var bDefaultSortASC=true;
|
|
|
|
var iDefaultSortCol=3;
|
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;
|
|
|
|
|
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
|
|
|
PlanesOnMap = 0
|
2013-06-02 15:51:38 +02:00
|
|
|
SpecialSquawk = false;
|
2013-05-21 22:28:16 +02:00
|
|
|
|
|
|
|
// Loop through all the planes in the data packet
|
|
|
|
for (var j=0; j < data.length; j++) {
|
|
|
|
// Do we already have this plane object in Planes?
|
|
|
|
// If not make it.
|
|
|
|
if (Planes[data[j].hex]) {
|
|
|
|
var plane = Planes[data[j].hex];
|
|
|
|
} else {
|
|
|
|
var plane = jQuery.extend(true, {}, planeObject);
|
|
|
|
}
|
2013-06-02 15:51:38 +02:00
|
|
|
|
2014-12-10 18:05:22 +01:00
|
|
|
// Set SpecialSquawk-value
|
|
|
|
if (data[j].squawk == '7500' || data[j].squawk == '7600' || data[j].squawk == '7700') {
|
|
|
|
SpecialSquawk = true;
|
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Call the function update
|
|
|
|
plane.funcUpdateData(data[j]);
|
|
|
|
|
|
|
|
// Copy the plane into Planes
|
|
|
|
Planes[plane.icao] = plane;
|
|
|
|
}
|
2014-12-10 18:05:22 +01:00
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
PlanesOnTable = data.length;
|
|
|
|
});
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
function initialize() {
|
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;
|
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() {
|
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
|
2013-05-30 11:22:52 +02:00
|
|
|
if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
|
|
|
|
var siteMarker = new google.maps.LatLng(SiteLat, SiteLon);
|
|
|
|
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({
|
|
|
|
position: siteMarker,
|
|
|
|
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.
|
|
|
|
window.setInterval(function() {
|
|
|
|
fetchData();
|
|
|
|
refreshTableInfo();
|
2013-05-26 14:19:38 +02:00
|
|
|
refreshSelected();
|
2013-05-21 22:28:16 +02:00
|
|
|
reaper();
|
2013-05-24 04:15:37 +02:00
|
|
|
extendedPulse();
|
2014-12-10 18:05:22 +01:00
|
|
|
}, RefreshInterval);
|
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() {
|
|
|
|
PlanesToReap = 0;
|
|
|
|
// When did the reaper start?
|
|
|
|
reaptime = new Date().getTime();
|
|
|
|
// Loop the planes
|
|
|
|
for (var reap in Planes) {
|
|
|
|
// Is this plane possibly reapable?
|
|
|
|
if (Planes[reap].reapable == true) {
|
|
|
|
// Has it not been seen for 5 minutes?
|
|
|
|
// This way we still have it if it returns before then
|
|
|
|
// Due to loss of signal or other reasons
|
|
|
|
if ((reaptime - Planes[reap].updated) > 300000) {
|
|
|
|
// Reap it.
|
|
|
|
delete Planes[reap];
|
|
|
|
}
|
|
|
|
PlanesToReap++;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Refresh the detail window about the plane
|
|
|
|
function refreshSelected() {
|
2013-05-26 14:19:38 +02:00
|
|
|
var selected = false;
|
|
|
|
if (typeof SelectedPlane !== 'undefined' && SelectedPlane != "ICAO" && SelectedPlane != null) {
|
|
|
|
selected = Planes[SelectedPlane];
|
|
|
|
}
|
|
|
|
|
|
|
|
var columns = 2;
|
|
|
|
var html = '';
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
html += '<table id="selectedinfo" width="100%">';
|
|
|
|
} else {
|
|
|
|
html += '<table id="selectedinfo" class="dim" width="100%">';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flight header line including squawk if needed
|
|
|
|
if (selected && selected.flight == "") {
|
2013-05-30 11:22:52 +02:00
|
|
|
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>N/A (' +
|
|
|
|
selected.icao + ')</b>';
|
2013-05-26 14:19:38 +02:00
|
|
|
} else if (selected && selected.flight != "") {
|
2013-05-30 11:22:52 +02:00
|
|
|
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>' +
|
|
|
|
selected.flight + '</b>';
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
2014-12-10 18:05:22 +01:00
|
|
|
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>DUMP1090 ' + Dump1090Version + '</b>';
|
2013-05-26 14:19:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (selected && selected.squawk == 7500) { // Lets hope we never see this... Aircraft Hijacking
|
|
|
|
html += ' <span class="squawk7500"> Squawking: Aircraft Hijacking </span>';
|
|
|
|
} else if (selected && selected.squawk == 7600) { // Radio Failure
|
|
|
|
html += ' <span class="squawk7600"> Squawking: Radio Failure </span>';
|
|
|
|
} else if (selected && selected.squawk == 7700) { // General Emergency
|
|
|
|
html += ' <span class="squawk7700"> Squawking: General Emergency </span>';
|
|
|
|
} else if (selected && selected.flight != '') {
|
2014-08-10 09:01:31 +02:00
|
|
|
html += ' <a href="http://fr24.com/'+selected.flight+'" target="_blank">[FR24]</a>';
|
2013-05-26 14:19:38 +02:00
|
|
|
html += ' <a href="http://www.flightstats.com/go/FlightStatus/flightStatusByFlight.do?';
|
|
|
|
html += 'flightNumber='+selected.flight+'" target="_blank">[FlightStats]</a>';
|
2014-02-27 21:40:14 +01:00
|
|
|
html += ' <a href="http://flightaware.com/live/flight/'+selected.flight+'" target="_blank">[FlightAware]</a>';
|
2013-05-26 14:19:38 +02:00
|
|
|
}
|
|
|
|
html += '<td></tr>';
|
|
|
|
|
|
|
|
if (selected) {
|
2013-05-28 11:15:18 +02:00
|
|
|
if (Metric) {
|
|
|
|
html += '<tr><td>Altitude: ' + Math.round(selected.altitude / 3.2828) + ' m</td>';
|
|
|
|
} else {
|
|
|
|
html += '<tr><td>Altitude: ' + selected.altitude + ' ft</td>';
|
|
|
|
}
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
|
|
|
html += '<tr><td>Altitude: n/a</td>';
|
|
|
|
}
|
2013-05-25 22:44:40 +02:00
|
|
|
|
2013-05-26 14:19:38 +02:00
|
|
|
if (selected && selected.squawk != '0000') {
|
|
|
|
html += '<td>Squawk: ' + selected.squawk + '</td></tr>';
|
|
|
|
} else {
|
|
|
|
html += '<td>Squawk: n/a</td></tr>';
|
|
|
|
}
|
|
|
|
|
|
|
|
html += '<tr><td>Speed: '
|
|
|
|
if (selected) {
|
2013-05-28 11:15:18 +02:00
|
|
|
if (Metric) {
|
|
|
|
html += Math.round(selected.speed * 1.852) + ' km/h';
|
|
|
|
} else {
|
|
|
|
html += selected.speed + ' kt';
|
|
|
|
}
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
|
|
|
html += 'n/a';
|
|
|
|
}
|
|
|
|
html += '</td>';
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
html += '<td>ICAO (hex): ' + selected.icao + '</td></tr>';
|
|
|
|
} else {
|
|
|
|
html += '<td>ICAO (hex): n/a</td></tr>'; // Something is wrong if we are here
|
|
|
|
}
|
|
|
|
|
|
|
|
html += '<tr><td>Track: '
|
|
|
|
if (selected && selected.vTrack) {
|
2014-08-02 05:42:58 +02:00
|
|
|
html += selected.track + '°' + ' (' + normalizeTrack(selected.track, selected.vTrack)[1] +')';
|
2013-05-26 14:19:38 +02:00
|
|
|
} else {
|
|
|
|
html += 'n/a';
|
|
|
|
}
|
|
|
|
html += '</td><td> </td></tr>';
|
2013-05-25 22:44:40 +02:00
|
|
|
|
2013-05-26 14:19:38 +02:00
|
|
|
html += '<tr><td colspan="' + columns + '" align="center">Lat/Long: ';
|
|
|
|
if (selected && selected.vPosition) {
|
2013-05-27 10:36:23 +02:00
|
|
|
html += selected.latitude + ', ' + selected.longitude + '</td></tr>';
|
|
|
|
|
|
|
|
// Let's show some extra data if we have site coordinates
|
|
|
|
if (SiteShow) {
|
2013-05-28 11:15:18 +02:00
|
|
|
var siteLatLon = new google.maps.LatLng(SiteLat, SiteLon);
|
|
|
|
var planeLatLon = new google.maps.LatLng(selected.latitude, selected.longitude);
|
|
|
|
var dist = google.maps.geometry.spherical.computeDistanceBetween (siteLatLon, planeLatLon);
|
2013-05-27 10:36:23 +02:00
|
|
|
|
2013-05-28 11:15:18 +02:00
|
|
|
if (Metric) {
|
|
|
|
dist /= 1000;
|
|
|
|
} else {
|
|
|
|
dist /= 1852;
|
2013-05-27 10:36:23 +02:00
|
|
|
}
|
2013-05-28 11:15:18 +02:00
|
|
|
dist = (Math.round((dist)*10)/10).toFixed(1);
|
2014-07-17 03:51:41 +02:00
|
|
|
html += '<tr><td colspan="' + columns + '" align="center">Distance from Site: ' + dist +
|
2013-05-28 11:15:18 +02:00
|
|
|
(Metric ? ' km' : ' NM') + '</td></tr>';
|
2013-05-27 10:36:23 +02:00
|
|
|
} // End of SiteShow
|
2013-05-21 22:28:16 +02:00
|
|
|
} else {
|
2013-05-27 10:36:23 +02:00
|
|
|
if (SiteShow) {
|
2014-07-17 03:51:41 +02:00
|
|
|
html += '<tr><td colspan="' + columns + '" align="center">Distance from Site: n/a ' +
|
2013-05-28 11:15:18 +02:00
|
|
|
(Metric ? ' km' : ' NM') + '</td></tr>';
|
2013-05-27 10:36:23 +02:00
|
|
|
} else {
|
|
|
|
html += 'n/a</td></tr>';
|
|
|
|
}
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2013-05-27 10:36:23 +02:00
|
|
|
|
2013-05-26 14:19:38 +02:00
|
|
|
html += '</table>';
|
2013-05-30 19:45:10 +02:00
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
document.getElementById('plane_detail').innerHTML = html;
|
|
|
|
}
|
2013-05-11 12:15:09 +02:00
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Right now we have no means to validate the speed is good
|
|
|
|
// Want to return (n/a) when we dont have it
|
|
|
|
// TODO: Edit C code to add a valid speed flag
|
|
|
|
// TODO: Edit js code to use said flag
|
|
|
|
function normalizeSpeed(speed, valid) {
|
|
|
|
return speed
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Returns back a long string, short string, and the track if we have a vaild track path
|
|
|
|
function normalizeTrack(track, valid){
|
|
|
|
x = []
|
|
|
|
if ((track > -1) && (track < 22.5)) {
|
|
|
|
x = ["North", "N", track]
|
|
|
|
}
|
|
|
|
if ((track > 22.5) && (track < 67.5)) {
|
|
|
|
x = ["North East", "NE", track]
|
|
|
|
}
|
|
|
|
if ((track > 67.5) && (track < 112.5)) {
|
|
|
|
x = ["East", "E", track]
|
|
|
|
}
|
|
|
|
if ((track > 112.5) && (track < 157.5)) {
|
|
|
|
x = ["South East", "SE", track]
|
|
|
|
}
|
|
|
|
if ((track > 157.5) && (track < 202.5)) {
|
|
|
|
x = ["South", "S", track]
|
|
|
|
}
|
|
|
|
if ((track > 202.5) && (track < 247.5)) {
|
|
|
|
x = ["South West", "SW", track]
|
|
|
|
}
|
|
|
|
if ((track > 247.5) && (track < 292.5)) {
|
|
|
|
x = ["West", "W", track]
|
|
|
|
}
|
|
|
|
if ((track > 292.5) && (track < 337.5)) {
|
|
|
|
x = ["North West", "NW", track]
|
|
|
|
}
|
|
|
|
if ((track > 337.5) && (track < 361)) {
|
|
|
|
x = ["North", "N", track]
|
|
|
|
}
|
|
|
|
if (!valid) {
|
|
|
|
x = [" ", "n/a", ""]
|
|
|
|
}
|
|
|
|
return x
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Refeshes the larger table of all the planes
|
2013-05-11 12:15:09 +02:00
|
|
|
function refreshTableInfo() {
|
2013-05-18 23:54:59 +02:00
|
|
|
var html = '<table id="tableinfo" width="100%">';
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '<thead style="background-color: #BBBBBB; cursor: pointer;">';
|
|
|
|
html += '<td onclick="setASC_DESC(\'0\');sortTable(\'tableinfo\',\'0\');">ICAO</td>';
|
2013-05-18 23:54:59 +02:00
|
|
|
html += '<td onclick="setASC_DESC(\'1\');sortTable(\'tableinfo\',\'1\');">Flight</td>';
|
2013-05-30 11:22:52 +02:00
|
|
|
html += '<td onclick="setASC_DESC(\'2\');sortTable(\'tableinfo\',\'2\');" ' +
|
|
|
|
'align="right">Squawk</td>';
|
|
|
|
html += '<td onclick="setASC_DESC(\'3\');sortTable(\'tableinfo\',\'3\');" ' +
|
|
|
|
'align="right">Altitude</td>';
|
|
|
|
html += '<td onclick="setASC_DESC(\'4\');sortTable(\'tableinfo\',\'4\');" ' +
|
|
|
|
'align="right">Speed</td>';
|
2014-07-17 03:42:02 +02:00
|
|
|
// Add distance column header to table if site coordinates are provided
|
|
|
|
if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
|
|
|
|
html += '<td onclick="setASC_DESC(\'5\');sortTable(\'tableinfo\',\'5\');" ' +
|
|
|
|
'align="right">Distance</td>';
|
|
|
|
}
|
|
|
|
html += '<td onclick="setASC_DESC(\'5\');sortTable(\'tableinfo\',\'6\');" ' +
|
2013-05-30 11:22:52 +02:00
|
|
|
'align="right">Track</td>';
|
2014-07-17 03:42:02 +02:00
|
|
|
html += '<td onclick="setASC_DESC(\'6\');sortTable(\'tableinfo\',\'7\');" ' +
|
2013-05-30 11:22:52 +02:00
|
|
|
'align="right">Msgs</td>';
|
2014-07-17 03:42:02 +02:00
|
|
|
html += '<td onclick="setASC_DESC(\'7\');sortTable(\'tableinfo\',\'8\');" ' +
|
2013-05-30 11:22:52 +02:00
|
|
|
'align="right">Seen</td></thead><tbody>';
|
2013-05-21 22:28:16 +02:00
|
|
|
for (var tablep in Planes) {
|
|
|
|
var tableplane = Planes[tablep]
|
|
|
|
if (!tableplane.reapable) {
|
|
|
|
var specialStyle = "";
|
|
|
|
// Is this the plane we selected?
|
|
|
|
if (tableplane.icao == SelectedPlane) {
|
|
|
|
specialStyle += " selected";
|
|
|
|
}
|
|
|
|
// Lets hope we never see this... Aircraft Hijacking
|
|
|
|
if (tableplane.squawk == 7500) {
|
|
|
|
specialStyle += " squawk7500";
|
|
|
|
}
|
|
|
|
// Radio Failure
|
|
|
|
if (tableplane.squawk == 7600) {
|
|
|
|
specialStyle += " squawk7600";
|
|
|
|
}
|
|
|
|
// Emergancy
|
|
|
|
if (tableplane.squawk == 7700) {
|
|
|
|
specialStyle += " squawk7700";
|
|
|
|
}
|
2013-05-25 13:06:31 +02:00
|
|
|
|
|
|
|
if (tableplane.vPosition == true) {
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '<tr class="plane_table_row vPosition' + specialStyle + '">';
|
2013-05-25 13:06:31 +02:00
|
|
|
} else {
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '<tr class="plane_table_row ' + specialStyle + '">';
|
2013-05-25 13:06:31 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '<td>' + tableplane.icao + '</td>';
|
|
|
|
html += '<td>' + tableplane.flight + '</td>';
|
2013-05-25 13:06:31 +02:00
|
|
|
if (tableplane.squawk != '0000' ) {
|
|
|
|
html += '<td align="right">' + tableplane.squawk + '</td>';
|
|
|
|
} else {
|
|
|
|
html += '<td align="right"> </td>';
|
|
|
|
}
|
2013-05-28 11:15:18 +02:00
|
|
|
|
|
|
|
if (Metric) {
|
|
|
|
html += '<td align="right">' + Math.round(tableplane.altitude / 3.2828) + '</td>';
|
|
|
|
html += '<td align="right">' + Math.round(tableplane.speed * 1.852) + '</td>';
|
|
|
|
} else {
|
|
|
|
html += '<td align="right">' + tableplane.altitude + '</td>';
|
|
|
|
html += '<td align="right">' + tableplane.speed + '</td>';
|
|
|
|
}
|
2014-07-17 03:42:02 +02:00
|
|
|
// Add distance column to table if site coordinates are provided
|
|
|
|
if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
|
|
|
|
html += '<td align="right">';
|
|
|
|
if (tableplane.vPosition) {
|
|
|
|
var siteLatLon = new google.maps.LatLng(SiteLat, SiteLon);
|
|
|
|
var planeLatLon = new google.maps.LatLng(tableplane.latitude, tableplane.longitude);
|
|
|
|
var dist = google.maps.geometry.spherical.computeDistanceBetween (siteLatLon, planeLatLon);
|
|
|
|
if (Metric) {
|
|
|
|
dist /= 1000;
|
|
|
|
} else {
|
|
|
|
dist /= 1852;
|
|
|
|
}
|
|
|
|
dist = (Math.round((dist)*10)/10).toFixed(1);
|
|
|
|
html += dist;
|
|
|
|
} else {
|
|
|
|
html += '0';
|
|
|
|
}
|
|
|
|
html += '</td>';
|
|
|
|
}
|
2013-05-28 11:15:18 +02:00
|
|
|
|
2013-05-25 22:44:40 +02:00
|
|
|
html += '<td align="right">';
|
|
|
|
if (tableplane.vTrack) {
|
|
|
|
html += normalizeTrack(tableplane.track, tableplane.vTrack)[2];
|
2013-09-27 11:57:26 +02:00
|
|
|
// html += ' (' + normalizeTrack(tableplane.track, tableplane.vTrack)[1] + ')';
|
2013-05-25 22:44:40 +02:00
|
|
|
} else {
|
|
|
|
html += ' ';
|
|
|
|
}
|
|
|
|
html += '</td>';
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '<td align="right">' + tableplane.messages + '</td>';
|
|
|
|
html += '<td align="right">' + tableplane.seen + '</td>';
|
|
|
|
html += '</tr>';
|
2013-05-18 23:54:59 +02:00
|
|
|
}
|
|
|
|
}
|
2013-05-21 22:28:16 +02:00
|
|
|
html += '</tbody></table>';
|
2013-05-18 23:54:59 +02:00
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
document.getElementById('planes_table').innerHTML = html;
|
2013-05-18 23:54:59 +02:00
|
|
|
|
2013-06-02 15:51:38 +02:00
|
|
|
if (SpecialSquawk) {
|
|
|
|
$('#SpecialSquawkWarning').css('display', 'inline');
|
|
|
|
} else {
|
|
|
|
$('#SpecialSquawkWarning').css('display', 'none');
|
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
// Click event for table
|
|
|
|
$('#planes_table').find('tr').click( function(){
|
2013-05-18 23:54:59 +02:00
|
|
|
var hex = $(this).find('td:first').text();
|
2013-05-21 22:28:16 +02:00
|
|
|
if (hex != "ICAO") {
|
|
|
|
selectPlaneByHex(hex);
|
2013-05-25 22:44:40 +02:00
|
|
|
refreshTableInfo();
|
|
|
|
refreshSelected();
|
2013-05-21 22:28:16 +02:00
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
sortTable("tableinfo");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Credit goes to a co-worker that needed a similar functions for something else
|
|
|
|
// we get a copy of it free ;)
|
|
|
|
function setASC_DESC(iCol) {
|
|
|
|
if(iSortCol==iCol) {
|
|
|
|
bSortASC=!bSortASC;
|
|
|
|
} else {
|
|
|
|
bSortASC=bDefaultSortASC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function sortTable(szTableID,iCol) {
|
|
|
|
//if iCol was not provided, and iSortCol is not set, assign default value
|
|
|
|
if (typeof iCol==='undefined'){
|
|
|
|
if(iSortCol!=-1){
|
|
|
|
var iCol=iSortCol;
|
2014-07-17 03:42:02 +02:00
|
|
|
} else if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
|
|
|
|
var iCol=5;
|
2013-05-18 23:54:59 +02:00
|
|
|
} else {
|
|
|
|
var iCol=iDefaultSortCol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//retrieve passed table element
|
|
|
|
var oTbl=document.getElementById(szTableID).tBodies[0];
|
|
|
|
var aStore=[];
|
|
|
|
|
|
|
|
//If supplied col # is greater than the actual number of cols, set sel col = to last col
|
2013-05-25 13:06:31 +02:00
|
|
|
if (typeof oTbl.rows[0] !== 'undefined' && oTbl.rows[0].cells.length <= iCol) {
|
2013-05-18 23:54:59 +02:00
|
|
|
iCol=(oTbl.rows[0].cells.length-1);
|
2013-05-25 13:06:31 +02:00
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
|
|
|
|
//store the col #
|
|
|
|
iSortCol=iCol;
|
|
|
|
|
|
|
|
//determine if we are delaing with numerical, or alphanumeric content
|
2013-05-25 13:06:31 +02:00
|
|
|
var bNumeric = false;
|
|
|
|
if ((typeof oTbl.rows[0] !== 'undefined') &&
|
|
|
|
(!isNaN(parseFloat(oTbl.rows[0].cells[iSortCol].textContent ||
|
|
|
|
oTbl.rows[0].cells[iSortCol].innerText)))) {
|
|
|
|
bNumeric = true;
|
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
|
|
|
|
//loop through the rows, storing each one inro aStore
|
|
|
|
for (var i=0,iLen=oTbl.rows.length;i<iLen;i++){
|
|
|
|
var oRow=oTbl.rows[i];
|
|
|
|
vColData=bNumeric?parseFloat(oRow.cells[iSortCol].textContent||oRow.cells[iSortCol].innerText):String(oRow.cells[iSortCol].textContent||oRow.cells[iSortCol].innerText);
|
|
|
|
aStore.push([vColData,oRow]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//sort aStore ASC/DESC based on value of bSortASC
|
2013-05-25 13:06:31 +02:00
|
|
|
if (bNumeric) { //numerical sort
|
2013-05-18 23:54:59 +02:00
|
|
|
aStore.sort(function(x,y){return bSortASC?x[0]-y[0]:y[0]-x[0];});
|
2013-05-25 13:06:31 +02:00
|
|
|
} else { //alpha sort
|
2013-05-18 23:54:59 +02:00
|
|
|
aStore.sort();
|
2013-05-25 13:06:31 +02:00
|
|
|
if(!bSortASC) {
|
2013-05-18 23:54:59 +02:00
|
|
|
aStore.reverse();
|
2013-05-25 13:06:31 +02:00
|
|
|
}
|
2013-05-18 23:54:59 +02:00
|
|
|
}
|
2013-05-12 14:15:18 +02:00
|
|
|
|
2013-05-18 23:54:59 +02:00
|
|
|
//rewrite the table rows to the passed table element
|
|
|
|
for(var i=0,iLen=aStore.length;i<iLen;i++){
|
|
|
|
oTbl.appendChild(aStore[i][1]);
|
|
|
|
}
|
|
|
|
aStore=null;
|
2013-05-11 12:15:09 +02:00
|
|
|
}
|
|
|
|
|
2013-05-21 22:28:16 +02:00
|
|
|
function selectPlaneByHex(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;
|
2013-05-22 19:09:12 +02:00
|
|
|
Planes[SelectedPlane].funcClearLine();
|
2013-05-24 04:15:37 +02:00
|
|
|
Planes[SelectedPlane].markerColor = MarkerColor;
|
|
|
|
// If the selected has a marker, make it not stand out
|
|
|
|
if (Planes[SelectedPlane].marker) {
|
|
|
|
Planes[SelectedPlane].marker.setIcon(Planes[SelectedPlane].funcGetIcon());
|
|
|
|
}
|
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.
|
|
|
|
if (String(SelectedPlane) != String(hex)) {
|
|
|
|
// Assign the new selected
|
|
|
|
SelectedPlane = hex;
|
|
|
|
Planes[SelectedPlane].is_selected = true;
|
|
|
|
// If the selected has a marker, make it stand out
|
|
|
|
if (Planes[SelectedPlane].marker) {
|
|
|
|
Planes[SelectedPlane].funcUpdateLines();
|
|
|
|
Planes[SelectedPlane].marker.setIcon(Planes[SelectedPlane].funcGetIcon());
|
|
|
|
}
|
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
|
|
|
}
|
2013-05-27 10:36:23 +02:00
|
|
|
refreshSelected();
|
|
|
|
refreshTableInfo();
|
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');
|
|
|
|
}
|