Merge remote-tracking branch 'csfa/map_enhancements' into dev
This commit is contained in:
commit
7dee192157
|
@ -11,14 +11,11 @@ PlaneCountInTitle = true;
|
||||||
MessageRateInTitle = false;
|
MessageRateInTitle = false;
|
||||||
|
|
||||||
// -- Output Settings -------------------------------------
|
// -- Output Settings -------------------------------------
|
||||||
// Show metric values
|
// The DisplayUnits setting controls whether nautical (ft, NM, knots),
|
||||||
// The Metric setting controls whether metric (m, km, km/h) or
|
// metric (m, km, km/h) or imperial (ft, mi, mph) units are used in the
|
||||||
// imperial (ft, NM, knots) units are used in the plane table
|
// plane table and in the detailed plane info. Valid values are
|
||||||
// and in the detailed plane info. If ShowOtherUnits is true,
|
// "nautical", "metric", or "imperial".
|
||||||
// then the other unit will also be shown in the detailed plane
|
DisplayUnits = "nautical";
|
||||||
// info.
|
|
||||||
Metric = false;
|
|
||||||
ShowOtherUnits = true;
|
|
||||||
|
|
||||||
// -- Map settings ----------------------------------------
|
// -- Map settings ----------------------------------------
|
||||||
// These settings are overridden by any position information
|
// These settings are overridden by any position information
|
||||||
|
@ -98,7 +95,7 @@ OutlineADSBColor = '#000000';
|
||||||
OutlineMlatColor = '#4040FF';
|
OutlineMlatColor = '#4040FF';
|
||||||
|
|
||||||
SiteCircles = true; // true to show circles (only shown if the center marker is shown)
|
SiteCircles = true; // true to show circles (only shown if the center marker is shown)
|
||||||
// In nautical miles or km (depending settings value 'Metric')
|
// In miles, nautical miles, or km (depending settings value 'DisplayUnits')
|
||||||
SiteCirclesDistances = new Array(100,150,200);
|
SiteCirclesDistances = new Array(100,150,200);
|
||||||
|
|
||||||
// Show the clocks at the top of the righthand pane? You can disable the clocks if you want here
|
// Show the clocks at the top of the righthand pane? You can disable the clocks if you want here
|
||||||
|
|
3
public_html/db/aircraft_types/README
Normal file
3
public_html/db/aircraft_types/README
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Aircraft type data was retrieved from http://www.icao.int/publications/DOC8643/ and converted to JSON format.
|
||||||
|
|
||||||
|
Data was last updated on 2016-03-23 and retrieved on 2016-08-25.
|
1
public_html/db/aircraft_types/icao_aircraft_types.json
Normal file
1
public_html/db/aircraft_types/icao_aircraft_types.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -22,6 +22,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _aircraft_cache = {};
|
var _aircraft_cache = {};
|
||||||
|
var _aircraft_type_cache = null;
|
||||||
|
|
||||||
function getAircraftData(icao) {
|
function getAircraftData(icao) {
|
||||||
var defer;
|
var defer;
|
||||||
|
@ -48,7 +49,7 @@ function request_from_db(icao, level, defer) {
|
||||||
var subkey;
|
var subkey;
|
||||||
|
|
||||||
if (dkey in data) {
|
if (dkey in data) {
|
||||||
defer.resolve(data[dkey]);
|
getIcaoAircraftTypeData(data[dkey], defer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +68,36 @@ function request_from_db(icao, level, defer) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getIcaoAircraftTypeData(aircraftData, defer) {
|
||||||
|
if (_aircraft_type_cache === null) {
|
||||||
|
$.getJSON("db/aircraft_types/icao_aircraft_types.json")
|
||||||
|
.done(function(typeLookupData) {
|
||||||
|
_aircraft_type_cache = typeLookupData;
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
lookupIcaoAircraftType(aircraftData, defer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lookupIcaoAircraftType(aircraftData, defer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookupIcaoAircraftType(aircraftData, defer) {
|
||||||
|
if (_aircraft_type_cache !== null && "t" in aircraftData) {
|
||||||
|
var typeDesignator = aircraftData.t.toUpperCase();
|
||||||
|
if (typeDesignator in _aircraft_type_cache) {
|
||||||
|
var typeData = _aircraft_type_cache[typeDesignator];
|
||||||
|
if (typeData.desc != undefined && typeData.desc != null && typeData.desc.length == 3) {
|
||||||
|
aircraftData.desc = typeData.desc;
|
||||||
|
}
|
||||||
|
aircraftData.wtc = typeData.wtc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defer.resolve(aircraftData);
|
||||||
|
}
|
||||||
|
|
||||||
var _request_count = 0;
|
var _request_count = 0;
|
||||||
var _request_queue = [];
|
var _request_queue = [];
|
||||||
var _request_cache = {};
|
var _request_cache = {};
|
||||||
|
|
|
@ -8,8 +8,23 @@ var DOWN_TRIANGLE='\u25bc'; // U+25BC BLACK DOWN-POINTING TRIANGLE
|
||||||
|
|
||||||
var TrackDirections = ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"];
|
var TrackDirections = ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"];
|
||||||
|
|
||||||
|
var UnitLabels = {
|
||||||
|
'altitude': { metric: "m", imperial: "ft", nautical: "ft"},
|
||||||
|
'speed': { metric: "km/h", imperial: "mph", nautical: "kt" },
|
||||||
|
'distance': { metric: "km", imperial: "mi", nautical: "NM" },
|
||||||
|
'verticalRate': { metric: "m/s", imperial: "ft/min", nautical: "ft/min" }
|
||||||
|
};
|
||||||
|
|
||||||
// formatting helpers
|
// formatting helpers
|
||||||
|
|
||||||
|
function get_unit_label(quantity, systemOfMeasurement) {
|
||||||
|
var labels = UnitLabels[quantity];
|
||||||
|
if (labels !== undefined && labels[systemOfMeasurement] !== undefined) {
|
||||||
|
return labels[systemOfMeasurement];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
// track in degrees (0..359)
|
// track in degrees (0..359)
|
||||||
function format_track_brief(track) {
|
function format_track_brief(track) {
|
||||||
if (track === null){
|
if (track === null){
|
||||||
|
@ -29,9 +44,8 @@ function format_track_long(track) {
|
||||||
return Math.round(track) + DEGREES + NBSP + "(" + TrackDirections[trackDir] + ")";
|
return Math.round(track) + DEGREES + NBSP + "(" + TrackDirections[trackDir] + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// altitude (input: alt in feet)
|
// alt in feet
|
||||||
// brief will always show either Metric or Imperial
|
function format_altitude_brief(alt, vr, displayUnits) {
|
||||||
function format_altitude_brief(alt, vr) {
|
|
||||||
var alt_text;
|
var alt_text;
|
||||||
|
|
||||||
if (alt === null){
|
if (alt === null){
|
||||||
|
@ -40,31 +54,24 @@ function format_altitude_brief(alt, vr) {
|
||||||
return "ground";
|
return "ground";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Metric) {
|
alt_text = Math.round(convert_altitude(alt, displayUnits)) + NBSP;
|
||||||
alt_text = Math.round(alt / 3.2828) + NBSP; // Altitude to meters
|
|
||||||
} else {
|
|
||||||
alt_text = Math.round(alt) + NBSP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vertical Rate Triangle
|
// Vertical Rate Triangle
|
||||||
|
var verticalRateTriangle = "<span class=\"verticalRateTriangle\">";
|
||||||
if (vr > 128){
|
if (vr > 128){
|
||||||
return alt_text + UP_TRIANGLE;
|
verticalRateTriangle += UP_TRIANGLE;
|
||||||
} else if (vr < -128){
|
} else if (vr < -128){
|
||||||
return alt_text + DOWN_TRIANGLE;
|
verticalRateTriangle += DOWN_TRIANGLE;
|
||||||
} else {
|
} else {
|
||||||
return alt_text + NBSP;
|
verticalRateTriangle += NBSP;
|
||||||
}
|
}
|
||||||
|
verticalRateTriangle += "</span>"
|
||||||
|
|
||||||
|
return alt_text + verticalRateTriangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// alt in ft
|
// alt in feet
|
||||||
function _alt_to_unit(alt, m) {
|
function format_altitude_long(alt, vr, displayUnits) {
|
||||||
if (m)
|
|
||||||
return Math.round(alt / 3.2828) + NBSP + "m";
|
|
||||||
else
|
|
||||||
return Math.round(alt) + NBSP + "ft";
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_altitude_long(alt, vr) {
|
|
||||||
var alt_text = "";
|
var alt_text = "";
|
||||||
|
|
||||||
if (alt === null) {
|
if (alt === null) {
|
||||||
|
@ -73,13 +80,7 @@ function format_altitude_long(alt, vr) {
|
||||||
return "on ground";
|
return "on ground";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary unit
|
alt_text = Math.round(convert_altitude(alt, displayUnits)) + NBSP + get_unit_label("altitude", displayUnits);
|
||||||
alt_text = _alt_to_unit(alt, Metric);
|
|
||||||
|
|
||||||
// Secondary unit
|
|
||||||
if (ShowOtherUnits) {
|
|
||||||
alt_text = alt_text + ' | ' + _alt_to_unit(alt, !Metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vr > 128) {
|
if (vr > 128) {
|
||||||
return UP_TRIANGLE + NBSP + alt_text;
|
return UP_TRIANGLE + NBSP + alt_text;
|
||||||
|
@ -90,83 +91,123 @@ function format_altitude_long(alt, vr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//input: speed in kts
|
// alt in feet
|
||||||
function format_speed_brief(speed) {
|
function convert_altitude(alt, displayUnits) {
|
||||||
|
if (displayUnits === "metric") {
|
||||||
|
return alt / 3.2808; // feet to meters
|
||||||
|
}
|
||||||
|
|
||||||
|
return alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// speed in knots
|
||||||
|
function format_speed_brief(speed, displayUnits) {
|
||||||
if (speed === null) {
|
if (speed === null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Metric) {
|
return Math.round(convert_speed(speed, displayUnits));
|
||||||
return Math.round(speed * 1.852); // knots to kilometers per hour
|
|
||||||
} else {
|
|
||||||
return Math.round(speed); // knots
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// speed in kts
|
// speed in knots
|
||||||
|
function format_speed_long(speed, displayUnits) {
|
||||||
function _speed_to_unit(speed, m) {
|
|
||||||
if (m)
|
|
||||||
return Math.round(speed * 1.852) + NBSP + "km/h";
|
|
||||||
else
|
|
||||||
return Math.round(speed) + NBSP + "kt";
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_speed_long(speed) {
|
|
||||||
if (speed === null) {
|
if (speed === null) {
|
||||||
return "n/a";
|
return "n/a";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary unit
|
var speed_text = Math.round(convert_speed(speed, displayUnits)) + NBSP + get_unit_label("speed", displayUnits);
|
||||||
var speed_text = _speed_to_unit(speed, Metric);
|
|
||||||
|
|
||||||
// Secondary unit
|
|
||||||
if (ShowOtherUnits) {
|
|
||||||
speed_text = speed_text + ' | ' + _speed_to_unit(speed, !Metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
return speed_text;
|
return speed_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// speed in knots
|
||||||
|
function convert_speed(speed, displayUnits) {
|
||||||
|
if (displayUnits === "metric") {
|
||||||
|
return speed * 1.852; // knots to kilometers per hour
|
||||||
|
}
|
||||||
|
else if (displayUnits === "imperial") {
|
||||||
|
return speed * 1.151; // knots to miles per hour
|
||||||
|
}
|
||||||
|
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
// dist in meters
|
// dist in meters
|
||||||
function format_distance_brief(dist) {
|
function format_distance_brief(dist, displayUnits) {
|
||||||
if (dist === null) {
|
if (dist === null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Metric) {
|
return convert_distance(dist, displayUnits).toFixed(1);
|
||||||
return (dist/1000).toFixed(1); // meters to kilometers
|
|
||||||
} else {
|
|
||||||
return (dist/1852).toFixed(1); // meters to nautocal miles
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dist in metres
|
// dist in meters
|
||||||
|
function format_distance_long(dist, displayUnits) {
|
||||||
function _dist_to_unit(dist, m) {
|
|
||||||
if (m)
|
|
||||||
return (dist/1000).toFixed(1) + NBSP + "km";
|
|
||||||
else
|
|
||||||
return (dist/1852).toFixed(1) + NBSP + "NM";
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_distance_long(dist) {
|
|
||||||
if (dist === null) {
|
if (dist === null) {
|
||||||
return "n/a";
|
return "n/a";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary unit
|
var dist_text = convert_distance(dist, displayUnits).toFixed(1) + NBSP + get_unit_label("distance", displayUnits);
|
||||||
var dist_text = _dist_to_unit(dist, Metric);
|
|
||||||
|
|
||||||
// Secondary unit
|
|
||||||
if (ShowOtherUnits) {
|
|
||||||
dist_text = dist_text + ' | ' + _dist_to_unit(dist, !Metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dist_text;
|
return dist_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dist in meters
|
||||||
|
function convert_distance(dist, displayUnits) {
|
||||||
|
if (displayUnits === "metric") {
|
||||||
|
return (dist / 1000); // meters to kilometers
|
||||||
|
}
|
||||||
|
else if (displayUnits === "imperial") {
|
||||||
|
return (dist / 1609); // meters to miles
|
||||||
|
}
|
||||||
|
return (dist / 1852); // meters to nautical miles
|
||||||
|
}
|
||||||
|
|
||||||
|
// rate in ft/min
|
||||||
|
function format_vert_rate_brief(rate, displayUnits) {
|
||||||
|
if (rate === null || rate === undefined) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return convert_vert_rate(rate, displayUnits).toFixed(displayUnits === "metric" ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rate in ft/min
|
||||||
|
function format_vert_rate_long(rate, displayUnits) {
|
||||||
|
if (rate === null || rate === undefined) {
|
||||||
|
return "n/a";
|
||||||
|
}
|
||||||
|
|
||||||
|
var rate_text = convert_vert_rate(rate, displayUnits).toFixed(displayUnits === "metric" ? 1 : 0) + NBSP + get_unit_label("verticalRate", displayUnits);
|
||||||
|
|
||||||
|
return rate_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rate in ft/min
|
||||||
|
function convert_vert_rate(rate, displayUnits) {
|
||||||
|
if (displayUnits === "metric") {
|
||||||
|
return (rate / 196.85); // ft/min to m/s
|
||||||
|
}
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
// p is a [lon, lat] coordinate
|
// p is a [lon, lat] coordinate
|
||||||
function format_latlng(p) {
|
function format_latlng(p) {
|
||||||
return p[1].toFixed(3) + DEGREES + "," + NBSP + p[0].toFixed(3) + DEGREES;
|
return p[1].toFixed(3) + DEGREES + "," + NBSP + p[0].toFixed(3) + DEGREES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function format_data_source(source) {
|
||||||
|
switch (source) {
|
||||||
|
case 'mlat':
|
||||||
|
return "MLAT";
|
||||||
|
case 'adsb':
|
||||||
|
return "ADS-B";
|
||||||
|
case 'mode_s':
|
||||||
|
return "Mode S";
|
||||||
|
case 'mode_ac':
|
||||||
|
return "Mode A/C";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
BIN
public_html/images/hide_sidebar_active_48x40.png
Normal file
BIN
public_html/images/hide_sidebar_active_48x40.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
public_html/images/hide_sidebar_inactive_48x40.png
Normal file
BIN
public_html/images/hide_sidebar_inactive_48x40.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
public_html/images/show_sidebar_active_48x40.png
Normal file
BIN
public_html/images/show_sidebar_active_48x40.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
BIN
public_html/images/show_sidebar_inactive_48x40.png
Normal file
BIN
public_html/images/show_sidebar_inactive_48x40.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -6,6 +6,7 @@
|
||||||
<link rel="stylesheet" href="jquery/jquery-ui-1.11.4-smoothness.css" />
|
<link rel="stylesheet" href="jquery/jquery-ui-1.11.4-smoothness.css" />
|
||||||
<script src="jquery/jquery-3.0.0.min.js"></script>
|
<script src="jquery/jquery-3.0.0.min.js"></script>
|
||||||
<script src="jquery/jquery-ui-1.11.4.min.js"></script>
|
<script src="jquery/jquery-ui-1.11.4.min.js"></script>
|
||||||
|
<script src="jquery/plugins/jquery.validate.min.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="ol3/ol-3.17.1.css" type="text/css" />
|
<link rel="stylesheet" href="ol3/ol-3.17.1.css" type="text/css" />
|
||||||
<script src="ol3/ol-3.17.1.js" type="text/javascript"></script>
|
<script src="ol3/ol-3.17.1.js" type="text/javascript"></script>
|
||||||
|
@ -45,60 +46,7 @@
|
||||||
<input type="hidden" name="submit" value="submit">
|
<input type="hidden" name="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div id="map_container">
|
<div id="layout_container">
|
||||||
<div id="map_canvas"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="sidebar_container">
|
|
||||||
<div id="sidebar_canvas">
|
|
||||||
<div id="sudo_buttons">
|
|
||||||
<table style="width: 100%">
|
|
||||||
<tr>
|
|
||||||
<td style="width: 150px; text-align: center;" class="pointer">
|
|
||||||
[ <span onclick="resetMap();">Reset Map</span> ]
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div> <!-- sudo_buttons -->
|
|
||||||
|
|
||||||
<div id="dump1090_infoblock">
|
|
||||||
<table style="width: 100%">
|
|
||||||
<tr class="infoblock_heading">
|
|
||||||
<td>
|
|
||||||
<b id="infoblock_name">FlightAware dump1090</b>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: right">
|
|
||||||
<a href="https://github.com/flightaware/dump1090" id="dump1090_version" target="_blank"></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="infoblock_body">
|
|
||||||
<td> </td>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="infoblock_body dim">
|
|
||||||
<td>(no aircraft selected)</td>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="infoblock_body">
|
|
||||||
<td> </td>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="infoblock_body">
|
|
||||||
<td>Aircraft (total): <span id="dump1090_total_ac">n/a</span></td>
|
|
||||||
<td>Messages: <span id="dump1090_message_rate">n/a</span>/sec</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="infoblock_body">
|
|
||||||
<td>(with positions): <span id="dump1090_total_ac_positions">n/a</span></td>
|
|
||||||
<td>History: <span id="dump1090_total_history">n/a</span> positions</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div> <!-- dump1090_infoblock -->
|
|
||||||
|
|
||||||
<div id="selected_infoblock" class="hidden">
|
<div id="selected_infoblock" class="hidden">
|
||||||
<table style="width: 100%">
|
<table style="width: 100%">
|
||||||
<tr class="infoblock_heading">
|
<tr class="infoblock_heading">
|
||||||
|
@ -118,7 +66,7 @@
|
||||||
<span id="selected_registration"></span>
|
<span id="selected_registration"></span>
|
||||||
<span id="selected_icaotype"></span>
|
<span id="selected_icaotype"></span>
|
||||||
<span id="selected_emergency"></span>
|
<span id="selected_emergency"></span>
|
||||||
<a id="selected_flightaware_link" href="" target="_blank">[FlightAware]</a>
|
<span id="selected_flightaware_link"></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -136,6 +84,11 @@
|
||||||
<td>RSSI: <span id="selected_rssi">n/a</span></td>
|
<td>RSSI: <span id="selected_rssi">n/a</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr class="infoblock_body">
|
||||||
|
<td>Vertical rate: <span id="selected_vertical_rate">n/a</span></td>
|
||||||
|
<td>Messages: <span id="selected_message_count">n/a</span></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr class="infoblock_body">
|
<tr class="infoblock_body">
|
||||||
<td>Track: <span id="selected_track">n/a</span></td>
|
<td>Track: <span id="selected_track">n/a</span></td>
|
||||||
<td>Last seen: <span id="selected_seen">n/a</span></td>
|
<td>Last seen: <span id="selected_seen">n/a</span></td>
|
||||||
|
@ -148,37 +101,124 @@
|
||||||
<tr class="infoblock_body">
|
<tr class="infoblock_body">
|
||||||
<td colspan="2">Distance from Site: <span id="selected_sitedist">n/a</span></td>
|
<td colspan="2">Distance from Site: <span id="selected_sitedist">n/a</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="infoblock_body">
|
||||||
|
<td colspan="2"><span id="selected_photo_link"></span></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div> <!-- selected_infoblock -->
|
</div> <!-- selected_infoblock -->
|
||||||
|
<div id="map_container">
|
||||||
|
<div id="map_canvas"></div>
|
||||||
|
<a id="toggle_sidebar_button" class="hide_sidebar" href="#"></a>
|
||||||
|
<a id="expand_sidebar_button" href="#"></a>
|
||||||
|
</div>
|
||||||
|
<div id="sidebar_container">
|
||||||
|
<div id="splitter" class="ui-resizable-handle ui-resizable-w"></div>
|
||||||
|
<div id="sidebar_canvas">
|
||||||
|
|
||||||
|
<div id="dump1090_infoblock">
|
||||||
|
<table style="width: 100%">
|
||||||
|
<tr class="infoblock_heading">
|
||||||
|
<td>
|
||||||
|
<b id="infoblock_name">FlightAware dump1090</b>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span id="show_map_button" class="sidebarButton pointer">Show Map</span>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right">
|
||||||
|
<a href="https://github.com/flightaware/dump1090" id="dump1090_version" target="_blank"></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div id="sudo_buttons">
|
||||||
|
<span class="sidebarButton pointer" onclick="resetMap();">Reset Map</span>
|
||||||
|
<span class="sidebarButton pointer" onclick="selectAllPlanes();">Select All</span>
|
||||||
|
<span class="sidebarButton pointer" onclick="deselectAllPlanes();">Select None</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr class="infoblock_body">
|
||||||
|
<td>Aircraft (total): <span id="dump1090_total_ac">n/a</span></td>
|
||||||
|
<td>Messages: <span id="dump1090_message_rate">n/a</span>/sec</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr class="infoblock_body">
|
||||||
|
<td>(with positions): <span id="dump1090_total_ac_positions">n/a</span></td>
|
||||||
|
<td>History: <span id="dump1090_total_history">n/a</span> positions</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div> <!-- dump1090_infoblock -->
|
||||||
|
|
||||||
|
<div id="units_container">
|
||||||
|
<label for="units_selector">Units:</label>
|
||||||
|
<select name="units_selector" id="units_selector">
|
||||||
|
<option value="nautical">Aeronautical</option>
|
||||||
|
<option value="metric">Metric</option>
|
||||||
|
<option value="imperial">Imperial</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form id="altitude_filter_form">
|
||||||
|
<label>Filter by altitude:</label>
|
||||||
|
<input id="altitude_filter_min" name="minAltitude" type="text" class="altitudeFilterInput" maxlength="5">
|
||||||
|
<label for="minAltitude" class="altitudeUnit"></label>
|
||||||
|
<span> to </span>
|
||||||
|
<input id="altitude_filter_max" name="maxAltitude" type="text" class="altitudeFilterInput" maxlength="5">
|
||||||
|
<label for="maxAltitude" class="altitudeUnit"></label>
|
||||||
|
<button type="submit">Filter</button>
|
||||||
|
<button id="altitude_filter_reset_button">Reset</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div id="planes_table">
|
<div id="planes_table">
|
||||||
<table id="tableinfo" style="width: 100%">
|
<table id="tableinfo" style="width: 100%">
|
||||||
<thead style="background-color: #BBBBBB; cursor: pointer;">
|
<thead class="aircraft_table_header">
|
||||||
<tr>
|
<tr>
|
||||||
<td id="icao" onclick="sortByICAO();">ICAO</td>
|
<td id="icao" onclick="sortByICAO();">ICAO</td>
|
||||||
<td id="flag" onclick="sortByCountry()"><!-- column for flag image --></td>
|
<td id="flag" onclick="sortByCountry()"><!-- column for flag image --></td>
|
||||||
<td id="flight" onclick="sortByFlight();">Flight</td>
|
<td id="flight" onclick="sortByFlight();">Ident</td>
|
||||||
<td id="squawk" onclick="sortBySquawk();" style="text-align: right">Squawk</td>
|
<td id="registration" onclick="sortByRegistration();">Registration</td>
|
||||||
<td id="altitude" onclick="sortByAltitude();" style="text-align: right">Altitude</td>
|
<td id="aircraft_type" onclick="sortByAircraftType();"> Aircraft type</td>
|
||||||
<td id="speed" onclick="sortBySpeed();" style="text-align: right">Speed</td>
|
<td id="squawk" onclick="sortBySquawk();">Squawk</td>
|
||||||
<td id="distance" onclick="sortByDistance();" style="text-align: right">Distance</td>
|
<td id="altitude" onclick="sortByAltitude();">Altitude (<span class="altitudeUnit"></span>)</td>
|
||||||
<td id="track" onclick="sortByTrack();" style="text-align: right">Track</td>
|
<td id="speed" onclick="sortBySpeed();">Speed (<span class="speedUnit"></span>)</td>
|
||||||
<td id="msgs" onclick="sortByMsgs();" style="text-align: right">Msgs</td>
|
<td id="vert_rate" onclick="sortByVerticalRate();">Vertical Rate (<span class="verticalRateUnit"></span>)</td>
|
||||||
<td id="seen" onclick="sortBySeen();" style="text-align: right">Age</td>
|
<td id="distance" onclick="sortByDistance();">Distance (<span class="distanceUnit"></span>)</td>
|
||||||
|
<td id="track" onclick="sortByTrack();">Track</td>
|
||||||
|
<td id="msgs" onclick="sortByMsgs();">Msgs</td>
|
||||||
|
<td id="seen" onclick="sortBySeen();">Age</td>
|
||||||
|
<td id="rssi" onclick="sortByRssi();">RSSI</td>
|
||||||
|
<td id="lat" onclick="sortByLatitude();">Latitude</td>
|
||||||
|
<td id="lon" onclick="sortByLongitude();">Longitude</td>
|
||||||
|
<td id="data_source" onclick="sortByDataSource();">Data Source</td>
|
||||||
|
<td id="airframes_mode_s_link">Airframes.org Link</td>
|
||||||
|
<td id="flightaware_mode_s_link">FlightAware Link</td>
|
||||||
|
<td id="flightaware_photo_link">Photos</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr id="plane_row_template" class="plane_table_row hidden">
|
<tr id="plane_row_template" class="plane_table_row hidden">
|
||||||
<td>ICAO</td>
|
<td style="text-transform: uppercase">ICAO</td>
|
||||||
<td><img style="width: 20px; height=12px" src="about:blank" alt="Flag"></td>
|
<td><img style="width: 20px; height=12px" src="about:blank" alt="Flag"></td>
|
||||||
<td>FLIGHT</td>
|
<td>FLIGHT</td>
|
||||||
|
<td>REGISTRATION</td>
|
||||||
|
<td>AIRCRAFT_TYPE</td>
|
||||||
<td style="text-align: right">SQUAWK</td>
|
<td style="text-align: right">SQUAWK</td>
|
||||||
<td style="text-align: right">ALTITUDE</td>
|
<td style="text-align: right">ALTITUDE</td>
|
||||||
<td style="text-align: right">SPEED</td>
|
<td style="text-align: right">SPEED</td>
|
||||||
|
<td style="text-align: right">VERT_RATE</td>
|
||||||
<td style="text-align: right">DISTANCE</td>
|
<td style="text-align: right">DISTANCE</td>
|
||||||
<td style="text-align: right">TRACK</td>
|
<td style="text-align: right">TRACK</td>
|
||||||
<td style="text-align: right">MSGS</td>
|
<td style="text-align: right">MSGS</td>
|
||||||
<td style="text-align: right">SEEN</td>
|
<td style="text-align: right">SEEN</td>
|
||||||
|
<td style="text-align: right">RSSI</td>
|
||||||
|
<td style="text-align: right">LAT</td>
|
||||||
|
<td style="text-align: right">LON</td>
|
||||||
|
<td style="text-align: right">DATA_SOURCE</td>
|
||||||
|
<td style="text-align: center">AIRFRAMES_MODE_S_LINK</td>
|
||||||
|
<td style="text-align: center">FLIGHTAWARE_MODE_S_LINK</td>
|
||||||
|
<td style="text-align: center">FLIGHTAWARE_PHOTO_LINK</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -186,6 +226,7 @@
|
||||||
|
|
||||||
</div> <!-- sidebar_canvas -->
|
</div> <!-- sidebar_canvas -->
|
||||||
</div> <!-- sidebar_container -->
|
</div> <!-- sidebar_container -->
|
||||||
|
</div> <!-- layout_container -->
|
||||||
|
|
||||||
<div id="SpecialSquawkWarning" class="hidden">
|
<div id="SpecialSquawkWarning" class="hidden">
|
||||||
<b>Squawk 7x00 is reported and shown.</b><br>
|
<b>Squawk 7x00 is reported and shown.</b><br>
|
||||||
|
|
4
public_html/jquery/plugins/jquery.validate.min.js
vendored
Executable file
4
public_html/jquery/plugins/jquery.validate.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
|
@ -73,7 +73,7 @@ var _a320 = {
|
||||||
|
|
||||||
var _b777 = {
|
var _b777 = {
|
||||||
key: "b777",
|
key: "b777",
|
||||||
scale: 1.15 * 0.75,
|
scale: 0.80 * 0.75,
|
||||||
size: [64, 64],
|
size: [64, 64],
|
||||||
anchor: [32, 32],
|
anchor: [32, 32],
|
||||||
path: "m 32,1 2,1 1,2 0,20 4,4 0,-4 3,0 0,4 -1,2 17,12 0,2 -16,-5 -7,0 0,13 -1,5 7,5 0,2 -8,-2 -1,2 -1,-2 -8,2 0,-2 7,-5 -1,-5 0,-13 -7,0 -16,5 0,-2 17,-12 -1,-2 0,-4 3,0 0,4 4,-4 0,-20 1,-2 2,-1z"
|
path: "m 32,1 2,1 1,2 0,20 4,4 0,-4 3,0 0,4 -1,2 17,12 0,2 -16,-5 -7,0 0,13 -1,5 7,5 0,2 -8,-2 -1,2 -1,-2 -8,2 0,-2 7,-5 -1,-5 0,-13 -7,0 -16,5 0,-2 17,-12 -1,-2 0,-4 3,0 0,4 4,-4 0,-20 1,-2 2,-1z"
|
||||||
|
@ -121,6 +121,21 @@ var _balloon = {
|
||||||
markerRadius: 32
|
markerRadius: 32
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var _helicopter = {
|
||||||
|
key : "helicopter",
|
||||||
|
scale : 0.50,
|
||||||
|
size : [64, 64],
|
||||||
|
anchor : [22, 32],
|
||||||
|
path : _rotorcraft_svg
|
||||||
|
};
|
||||||
|
|
||||||
|
var _single_prop = {
|
||||||
|
key : "single_prop",
|
||||||
|
scale : 0.30,
|
||||||
|
size : [64, 64],
|
||||||
|
anchor : [32, 25],
|
||||||
|
path : _beechcraft_svg
|
||||||
|
};
|
||||||
|
|
||||||
// by Oliver Jowett <oliver@mutability.co.uk>
|
// by Oliver Jowett <oliver@mutability.co.uk>
|
||||||
// licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
|
// licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
|
||||||
|
@ -134,13 +149,13 @@ var _a380 = {
|
||||||
|
|
||||||
var _b738 = {
|
var _b738 = {
|
||||||
key: "b738",
|
key: "b738",
|
||||||
scale: 0.63 * 0.75,
|
scale: 0.70 * 0.75,
|
||||||
size: [64, 64],
|
size: [64, 64],
|
||||||
anchor: [32, 32],
|
anchor: [32, 32],
|
||||||
path: "m 32,61 -1,-1 -9,2 -2,1 0,-2 9,-6 1,-1 -1,-9 0,-11 -7,0 -1,1 0,-1 -3,1 -1,1 0,-1 -3,1 -9,3 -1,1 0,-2 1,-2 17,-9 1,-1 -1,-2 0,-3 1,-1 2,0 1,1 0,3 3,-2 0,-13 1,-5 1,-3 1,-1 1,1 1,3 1,5 0,13 3,2 0,-3 1,-1 2,0 1,1 0,3 -1,2 1,1 17,9 1,2 0,2 -1,-1 -9,-3 -3,-1 0,1 -1,-1 -3,-1 0,1 -1,-1 -7,0 0,11 -1,9 1,1 9,6 0,2 -2,-1 -9,-2 -1,1 z"
|
path: "m 32,61 -1,-1 -9,2 -2,1 0,-2 9,-6 1,-1 -1,-9 0,-11 -7,0 -1,1 0,-1 -3,1 -1,1 0,-1 -3,1 -9,3 -1,1 0,-2 1,-2 17,-9 1,-1 -1,-2 0,-3 1,-1 2,0 1,1 0,3 3,-2 0,-13 1,-5 1,-3 1,-1 1,1 1,3 1,5 0,13 3,2 0,-3 1,-1 2,0 1,1 0,3 -1,2 1,1 17,9 1,2 0,2 -1,-1 -9,-3 -3,-1 0,1 -1,-1 -3,-1 0,1 -1,-1 -7,0 0,11 -1,9 1,1 9,6 0,2 -2,-1 -9,-2 -1,1 z"
|
||||||
};
|
};
|
||||||
|
|
||||||
var TypeIcons = {
|
var TypeDesignatorIcons = {
|
||||||
'A318': _a320, // shortened a320
|
'A318': _a320, // shortened a320
|
||||||
'A319': _a320, // shortened a320
|
'A319': _a320, // shortened a320
|
||||||
'A320': _a320,
|
'A320': _a320,
|
||||||
|
@ -182,14 +197,30 @@ var TypeIcons = {
|
||||||
'C30J': _c130
|
'C30J': _c130
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Maps ICAO aircraft type description codes (e.g. "L2J") to aircraft icons. This is used if the ICAO type designator (e.g. "B731")
|
||||||
|
// cannot be found in the TypeDesignatorIcons mappings. The key can be one of the following:
|
||||||
|
// - Single character: The basic aircraft type letter code (e.g. "H" for helicopter).
|
||||||
|
// - Three characters: The ICAO type description code (e.g. "L2J" for landplanes with 2 jet engines).
|
||||||
|
// - Five characters: The ICAO type description code concatenated with the wake turbulence category code, separated by
|
||||||
|
// a dash (e.g. "L2J-M").
|
||||||
|
|
||||||
|
var TypeDescriptionIcons = {
|
||||||
|
'H': _helicopter,
|
||||||
|
|
||||||
|
'L1J': _g650,
|
||||||
|
'L1P': _single_prop,
|
||||||
|
'L1T': _single_prop,
|
||||||
|
|
||||||
|
'L2P': _b200,
|
||||||
|
'L2T': _b200,
|
||||||
|
|
||||||
|
'L2J-L': _g650,
|
||||||
|
'L2J-M': _a320,
|
||||||
|
'L2J-H': _b777,
|
||||||
|
};
|
||||||
|
|
||||||
var CategoryIcons = {
|
var CategoryIcons = {
|
||||||
"A1" : {
|
"A1" : _single_prop,
|
||||||
key : "A1",
|
|
||||||
scale : 0.30,
|
|
||||||
size : [64, 64],
|
|
||||||
anchor : [32, 25],
|
|
||||||
path : _beechcraft_svg
|
|
||||||
},
|
|
||||||
|
|
||||||
"A2" : {
|
"A2" : {
|
||||||
key : "A2",
|
key : "A2",
|
||||||
|
@ -215,13 +246,7 @@ var CategoryIcons = {
|
||||||
path : _heavy_svg
|
path : _heavy_svg
|
||||||
},
|
},
|
||||||
|
|
||||||
"A7" : {
|
"A7" : _helicopter,
|
||||||
key : "A7",
|
|
||||||
scale : 0.50,
|
|
||||||
size : [64, 64],
|
|
||||||
anchor : [22, 32],
|
|
||||||
path : _rotorcraft_svg
|
|
||||||
},
|
|
||||||
|
|
||||||
"B2" : _balloon
|
"B2" : _balloon
|
||||||
};
|
};
|
||||||
|
@ -234,9 +259,27 @@ var DefaultIcon = {
|
||||||
path : _generic_plane_svg
|
path : _generic_plane_svg
|
||||||
};
|
};
|
||||||
|
|
||||||
function getBaseMarker(category, type) {
|
function getBaseMarker(category, typeDesignator, typeDescription, wtc) {
|
||||||
if (type in TypeIcons) {
|
if (typeDesignator in TypeDesignatorIcons) {
|
||||||
return TypeIcons[type];
|
return TypeDesignatorIcons[typeDesignator];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeDescription !== undefined && typeDescription !== null && typeDescription.length === 3) {
|
||||||
|
if (wtc !== undefined && wtc !== null && wtc.length === 1) {
|
||||||
|
var typeDescriptionWithWtc = typeDescription + "-" + wtc;
|
||||||
|
if (typeDescriptionWithWtc in TypeDescriptionIcons) {
|
||||||
|
return TypeDescriptionIcons[typeDescriptionWithWtc];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeDescription in TypeDescriptionIcons) {
|
||||||
|
return TypeDescriptionIcons[typeDescription];
|
||||||
|
}
|
||||||
|
|
||||||
|
var basicType = typeDescription.charAt(0);
|
||||||
|
if (basicType in TypeDescriptionIcons) {
|
||||||
|
return TypeDescriptionIcons[basicType];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (category in CategoryIcons) {
|
if (category in CategoryIcons) {
|
||||||
|
@ -246,7 +289,7 @@ function getBaseMarker(category, type) {
|
||||||
return DefaultIcon;
|
return DefaultIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
function svgPathToSvg(path, size, stroke, width, fill) {
|
function svgPathToSvg(path, size, stroke, width, fill, transparentBorderWidth) {
|
||||||
var svg = '<svg width="' + size[0] + 'px" height="' + size[1] + 'px" version="1.1" xmlns="http://www.w3.org/2000/svg">';
|
var svg = '<svg width="' + size[0] + 'px" height="' + size[1] + 'px" version="1.1" xmlns="http://www.w3.org/2000/svg">';
|
||||||
svg += '<path d="' + path + '"';
|
svg += '<path d="' + path + '"';
|
||||||
if (stroke !== null) {
|
if (stroke !== null) {
|
||||||
|
@ -258,11 +301,19 @@ function svgPathToSvg(path, size, stroke, width, fill) {
|
||||||
if (fill !== null) {
|
if (fill !== null) {
|
||||||
svg += ' fill="' + fill + '"';
|
svg += ' fill="' + fill + '"';
|
||||||
}
|
}
|
||||||
svg += '/></svg>';
|
svg += '/>';
|
||||||
|
// Add a transparent border to increase the size of the plane marker clickable area.
|
||||||
|
if (transparentBorderWidth > 0) {
|
||||||
|
// If the border is 100% transparent, OpenLayers will ignore it completely - see
|
||||||
|
// https://github.com/openlayers/ol3/issues/2961. The stroke opacity is set to 1% as a workaround.
|
||||||
|
// This is transparent enough to be invisible to the user.
|
||||||
|
svg += '<path d="' + path + '" fill="none" stroke="#FFFFFF" stroke-opacity="0.01" stroke-width="' + transparentBorderWidth + '" />';
|
||||||
|
}
|
||||||
|
svg += '</svg>';
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function svgPathToURI(path, size, stroke, width, fill) {
|
function svgPathToURI(path, size, stroke, width, fill, transparentBorderWidth) {
|
||||||
return "data:image/svg+xml;base64," + btoa(svgPathToSvg(path, size, stroke, width, fill));
|
return "data:image/svg+xml;base64," + btoa(svgPathToSvg(path, size, stroke, width, fill, transparentBorderWidth));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,14 @@ function PlaneObject(icao) {
|
||||||
this.markerStaticIcon = null;
|
this.markerStaticIcon = null;
|
||||||
this.markerStyleKey = null;
|
this.markerStyleKey = null;
|
||||||
this.markerSvgKey = null;
|
this.markerSvgKey = null;
|
||||||
|
this.filter = {};
|
||||||
|
|
||||||
// start from a computed registration, let the DB override it
|
// start from a computed registration, let the DB override it
|
||||||
// if it has something else.
|
// if it has something else.
|
||||||
this.registration = registration_from_hexid(this.icao);
|
this.registration = registration_from_hexid(this.icao);
|
||||||
this.icaotype = null;
|
this.icaotype = null;
|
||||||
|
this.typeDescription = null;
|
||||||
|
this.wtc = null;
|
||||||
|
|
||||||
// request metadata
|
// request metadata
|
||||||
getAircraftData(this.icao).done(function(data) {
|
getAircraftData(this.icao).done(function(data) {
|
||||||
|
@ -59,12 +62,32 @@ function PlaneObject(icao) {
|
||||||
this.icaotype = data.t;
|
this.icaotype = data.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("desc" in data) {
|
||||||
|
this.typeDescription = data.desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("wtc" in data) {
|
||||||
|
this.wtc = data.wtc;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.selected) {
|
if (this.selected) {
|
||||||
refreshSelected();
|
refreshSelected();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaneObject.prototype.isFiltered = function() {
|
||||||
|
if (this.filter.minAltitude !== undefined && this.filter.maxAltitude !== undefined) {
|
||||||
|
if (this.altitude === null || this.altitude === undefined) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var planeAltitude = this.altitude === "ground" ? 0 : convert_altitude(this.altitude, this.filter.altitudeUnits);
|
||||||
|
return planeAltitude < this.filter.minAltitude || planeAltitude > this.filter.maxAltitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 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(estimate_time) {
|
PlaneObject.prototype.updateTrack = function(estimate_time) {
|
||||||
|
@ -183,6 +206,27 @@ PlaneObject.prototype.clearLines = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PlaneObject.prototype.getDataSource = function() {
|
||||||
|
// MLAT
|
||||||
|
if (this.position_from_mlat) {
|
||||||
|
return 'mlat';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not MLAT, but position reported - ADSB
|
||||||
|
if (this.position !== null) {
|
||||||
|
return 'adsb';
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyHexRegex = /^0*$/;
|
||||||
|
// No position and no ICAO hex code - Mode A/C
|
||||||
|
if (emptyHexRegex.test(this.icao)) {
|
||||||
|
return 'mode_ac';
|
||||||
|
}
|
||||||
|
|
||||||
|
// No position and ICAO hex code present - Mode S
|
||||||
|
return 'mode_s';
|
||||||
|
};
|
||||||
|
|
||||||
PlaneObject.prototype.getMarkerColor = function() {
|
PlaneObject.prototype.getMarkerColor = function() {
|
||||||
// Emergency squawks override everything else
|
// Emergency squawks override everything else
|
||||||
if (this.squawk in SpecialSquawks)
|
if (this.squawk in SpecialSquawks)
|
||||||
|
@ -258,9 +302,10 @@ PlaneObject.prototype.updateIcon = function() {
|
||||||
var col = this.getMarkerColor();
|
var col = this.getMarkerColor();
|
||||||
var opacity = (this.position_from_mlat ? 0.75 : 1.0);
|
var opacity = (this.position_from_mlat ? 0.75 : 1.0);
|
||||||
var outline = (this.position_from_mlat ? OutlineMlatColor : OutlineADSBColor);
|
var outline = (this.position_from_mlat ? OutlineMlatColor : OutlineADSBColor);
|
||||||
var baseMarker = getBaseMarker(this.category, this.icaotype);
|
var baseMarker = getBaseMarker(this.category, this.icaotype, this.typeDescription, this.wtc);
|
||||||
var weight = ((this.selected ? 2 : 1) / baseMarker.scale).toFixed(1);
|
var weight = ((this.selected ? 2 : 1) / baseMarker.scale).toFixed(1);
|
||||||
var rotation = (this.track === null ? 0 : this.track);
|
var rotation = (this.track === null ? 0 : this.track);
|
||||||
|
var transparentBorderWidth = 16;
|
||||||
|
|
||||||
var svgKey = col + '!' + outline + '!' + baseMarker.key + '!' + weight;
|
var svgKey = col + '!' + outline + '!' + baseMarker.key + '!' + weight;
|
||||||
var styleKey = opacity + '!' + rotation;
|
var styleKey = opacity + '!' + rotation;
|
||||||
|
@ -274,7 +319,7 @@ PlaneObject.prototype.updateIcon = function() {
|
||||||
anchorYUnits: 'pixels',
|
anchorYUnits: 'pixels',
|
||||||
scale: baseMarker.scale,
|
scale: baseMarker.scale,
|
||||||
imgSize: baseMarker.size,
|
imgSize: baseMarker.size,
|
||||||
src: svgPathToURI(baseMarker.path, baseMarker.size, outline, weight, col),
|
src: svgPathToURI(baseMarker.path, baseMarker.size, outline, weight, col, transparentBorderWidth),
|
||||||
rotation: (baseMarker.noRotate ? 0 : rotation * Math.PI / 180.0),
|
rotation: (baseMarker.noRotate ? 0 : rotation * Math.PI / 180.0),
|
||||||
opacity: opacity,
|
opacity: opacity,
|
||||||
rotateWithView: (baseMarker.noRotate ? false : true)
|
rotateWithView: (baseMarker.noRotate ? false : true)
|
||||||
|
@ -300,7 +345,7 @@ PlaneObject.prototype.updateIcon = function() {
|
||||||
anchorYUnits: 'pixels',
|
anchorYUnits: 'pixels',
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
imgSize: [size, size],
|
imgSize: [size, size],
|
||||||
src: svgPathToURI(arrowPath, [size, size], outline, 1, outline),
|
src: svgPathToURI(arrowPath, [size, size], outline, 1, outline, transparentBorderWidth),
|
||||||
rotation: rotation * Math.PI / 180.0,
|
rotation: rotation * Math.PI / 180.0,
|
||||||
opacity: opacity,
|
opacity: opacity,
|
||||||
rotateWithView: true
|
rotateWithView: true
|
||||||
|
@ -421,7 +466,7 @@ PlaneObject.prototype.clearMarker = function() {
|
||||||
|
|
||||||
// Update our marker on the map
|
// Update our marker on the map
|
||||||
PlaneObject.prototype.updateMarker = function(moved) {
|
PlaneObject.prototype.updateMarker = function(moved) {
|
||||||
if (!this.visible || this.position == null) {
|
if (!this.visible || this.position == null || this.isFiltered()) {
|
||||||
this.clearMarker();
|
this.clearMarker();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -480,9 +525,10 @@ PlaneObject.prototype.updateLines = function() {
|
||||||
var lastfixed = lastseg.fixed.getCoordinateAt(1.0);
|
var lastfixed = lastseg.fixed.getCoordinateAt(1.0);
|
||||||
var geom = new ol.geom.LineString([lastfixed, ol.proj.fromLonLat(this.position)]);
|
var geom = new ol.geom.LineString([lastfixed, ol.proj.fromLonLat(this.position)]);
|
||||||
var feature = new ol.Feature(geom);
|
var feature = new ol.Feature(geom);
|
||||||
|
lastseg.feature = feature;
|
||||||
feature.setStyle(this.altitude === 'ground' ? groundStyle : airStyle);
|
feature.setStyle(this.altitude === 'ground' ? groundStyle : airStyle);
|
||||||
|
|
||||||
if (PlaneTrailFeatures.length == 0) {
|
if (PlaneTrailFeatures.getLength() == 0) {
|
||||||
PlaneTrailFeatures.push(feature);
|
PlaneTrailFeatures.push(feature);
|
||||||
} else {
|
} else {
|
||||||
PlaneTrailFeatures.setAt(0, feature);
|
PlaneTrailFeatures.setAt(0, feature);
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
// Define our global variables
|
// Define our global variables
|
||||||
var OLMap = null;
|
var OLMap = null;
|
||||||
var StaticFeatures = new ol.Collection();
|
var StaticFeatures = new ol.Collection();
|
||||||
|
var SiteCircleFeatures = new ol.Collection();
|
||||||
var PlaneIconFeatures = new ol.Collection();
|
var PlaneIconFeatures = new ol.Collection();
|
||||||
var PlaneTrailFeatures = new ol.Collection();
|
var PlaneTrailFeatures = new ol.Collection();
|
||||||
var Planes = {};
|
var Planes = {};
|
||||||
|
var PlanesModeAc = {};
|
||||||
var PlanesOrdered = [];
|
var PlanesOrdered = [];
|
||||||
|
var PlaneFilter = {};
|
||||||
var SelectedPlane = null;
|
var SelectedPlane = null;
|
||||||
|
var SelectedAllPlanes = false;
|
||||||
var FollowSelected = false;
|
var FollowSelected = false;
|
||||||
|
|
||||||
var SpecialSquawks = {
|
var SpecialSquawks = {
|
||||||
|
@ -62,15 +66,19 @@ function processReceiverUpdate(data) {
|
||||||
for (var j=0; j < acs.length; j++) {
|
for (var j=0; j < acs.length; j++) {
|
||||||
var ac = acs[j];
|
var ac = acs[j];
|
||||||
var hex = ac.hex;
|
var hex = ac.hex;
|
||||||
|
var squawk = ac.squawk;
|
||||||
var plane = null;
|
var plane = null;
|
||||||
|
|
||||||
// Do we already have this plane object in Planes?
|
// Do we already have this plane object in Planes?
|
||||||
// If not make it.
|
// If not make it.
|
||||||
|
|
||||||
if (Planes[hex]) {
|
if (hex !== "000000" && Planes[hex]) {
|
||||||
plane = Planes[hex];
|
plane = Planes[hex];
|
||||||
|
} else if (hex === "000000" && PlanesModeAc[squawk]) {
|
||||||
|
plane = PlanesModeAc[squawk];
|
||||||
} else {
|
} else {
|
||||||
plane = new PlaneObject(hex);
|
plane = new PlaneObject(hex);
|
||||||
|
plane.filter = PlaneFilter;
|
||||||
plane.tr = PlaneRowTemplate.cloneNode(true);
|
plane.tr = PlaneRowTemplate.cloneNode(true);
|
||||||
|
|
||||||
if (hex[0] === '~') {
|
if (hex[0] === '~') {
|
||||||
|
@ -89,17 +97,34 @@ function processReceiverUpdate(data) {
|
||||||
$('img', plane.tr.cells[1]).css('display', 'none');
|
$('img', plane.tr.cells[1]).css('display', 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hex !== "000000") {
|
||||||
plane.tr.addEventListener('click', function(h, evt) {
|
plane.tr.addEventListener('click', function(h, evt) {
|
||||||
|
if (evt.srcElement instanceof HTMLAnchorElement) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$("#map_container").is(":visible")) {
|
||||||
|
showMap();
|
||||||
|
}
|
||||||
selectPlaneByHex(h, false);
|
selectPlaneByHex(h, false);
|
||||||
|
adjustSelectedInfoBlockPosition();
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}.bind(undefined, hex));
|
}.bind(undefined, hex));
|
||||||
|
|
||||||
plane.tr.addEventListener('dblclick', function(h, evt) {
|
plane.tr.addEventListener('dblclick', function(h, evt) {
|
||||||
|
if (!$("#map_container").is(":visible")) {
|
||||||
|
showMap();
|
||||||
|
}
|
||||||
selectPlaneByHex(h, true);
|
selectPlaneByHex(h, true);
|
||||||
|
adjustSelectedInfoBlockPosition();
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}.bind(undefined, hex));
|
}.bind(undefined, hex));
|
||||||
|
|
||||||
Planes[hex] = plane;
|
Planes[hex] = plane;
|
||||||
|
} else {
|
||||||
|
PlanesModeAc[squawk] = plane;
|
||||||
|
}
|
||||||
PlanesOrdered.push(plane);
|
PlanesOrdered.push(plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +154,7 @@ function fetchData() {
|
||||||
plane.updateTick(now, LastReceiverTimestamp);
|
plane.updateTick(now, LastReceiverTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectNewPlanes();
|
||||||
refreshTableInfo();
|
refreshTableInfo();
|
||||||
refreshSelected();
|
refreshSelected();
|
||||||
|
|
||||||
|
@ -197,6 +223,53 @@ function initialize() {
|
||||||
|
|
||||||
$("#loader").removeClass("hidden");
|
$("#loader").removeClass("hidden");
|
||||||
|
|
||||||
|
// Set up map/sidebar splitter
|
||||||
|
$("#sidebar_container").resizable({handles: {w: '#splitter'}});
|
||||||
|
|
||||||
|
// Set up aircraft information panel
|
||||||
|
$("#selected_infoblock").draggable({containment: "parent"});
|
||||||
|
|
||||||
|
// Set up event handlers for buttons
|
||||||
|
$("#toggle_sidebar_button").click(toggleSidebarVisibility);
|
||||||
|
$("#expand_sidebar_button").click(expandSidebar);
|
||||||
|
$("#show_map_button").click(showMap);
|
||||||
|
|
||||||
|
// Set initial element visibility
|
||||||
|
$("#show_map_button").hide();
|
||||||
|
setColumnVisibility();
|
||||||
|
|
||||||
|
// Initialize other controls
|
||||||
|
initializeUnitsSelector();
|
||||||
|
|
||||||
|
// Set up altitude filter button event handlers and validation options
|
||||||
|
$("#altitude_filter_form").submit(onFilterByAltitude);
|
||||||
|
$("#altitude_filter_form").validate({
|
||||||
|
errorPlacement: function(error, element) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
minAltitude: {
|
||||||
|
number: true,
|
||||||
|
min: -99999,
|
||||||
|
max: 99999
|
||||||
|
},
|
||||||
|
maxAltitude: {
|
||||||
|
number: true,
|
||||||
|
min: -99999,
|
||||||
|
max: 99999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#altitude_filter_reset_button").click(onResetAltitudeFilter);
|
||||||
|
|
||||||
|
// Force map to redraw if sidebar container is resized - use a timer to debounce
|
||||||
|
var mapResizeTimeout;
|
||||||
|
$("#sidebar_container").on("resize", function() {
|
||||||
|
clearTimeout(mapResizeTimeout);
|
||||||
|
mapResizeTimeout = setTimeout(updateMapSize, 10);
|
||||||
|
});
|
||||||
|
|
||||||
// Get receiver metadata, reconfigure using it, then continue
|
// Get receiver metadata, reconfigure using it, then continue
|
||||||
// with initialization
|
// with initialization
|
||||||
$.ajax({ url: 'data/receiver.json',
|
$.ajax({ url: 'data/receiver.json',
|
||||||
|
@ -354,7 +427,7 @@ function initialize_map() {
|
||||||
sortByDistance();
|
sortByDistance();
|
||||||
} else {
|
} else {
|
||||||
SitePosition = null;
|
SitePosition = null;
|
||||||
PlaneRowTemplate.cells[6].style.display = 'none'; // hide distance column
|
PlaneRowTemplate.cells[9].style.display = 'none'; // hide distance column
|
||||||
document.getElementById("distance").style.display = 'none'; // hide distance header
|
document.getElementById("distance").style.display = 'none'; // hide distance header
|
||||||
sortByAltitude();
|
sortByAltitude();
|
||||||
}
|
}
|
||||||
|
@ -457,7 +530,7 @@ function initialize_map() {
|
||||||
controls: [new ol.control.Zoom(),
|
controls: [new ol.control.Zoom(),
|
||||||
new ol.control.Rotate(),
|
new ol.control.Rotate(),
|
||||||
new ol.control.Attribution({collapsed: false}),
|
new ol.control.Attribution({collapsed: false}),
|
||||||
new ol.control.ScaleLine({units: Metric ? "metric" : "nautical"}),
|
new ol.control.ScaleLine({units: DisplayUnits}),
|
||||||
new ol.control.LayerSwitcher()
|
new ol.control.LayerSwitcher()
|
||||||
],
|
],
|
||||||
loadTilesWhileAnimating: true,
|
loadTilesWhileAnimating: true,
|
||||||
|
@ -496,6 +569,10 @@ function initialize_map() {
|
||||||
null);
|
null);
|
||||||
if (hex) {
|
if (hex) {
|
||||||
selectPlaneByHex(hex, (evt.type === 'dblclick'));
|
selectPlaneByHex(hex, (evt.type === 'dblclick'));
|
||||||
|
adjustSelectedInfoBlockPosition();
|
||||||
|
evt.stopPropagation();
|
||||||
|
} else {
|
||||||
|
deselectAllPlanes();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -518,26 +595,7 @@ function initialize_map() {
|
||||||
StaticFeatures.push(feature);
|
StaticFeatures.push(feature);
|
||||||
|
|
||||||
if (SiteCircles) {
|
if (SiteCircles) {
|
||||||
var circleStyle = new ol.style.Style({
|
createSiteCircleFeatures();
|
||||||
fill: null,
|
|
||||||
stroke: new ol.style.Stroke({
|
|
||||||
color: '#000000',
|
|
||||||
width: 1
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var i=0; i < SiteCirclesDistances.length; ++i) {
|
|
||||||
var distance = SiteCirclesDistances[i] * 1000.0;
|
|
||||||
if (!Metric) {
|
|
||||||
distance *= 1.852;
|
|
||||||
}
|
|
||||||
|
|
||||||
var circle = make_geodesic_circle(SitePosition, distance, 360);
|
|
||||||
circle.transform('EPSG:4326', 'EPSG:3857');
|
|
||||||
var feature = new ol.Feature(circle);
|
|
||||||
feature.setStyle(circleStyle);
|
|
||||||
StaticFeatures.push(feature);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,6 +649,39 @@ function initialize_map() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createSiteCircleFeatures() {
|
||||||
|
// Clear existing circles first
|
||||||
|
SiteCircleFeatures.forEach(function(circleFeature) {
|
||||||
|
StaticFeatures.remove(circleFeature);
|
||||||
|
});
|
||||||
|
SiteCircleFeatures.clear();
|
||||||
|
|
||||||
|
var circleStyle = new ol.style.Style({
|
||||||
|
fill: null,
|
||||||
|
stroke: new ol.style.Stroke({
|
||||||
|
color: '#000000',
|
||||||
|
width: 1
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var conversionFactor = 1000.0;
|
||||||
|
if (DisplayUnits === "nautical") {
|
||||||
|
conversionFactor = 1852.0;
|
||||||
|
} else if (DisplayUnits === "imperial") {
|
||||||
|
conversionFactor = 1609.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i=0; i < SiteCirclesDistances.length; ++i) {
|
||||||
|
var distance = SiteCirclesDistances[i] * conversionFactor;
|
||||||
|
var circle = make_geodesic_circle(SitePosition, distance, 360);
|
||||||
|
circle.transform('EPSG:4326', 'EPSG:3857');
|
||||||
|
var feature = new ol.Feature(circle);
|
||||||
|
feature.setStyle(circleStyle);
|
||||||
|
StaticFeatures.push(feature);
|
||||||
|
SiteCircleFeatures.push(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This looks for planes to reap out of the master Planes variable
|
// This looks for planes to reap out of the master Planes variable
|
||||||
function reaper() {
|
function reaper() {
|
||||||
//console.log("Reaping started..");
|
//console.log("Reaping started..");
|
||||||
|
@ -601,11 +692,13 @@ function reaper() {
|
||||||
var plane = PlanesOrdered[i];
|
var plane = PlanesOrdered[i];
|
||||||
if (plane.seen > 300) {
|
if (plane.seen > 300) {
|
||||||
// Reap it.
|
// Reap it.
|
||||||
//console.log("Reaping " + plane.icao);
|
|
||||||
//console.log("parent " + plane.tr.parentNode);
|
|
||||||
plane.tr.parentNode.removeChild(plane.tr);
|
plane.tr.parentNode.removeChild(plane.tr);
|
||||||
plane.tr = null;
|
plane.tr = null;
|
||||||
|
if (plane.icao === "000000") {
|
||||||
|
delete PlanesModeAc[plane.squawk];
|
||||||
|
} else {
|
||||||
delete Planes[plane.icao];
|
delete Planes[plane.icao];
|
||||||
|
}
|
||||||
plane.destroy();
|
plane.destroy();
|
||||||
} else {
|
} else {
|
||||||
// Keep it.
|
// Keep it.
|
||||||
|
@ -655,8 +748,6 @@ function refreshSelected() {
|
||||||
selected = Planes[SelectedPlane];
|
selected = Planes[SelectedPlane];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selected) {
|
|
||||||
$('#selected_infoblock').css('display','none');
|
|
||||||
$('#dump1090_infoblock').css('display','block');
|
$('#dump1090_infoblock').css('display','block');
|
||||||
$('#dump1090_version').text(Dump1090Version);
|
$('#dump1090_version').text(Dump1090Version);
|
||||||
$('#dump1090_total_ac').text(TrackedAircraft);
|
$('#dump1090_total_ac').text(TrackedAircraft);
|
||||||
|
@ -669,19 +760,18 @@ function refreshSelected() {
|
||||||
$('#dump1090_message_rate').text("n/a");
|
$('#dump1090_message_rate').text("n/a");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSelectedInfoBlockVisibility();
|
||||||
|
|
||||||
|
if (!selected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#dump1090_infoblock').css('display','none');
|
|
||||||
$('#selected_infoblock').css('display','block');
|
|
||||||
|
|
||||||
$('#selected_flightaware_link').attr('href','//flightaware.com/live/modes/'+selected.icao+'/redirect');
|
|
||||||
|
|
||||||
if (selected.flight !== null && selected.flight !== "") {
|
if (selected.flight !== null && selected.flight !== "") {
|
||||||
$('#selected_callsign').text(selected.flight);
|
$('#selected_callsign').text(selected.flight);
|
||||||
} else {
|
} else {
|
||||||
$('#selected_callsign').text('n/a');
|
$('#selected_callsign').text('n/a');
|
||||||
}
|
}
|
||||||
|
$('#selected_flightaware_link').html(getFlightAwareModeSLink(selected.icao, selected.flight, "[FlightAware]"));
|
||||||
|
|
||||||
if (selected.registration !== null) {
|
if (selected.registration !== null) {
|
||||||
$('#selected_registration').text(selected.registration);
|
$('#selected_registration').text(selected.registration);
|
||||||
|
@ -703,7 +793,7 @@ function refreshSelected() {
|
||||||
emerg.className = 'hidden';
|
emerg.className = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#selected_altitude").text(format_altitude_long(selected.altitude, selected.vert_rate));
|
$("#selected_altitude").text(format_altitude_long(selected.altitude, selected.vert_rate, DisplayUnits));
|
||||||
|
|
||||||
if (selected.squawk === null || selected.squawk === '0000') {
|
if (selected.squawk === null || selected.squawk === '0000') {
|
||||||
$('#selected_squawk').text('n/a');
|
$('#selected_squawk').text('n/a');
|
||||||
|
@ -711,7 +801,8 @@ function refreshSelected() {
|
||||||
$('#selected_squawk').text(selected.squawk);
|
$('#selected_squawk').text(selected.squawk);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#selected_speed').text(format_speed_long(selected.speed));
|
$('#selected_speed').text(format_speed_long(selected.speed, DisplayUnits));
|
||||||
|
$('#selected_vertical_rate').text(format_vert_rate_long(selected.vert_rate, DisplayUnits));
|
||||||
$('#selected_icao').text(selected.icao.toUpperCase());
|
$('#selected_icao').text(selected.icao.toUpperCase());
|
||||||
$('#airframes_post_icao').attr('value',selected.icao);
|
$('#airframes_post_icao').attr('value',selected.icao);
|
||||||
$('#selected_track').text(format_track_long(selected.track));
|
$('#selected_track').text(format_track_long(selected.track));
|
||||||
|
@ -750,8 +841,10 @@ function refreshSelected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#selected_sitedist').text(format_distance_long(selected.sitedist));
|
$('#selected_sitedist').text(format_distance_long(selected.sitedist, DisplayUnits));
|
||||||
$('#selected_rssi').text(selected.rssi.toFixed(1) + ' dBFS');
|
$('#selected_rssi').text(selected.rssi.toFixed(1) + ' dBFS');
|
||||||
|
$('#selected_message_count').text(selected.messages);
|
||||||
|
$('#selected_photo_link').html(getFlightAwarePhotoLink(selected.registration));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refreshes the larger table of all the planes
|
// Refreshes the larger table of all the planes
|
||||||
|
@ -762,10 +855,15 @@ function refreshTableInfo() {
|
||||||
TrackedAircraftPositions = 0
|
TrackedAircraftPositions = 0
|
||||||
TrackedHistorySize = 0
|
TrackedHistorySize = 0
|
||||||
|
|
||||||
|
$(".altitudeUnit").text(get_unit_label("altitude", DisplayUnits));
|
||||||
|
$(".speedUnit").text(get_unit_label("speed", DisplayUnits));
|
||||||
|
$(".distanceUnit").text(get_unit_label("distance", DisplayUnits));
|
||||||
|
$(".verticalRateUnit").text(get_unit_label("verticalRate", DisplayUnits));
|
||||||
|
|
||||||
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
for (var i = 0; i < PlanesOrdered.length; ++i) {
|
||||||
var tableplane = PlanesOrdered[i];
|
var tableplane = PlanesOrdered[i];
|
||||||
TrackedHistorySize += tableplane.history_size;
|
TrackedHistorySize += tableplane.history_size;
|
||||||
if (!tableplane.visible) {
|
if (!tableplane.visible || tableplane.isFiltered()) {
|
||||||
tableplane.tr.className = "plane_table_row hidden";
|
tableplane.tr.className = "plane_table_row hidden";
|
||||||
} else {
|
} else {
|
||||||
TrackedAircraft++;
|
TrackedAircraft++;
|
||||||
|
@ -787,14 +885,24 @@ function refreshTableInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICAO doesn't change
|
// ICAO doesn't change
|
||||||
tableplane.tr.cells[2].textContent = (tableplane.flight !== null ? tableplane.flight : "");
|
tableplane.tr.cells[2].innerHTML = getFlightAwareIdentLink(tableplane.flight);
|
||||||
tableplane.tr.cells[3].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
|
tableplane.tr.cells[3].textContent = (tableplane.registration !== null ? tableplane.registration : "");
|
||||||
tableplane.tr.cells[4].textContent = format_altitude_brief(tableplane.altitude, tableplane.vert_rate);
|
tableplane.tr.cells[4].textContent = (tableplane.icaotype !== null ? tableplane.icaotype : "");
|
||||||
tableplane.tr.cells[5].textContent = format_speed_brief(tableplane.speed);
|
tableplane.tr.cells[5].textContent = (tableplane.squawk !== null ? tableplane.squawk : "");
|
||||||
tableplane.tr.cells[6].textContent = format_distance_brief(tableplane.sitedist);
|
tableplane.tr.cells[6].innerHTML = format_altitude_brief(tableplane.altitude, tableplane.vert_rate, DisplayUnits);
|
||||||
tableplane.tr.cells[7].textContent = format_track_brief(tableplane.track);
|
tableplane.tr.cells[7].textContent = format_speed_brief(tableplane.speed, DisplayUnits);
|
||||||
tableplane.tr.cells[8].textContent = tableplane.messages;
|
tableplane.tr.cells[8].textContent = format_vert_rate_brief(tableplane.vert_rate, DisplayUnits);
|
||||||
tableplane.tr.cells[9].textContent = tableplane.seen.toFixed(0);
|
tableplane.tr.cells[9].textContent = format_distance_brief(tableplane.sitedist, DisplayUnits);
|
||||||
|
tableplane.tr.cells[10].textContent = format_track_brief(tableplane.track);
|
||||||
|
tableplane.tr.cells[11].textContent = tableplane.messages;
|
||||||
|
tableplane.tr.cells[12].textContent = tableplane.seen.toFixed(0);
|
||||||
|
tableplane.tr.cells[13].textContent = (tableplane.rssi !== null ? tableplane.rssi : "");
|
||||||
|
tableplane.tr.cells[14].textContent = (tableplane.position !== null ? tableplane.position[1].toFixed(4) : "");
|
||||||
|
tableplane.tr.cells[15].textContent = (tableplane.position !== null ? tableplane.position[0].toFixed(4) : "");
|
||||||
|
tableplane.tr.cells[16].textContent = format_data_source(tableplane.getDataSource());
|
||||||
|
tableplane.tr.cells[17].innerHTML = getAirframesModeSLink(tableplane.icao);
|
||||||
|
tableplane.tr.cells[18].innerHTML = getFlightAwareModeSLink(tableplane.icao, tableplane.flight);
|
||||||
|
tableplane.tr.cells[19].innerHTML = getFlightAwarePhotoLink(tableplane.registration);
|
||||||
tableplane.tr.className = classes;
|
tableplane.tr.className = classes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,14 +937,21 @@ function compareNumeric(xf,yf) {
|
||||||
|
|
||||||
function sortByICAO() { sortBy('icao', compareAlpha, function(x) { return x.icao; }); }
|
function sortByICAO() { sortBy('icao', compareAlpha, function(x) { return x.icao; }); }
|
||||||
function sortByFlight() { sortBy('flight', compareAlpha, function(x) { return x.flight; }); }
|
function sortByFlight() { sortBy('flight', compareAlpha, function(x) { return x.flight; }); }
|
||||||
|
function sortByRegistration() { sortBy('registration', compareAlpha, function(x) { return x.registration; }); }
|
||||||
|
function sortByAircraftType() { sortBy('icaotype', compareAlpha, function(x) { return x.icaotype; }); }
|
||||||
function sortBySquawk() { sortBy('squawk', compareAlpha, function(x) { return x.squawk; }); }
|
function sortBySquawk() { sortBy('squawk', compareAlpha, function(x) { return x.squawk; }); }
|
||||||
function sortByAltitude() { sortBy('altitude',compareNumeric, function(x) { return (x.altitude == "ground" ? -1e9 : x.altitude); }); }
|
function sortByAltitude() { sortBy('altitude',compareNumeric, function(x) { return (x.altitude == "ground" ? -1e9 : x.altitude); }); }
|
||||||
function sortBySpeed() { sortBy('speed', compareNumeric, function(x) { return x.speed; }); }
|
function sortBySpeed() { sortBy('speed', compareNumeric, function(x) { return x.speed; }); }
|
||||||
|
function sortByVerticalRate() { sortBy('vert_rate', compareNumeric, function(x) { return x.vert_rate; }); }
|
||||||
function sortByDistance() { sortBy('sitedist',compareNumeric, function(x) { return x.sitedist; }); }
|
function sortByDistance() { sortBy('sitedist',compareNumeric, function(x) { return x.sitedist; }); }
|
||||||
function sortByTrack() { sortBy('track', compareNumeric, function(x) { return x.track; }); }
|
function sortByTrack() { sortBy('track', compareNumeric, function(x) { return x.track; }); }
|
||||||
function sortByMsgs() { sortBy('msgs', compareNumeric, function(x) { return x.messages; }); }
|
function sortByMsgs() { sortBy('msgs', compareNumeric, function(x) { return x.messages; }); }
|
||||||
function sortBySeen() { sortBy('seen', compareNumeric, function(x) { return x.seen; }); }
|
function sortBySeen() { sortBy('seen', compareNumeric, function(x) { return x.seen; }); }
|
||||||
function sortByCountry() { sortBy('country', compareAlpha, function(x) { return x.icaorange.country; }); }
|
function sortByCountry() { sortBy('country', compareAlpha, function(x) { return x.icaorange.country; }); }
|
||||||
|
function sortByRssi() { sortBy('rssi', compareNumeric, function(x) { return x.rssi }); }
|
||||||
|
function sortByLatitude() { sortBy('lat', compareNumeric, function(x) { return (x.position !== null ? x.position[1] : null) }); }
|
||||||
|
function sortByLongitude() { sortBy('lon', compareNumeric, function(x) { return (x.position !== null ? x.position[0] : null) }); }
|
||||||
|
function sortByDataSource() { sortBy('data_source', compareAlpha, function(x) { return x.getDataSource() } ); }
|
||||||
|
|
||||||
var sortId = '';
|
var sortId = '';
|
||||||
var sortCompare = null;
|
var sortCompare = null;
|
||||||
|
@ -894,6 +1009,11 @@ function sortBy(id,sc,se) {
|
||||||
function selectPlaneByHex(hex,autofollow) {
|
function selectPlaneByHex(hex,autofollow) {
|
||||||
//console.log("select: " + hex);
|
//console.log("select: " + hex);
|
||||||
// If SelectedPlane has something in it, clear out the selected
|
// If SelectedPlane has something in it, clear out the selected
|
||||||
|
|
||||||
|
if (SelectedAllPlanes) {
|
||||||
|
deselectAllPlanes();
|
||||||
|
}
|
||||||
|
|
||||||
if (SelectedPlane != null) {
|
if (SelectedPlane != null) {
|
||||||
Planes[SelectedPlane].selected = false;
|
Planes[SelectedPlane].selected = false;
|
||||||
Planes[SelectedPlane].clearLines();
|
Planes[SelectedPlane].clearLines();
|
||||||
|
@ -929,6 +1049,67 @@ function selectPlaneByHex(hex,autofollow) {
|
||||||
refreshSelected();
|
refreshSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loop through the planes and mark them as selected to show the paths for all planes
|
||||||
|
function selectAllPlanes() {
|
||||||
|
// if all planes are already selected, deselect them all
|
||||||
|
if (SelectedAllPlanes) {
|
||||||
|
deselectAllPlanes();
|
||||||
|
} else {
|
||||||
|
// If SelectedPlane has something in it, clear out the selected
|
||||||
|
if (SelectedPlane != null) {
|
||||||
|
Planes[SelectedPlane].selected = false;
|
||||||
|
Planes[SelectedPlane].clearLines();
|
||||||
|
Planes[SelectedPlane].updateMarker();
|
||||||
|
$(Planes[SelectedPlane].tr).removeClass("selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedPlane = null;
|
||||||
|
|
||||||
|
for(var key in Planes) {
|
||||||
|
if (Planes[key].visible && !Planes[key].isFiltered()) {
|
||||||
|
Planes[key].selected = true;
|
||||||
|
Planes[key].updateLines();
|
||||||
|
Planes[key].updateMarker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectedAllPlanes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
// on refreshes, try to find new planes and mark them as selected
|
||||||
|
function selectNewPlanes() {
|
||||||
|
if (SelectedAllPlanes) {
|
||||||
|
for (var key in Planes) {
|
||||||
|
if (!Planes[key].visible || Planes[key].isFiltered()) {
|
||||||
|
Planes[key].selected = false;
|
||||||
|
Planes[key].clearLines();
|
||||||
|
Planes[key].updateMarker();
|
||||||
|
} else {
|
||||||
|
if (Planes[key].selected !== true) {
|
||||||
|
Planes[key].selected = true;
|
||||||
|
Planes[key].updateLines();
|
||||||
|
Planes[key].updateMarker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deselect all the planes
|
||||||
|
function deselectAllPlanes() {
|
||||||
|
for(var key in Planes) {
|
||||||
|
Planes[key].selected = false;
|
||||||
|
Planes[key].clearLines();
|
||||||
|
Planes[key].updateMarker();
|
||||||
|
$(Planes[key].tr).removeClass("selected");
|
||||||
|
}
|
||||||
|
SelectedPlane = null;
|
||||||
|
SelectedAllPlanes = false;
|
||||||
|
refreshSelected();
|
||||||
|
}
|
||||||
|
|
||||||
function toggleFollowSelected() {
|
function toggleFollowSelected() {
|
||||||
FollowSelected = !FollowSelected;
|
FollowSelected = !FollowSelected;
|
||||||
if (FollowSelected && OLMap.getView().getZoom() < 8)
|
if (FollowSelected && OLMap.getView().getZoom() < 8)
|
||||||
|
@ -948,3 +1129,269 @@ function resetMap() {
|
||||||
|
|
||||||
selectPlaneByHex(null,false);
|
selectPlaneByHex(null,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateMapSize() {
|
||||||
|
OLMap.updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSidebarVisibility(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$("#sidebar_container").toggle();
|
||||||
|
$("#expand_sidebar_button").toggle();
|
||||||
|
$("#toggle_sidebar_button").toggleClass("show_sidebar");
|
||||||
|
$("#toggle_sidebar_button").toggleClass("hide_sidebar");
|
||||||
|
updateMapSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function expandSidebar(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$("#map_container").hide()
|
||||||
|
$("#toggle_sidebar_button").hide();
|
||||||
|
$("#splitter").hide();
|
||||||
|
$("#sudo_buttons").hide();
|
||||||
|
$("#show_map_button").show();
|
||||||
|
$("#sidebar_container").width("100%");
|
||||||
|
setColumnVisibility();
|
||||||
|
setSelectedInfoBlockVisibility();
|
||||||
|
updateMapSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMap() {
|
||||||
|
$("#map_container").show()
|
||||||
|
$("#toggle_sidebar_button").show();
|
||||||
|
$("#splitter").show();
|
||||||
|
$("#sudo_buttons").show();
|
||||||
|
$("#show_map_button").hide();
|
||||||
|
$("#sidebar_container").width("470px");
|
||||||
|
setColumnVisibility();
|
||||||
|
setSelectedInfoBlockVisibility();
|
||||||
|
updateMapSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showColumn(table, columnId, visible) {
|
||||||
|
var index = $(columnId).index();
|
||||||
|
if (index >= 0) {
|
||||||
|
var cells = $(table).find("td:nth-child(" + (index + 1).toString() + ")");
|
||||||
|
if (visible) {
|
||||||
|
cells.show();
|
||||||
|
} else {
|
||||||
|
cells.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setColumnVisibility() {
|
||||||
|
var mapIsVisible = $("#map_container").is(":visible");
|
||||||
|
var infoTable = $("#tableinfo");
|
||||||
|
|
||||||
|
showColumn(infoTable, "#registration", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#aircraft_type", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#vert_rate", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#rssi", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#lat", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#lon", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#data_source", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#airframes_mode_s_link", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#flightaware_mode_s_link", !mapIsVisible);
|
||||||
|
showColumn(infoTable, "#flightaware_photo_link", !mapIsVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSelectedInfoBlockVisibility() {
|
||||||
|
var mapIsVisible = $("#map_container").is(":visible");
|
||||||
|
var planeSelected = (typeof SelectedPlane !== 'undefined' && SelectedPlane != null && SelectedPlane != "ICAO");
|
||||||
|
|
||||||
|
if (planeSelected && mapIsVisible) {
|
||||||
|
$('#selected_infoblock').show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#selected_infoblock').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reposition selected plane info box if it overlaps plane marker
|
||||||
|
function adjustSelectedInfoBlockPosition() {
|
||||||
|
if (typeof Planes === 'undefined' || typeof SelectedPlane === 'undefined' || Planes === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedPlane = Planes[SelectedPlane];
|
||||||
|
|
||||||
|
if (selectedPlane === undefined || selectedPlane === null || selectedPlane.marker === undefined || selectedPlane.marker === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get marker position
|
||||||
|
var marker = selectedPlane.marker;
|
||||||
|
var markerCoordinates = selectedPlane.marker.getGeometry().getCoordinates();
|
||||||
|
var markerPosition = OLMap.getPixelFromCoordinate(markerCoordinates);
|
||||||
|
|
||||||
|
// Get info box position and size
|
||||||
|
var infoBox = $('#selected_infoblock');
|
||||||
|
var infoBoxPosition = infoBox.position();
|
||||||
|
var infoBoxExtent = getExtent(infoBoxPosition.left, infoBoxPosition.top, infoBox.outerWidth(), infoBox.outerHeight());
|
||||||
|
|
||||||
|
// Get map size
|
||||||
|
var mapCanvas = $('#map_canvas');
|
||||||
|
var mapExtent = getExtent(0, 0, mapCanvas.width(), mapCanvas.height());
|
||||||
|
|
||||||
|
// Check for overlap
|
||||||
|
if (isPointInsideExtent(markerPosition[0], markerPosition[1], infoBoxExtent)) {
|
||||||
|
// Array of possible new positions for info box
|
||||||
|
var candidatePositions = [];
|
||||||
|
candidatePositions.push( { x: 20, y: 20 } );
|
||||||
|
candidatePositions.push( { x: 20, y: markerPosition[1] + 40 } );
|
||||||
|
|
||||||
|
// Find new position
|
||||||
|
for (var i = 0; i < candidatePositions.length; i++) {
|
||||||
|
var candidatePosition = candidatePositions[i];
|
||||||
|
var candidateExtent = getExtent(candidatePosition.x, candidatePosition.y, infoBox.outerWidth(), infoBox.outerHeight());
|
||||||
|
|
||||||
|
if (!isPointInsideExtent(markerPosition[0], markerPosition[1], candidateExtent) && isPointInsideExtent(candidatePosition.x, candidatePosition.y, mapExtent)) {
|
||||||
|
// Found a new position that doesn't overlap marker - move box to that position
|
||||||
|
infoBox.css("left", candidatePosition.x);
|
||||||
|
infoBox.css("top", candidatePosition.y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExtent(x, y, width, height) {
|
||||||
|
return {
|
||||||
|
xMin: x,
|
||||||
|
yMin: y,
|
||||||
|
xMax: x + width - 1,
|
||||||
|
yMax: y + height - 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPointInsideExtent(x, y, extent) {
|
||||||
|
return x >= extent.xMin && x <= extent.xMax && y >= extent.yMin && y <= extent.yMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeUnitsSelector() {
|
||||||
|
// Get display unit preferences from local storage
|
||||||
|
if (!localStorage.getItem('displayUnits')) {
|
||||||
|
localStorage['displayUnits'] = "nautical";
|
||||||
|
}
|
||||||
|
var displayUnits = localStorage['displayUnits'];
|
||||||
|
DisplayUnits = displayUnits;
|
||||||
|
|
||||||
|
// Initialize drop-down
|
||||||
|
var unitsSelector = $("#units_selector");
|
||||||
|
unitsSelector.val(displayUnits);
|
||||||
|
unitsSelector.on("change", onDisplayUnitsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDisplayUnitsChanged(e) {
|
||||||
|
var displayUnits = event.target.value;
|
||||||
|
// Save display units to local storage
|
||||||
|
localStorage['displayUnits'] = displayUnits;
|
||||||
|
DisplayUnits = displayUnits;
|
||||||
|
|
||||||
|
// Update filters
|
||||||
|
updatePlaneFilter();
|
||||||
|
|
||||||
|
// Refresh data
|
||||||
|
refreshTableInfo();
|
||||||
|
refreshSelected();
|
||||||
|
|
||||||
|
// Redraw range rings
|
||||||
|
if (SitePosition !== null && SitePosition !== undefined && SiteCircles) {
|
||||||
|
createSiteCircleFeatures();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset map scale line units
|
||||||
|
OLMap.getControls().forEach(function(control) {
|
||||||
|
if (control instanceof ol.control.ScaleLine) {
|
||||||
|
control.setUnits(displayUnits);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFilterByAltitude(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
updatePlaneFilter();
|
||||||
|
refreshTableInfo();
|
||||||
|
|
||||||
|
var selectedPlane = Planes[SelectedPlane];
|
||||||
|
if (selectedPlane !== undefined && selectedPlane !== null && selectedPlane.isFiltered()) {
|
||||||
|
SelectedPlane = null;
|
||||||
|
selectedPlane.selected = false;
|
||||||
|
selectedPlane.clearLines();
|
||||||
|
selectedPlane.updateMarker();
|
||||||
|
refreshSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResetAltitudeFilter(e) {
|
||||||
|
$("#altitude_filter_min").val("");
|
||||||
|
$("#altitude_filter_max").val("");
|
||||||
|
|
||||||
|
updatePlaneFilter();
|
||||||
|
refreshTableInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePlaneFilter() {
|
||||||
|
var minAltitude = parseFloat($("#altitude_filter_min").val().trim());
|
||||||
|
var maxAltitude = parseFloat($("#altitude_filter_max").val().trim());
|
||||||
|
|
||||||
|
if (minAltitude === NaN) {
|
||||||
|
minAltitude = -Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxAltitude === NaN) {
|
||||||
|
maxAltitude = Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlaneFilter.minAltitude = minAltitude;
|
||||||
|
PlaneFilter.maxAltitude = maxAltitude;
|
||||||
|
PlaneFilter.altitudeUnits = DisplayUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlightAwareIdentLink(ident, linkText) {
|
||||||
|
if (ident !== null && ident !== "") {
|
||||||
|
if (!linkText) {
|
||||||
|
linkText = ident;
|
||||||
|
}
|
||||||
|
return "<a target=\"_blank\" href=\"https://flightaware.com/live/flight/" + ident.trim() + "\">" + linkText + "</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlightAwareModeSLink(code, ident, linkText) {
|
||||||
|
if (code !== null && code.length > 0 && code[0] !== '~' && code !== "000000") {
|
||||||
|
if (!linkText) {
|
||||||
|
linkText = "FlightAware: " + code.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkHtml = "<a target=\"_blank\" href=\"https://flightaware.com/live/modes/" + code ;
|
||||||
|
if (ident !== null && ident !== "") {
|
||||||
|
linkHtml += "/ident/" + ident.trim();
|
||||||
|
}
|
||||||
|
linkHtml += "/redirect\">" + linkText + "</a>";
|
||||||
|
return linkHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlightAwarePhotoLink(registration) {
|
||||||
|
if (registration !== null && registration !== "") {
|
||||||
|
return "<a target=\"_blank\" href=\"https://flightaware.com/photos/aircraft/" + registration.trim() + "\">See Photos</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAirframesModeSLink(code) {
|
||||||
|
if (code !== null && code.length > 0 && code[0] !== '~' && code !== "000000") {
|
||||||
|
return "<a href=\"http://www.airframes.org/\" onclick=\"$('#airframes_post_icao').attr('value','" + code + "'); document.getElementById('horrible_hack').submit.call(document.getElementById('airframes_post')); return false;\">Airframes.org: " + code.toUpperCase() + "</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,96 @@ html, body {
|
||||||
margin: 0; padding: 0; background-color: #ffffff; font-family: Tahoma, Sans-Serif;
|
margin: 0; padding: 0; background-color: #ffffff; font-family: Tahoma, Sans-Serif;
|
||||||
font-size: 10pt; overflow: auto; height: 100%;
|
font-size: 10pt; overflow: auto; height: 100%;
|
||||||
}
|
}
|
||||||
div#map_container { float: left; width: 100%; height: 100%; }
|
|
||||||
div#map_canvas { height: 100%; margin-right: 420px; }
|
|
||||||
|
|
||||||
div#sidebar_container { float: left; width: 410px; margin-left: -410px; height: 100%; overflow: auto; }
|
#layout_container {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#selected_infoblock {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 20px;
|
||||||
|
min-width: 360px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 4px 4px 10px #444444;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map_container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map_canvas {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle_sidebar_button {
|
||||||
|
display: block;
|
||||||
|
width: 48px;
|
||||||
|
height: 40px;
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle_sidebar_button.show_sidebar {
|
||||||
|
background-image: url("images/show_sidebar_inactive_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle_sidebar_button.show_sidebar:hover {
|
||||||
|
background-image: url("images/show_sidebar_active_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle_sidebar_button.hide_sidebar {
|
||||||
|
background-image: url("images/hide_sidebar_inactive_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle_sidebar_button.hide_sidebar:hover {
|
||||||
|
background-image: url("images/hide_sidebar_active_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#expand_sidebar_button {
|
||||||
|
display: block;
|
||||||
|
width: 48px;
|
||||||
|
height: 40px;
|
||||||
|
position: absolute;
|
||||||
|
top: 56px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#expand_sidebar_button {
|
||||||
|
background-image: url("images/show_sidebar_inactive_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#expand_sidebar_button:hover {
|
||||||
|
background-image: url("images/show_sidebar_active_48x40.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar_container {
|
||||||
|
display: flex;
|
||||||
|
width: 470px;
|
||||||
|
left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#splitter {
|
||||||
|
flex: 0 0 6px;
|
||||||
|
cursor: col-resize;
|
||||||
|
background-color: #bbbbbb;
|
||||||
|
left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar_canvas {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: 10px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
div#SpecialSquawkWarning { position: absolute; bottom: 25px; right: 430px; border: 2px solid red;
|
div#SpecialSquawkWarning { position: absolute; bottom: 25px; right: 430px; border: 2px solid red;
|
||||||
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
||||||
|
@ -19,10 +105,37 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right:
|
||||||
#spinny { width: 128px; height: 128px; position: absolute; top: 50%; left: 50%; margin: -64px 0 0 -64px; }
|
#spinny { width: 128px; height: 128px; position: absolute; top: 50%; left: 50%; margin: -64px 0 0 -64px; }
|
||||||
#loader_progress { width: 250px; height: 20px; position: absolute; top: 50%; left: 50%; margin: 128px 0 0 -125px; }
|
#loader_progress { width: 250px; height: 20px; position: absolute; top: 50%; left: 50%; margin: 128px 0 0 -125px; }
|
||||||
|
|
||||||
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
|
#tableinfo { font-size: small; }
|
||||||
|
|
||||||
.vPosition { font-weight: bold; background-color: #d5ffd5; }
|
#sudo_buttons {
|
||||||
.mlat { font-weight: bold; background-color: #d5d5ff; }
|
display: flex;
|
||||||
|
padding: 15px 40px 15px 40px;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
#units_container,
|
||||||
|
#altitude_filter_form {
|
||||||
|
font-size: small;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aircraft_table_header {
|
||||||
|
background-color: #409EDF;
|
||||||
|
color: #FFFFFF;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.aircraft_table_header td {
|
||||||
|
font-size: smaller;
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verticalRateTriangle {
|
||||||
|
font-family: "Courier New",monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vPosition { background-color: #C3FFDF; }
|
||||||
|
.mlat { background-color: #C7EAFC; }
|
||||||
.squawk7500 { font-weight: bold; background-color: #ff5555; }
|
.squawk7500 { font-weight: bold; background-color: #ff5555; }
|
||||||
.squawk7600 { font-weight: bold; background-color: #00ffff; }
|
.squawk7600 { font-weight: bold; background-color: #00ffff; }
|
||||||
.squawk7700 { font-weight: bold; background-color: #ffff00; }
|
.squawk7700 { font-weight: bold; background-color: #ffff00; }
|
||||||
|
@ -42,3 +155,33 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right:
|
||||||
|
|
||||||
.pointer { cursor: pointer; }
|
.pointer { cursor: pointer; }
|
||||||
|
|
||||||
|
.sidebarButton {
|
||||||
|
background-color: #409EDF;
|
||||||
|
padding: 4px 15px 4px 15px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebarButton:hover {
|
||||||
|
background-color: #3c6ea3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.altitudeFilterInput {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.error, textarea.error, input.error {
|
||||||
|
color: #FF0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-zoom {
|
||||||
|
left: auto !important;
|
||||||
|
right: 20px !important;
|
||||||
|
top: 120px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-switcher {
|
||||||
|
top: 190px !important;
|
||||||
|
right: 10px !important;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue