Add ability to filter planes by altitude

This commit is contained in:
Carlos Salaverria 2016-08-24 15:28:13 -05:00
parent e243a2bf1a
commit 6b2c238a54
5 changed files with 122 additions and 15 deletions

View file

@ -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>
@ -169,6 +170,17 @@
</select> </select>
</div> </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 style="background-color: #BBBBBB; cursor: pointer;">
@ -179,10 +191,10 @@
<td id="registration" onclick="sortByRegistration();">Registration</td> <td id="registration" onclick="sortByRegistration();">Registration</td>
<td id="aircraft_type" onclick="sortByAircraftType();"> Aircraft type</td> <td id="aircraft_type" onclick="sortByAircraftType();"> Aircraft type</td>
<td id="squawk" onclick="sortBySquawk();" style="text-align: right">Squawk</td> <td id="squawk" onclick="sortBySquawk();" style="text-align: right">Squawk</td>
<td id="altitude" onclick="sortByAltitude();" style="text-align: right">Altitude (<span id="header_altitude_unit"></span>)</td> <td id="altitude" onclick="sortByAltitude();" style="text-align: right">Altitude (<span class="altitudeUnit"></span>)</td>
<td id="speed" onclick="sortBySpeed();" style="text-align: right">Speed (<span id="header_speed_unit"></span>)</td> <td id="speed" onclick="sortBySpeed();" style="text-align: right">Speed (<span class="speedUnit"></span>)</td>
<td id="vert_rate" onclick="sortByVerticalRate();" style="text-align: right">Vertical Rate (<span id="header_vert_rate_unit"></span>)</td> <td id="vert_rate" onclick="sortByVerticalRate();" style="text-align: right">Vertical Rate (<span class="verticalRateUnit"></span>)</td>
<td id="distance" onclick="sortByDistance();" style="text-align: right">Distance (<span id="header_distance_unit"></span>)</td> <td id="distance" onclick="sortByDistance();" style="text-align: right">Distance (<span class="distanceUnit"></span>)</td>
<td id="track" onclick="sortByTrack();" style="text-align: right">Track</td> <td id="track" onclick="sortByTrack();" style="text-align: right">Track</td>
<td id="msgs" onclick="sortByMsgs();" style="text-align: right">Msgs</td> <td id="msgs" onclick="sortByMsgs();" style="text-align: right">Msgs</td>
<td id="seen" onclick="sortBySeen();" style="text-align: right">Age</td> <td id="seen" onclick="sortBySeen();" style="text-align: right">Age</td>

File diff suppressed because one or more lines are too long

View file

@ -41,6 +41,7 @@ function PlaneObject(icao) {
this.markerIcon = null; this.markerIcon = null;
this.markerStyleKey = null; this.markerStyleKey = null;
this.markerSvgKey = null; this.markerSvgKey = null;
this.filter = {};
// request metadata // request metadata
this.registration = null; this.registration = null;
@ -60,6 +61,18 @@ function PlaneObject(icao) {
}.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) {
@ -413,7 +426,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;
} }
@ -466,9 +479,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);

View file

@ -9,6 +9,7 @@ var PlaneIconFeatures = new ol.Collection();
var PlaneTrailFeatures = new ol.Collection(); var PlaneTrailFeatures = new ol.Collection();
var Planes = {}; var Planes = {};
var PlanesOrdered = []; var PlanesOrdered = [];
var PlaneFilter = {};
var SelectedPlane = null; var SelectedPlane = null;
var SelectedAllPlanes = false; var SelectedAllPlanes = false;
var FollowSelected = false; var FollowSelected = false;
@ -73,6 +74,7 @@ function processReceiverUpdate(data) {
plane = Planes[hex]; plane = Planes[hex];
} 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] === '~') {
@ -226,6 +228,28 @@ function initialize() {
// Initialize other controls // Initialize other controls
initializeUnitsSelector(); 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 // Force map to redraw if sidebar container is resized - use a timer to debounce
var mapResizeTimeout; var mapResizeTimeout;
$("#sidebar_container").on("resize", function() { $("#sidebar_container").on("resize", function() {
@ -793,10 +817,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++;
@ -837,11 +866,6 @@ function refreshTableInfo() {
tableplane.tr.cells[18].innerHTML = getFlightAwareModeSLink(tableplane.icao); tableplane.tr.cells[18].innerHTML = getFlightAwareModeSLink(tableplane.icao);
tableplane.tr.cells[19].innerHTML = getFlightAwarePhotoLink(tableplane.registration); tableplane.tr.cells[19].innerHTML = getFlightAwarePhotoLink(tableplane.registration);
tableplane.tr.className = classes; tableplane.tr.className = classes;
$("#header_altitude_unit").text(get_unit_label("altitude", DisplayUnits));
$("#header_speed_unit").text(get_unit_label("speed", DisplayUnits));
$("#header_distance_unit").text(get_unit_label("distance", DisplayUnits));
$("#header_vert_rate_unit").text(get_unit_label("verticalRate", DisplayUnits));
} }
} }
@ -1004,7 +1028,7 @@ function selectAllPlanes() {
SelectedPlane = null; SelectedPlane = null;
for(var key in Planes) { for(var key in Planes) {
if (Planes[key].visible !== false) { if (Planes[key].visible && !Planes[key].isFiltered()) {
Planes[key].selected = true; Planes[key].selected = true;
Planes[key].updateLines(); Planes[key].updateLines();
Planes[key].updateMarker(); Planes[key].updateMarker();
@ -1020,7 +1044,7 @@ function selectAllPlanes() {
function selectNewPlanes() { function selectNewPlanes() {
if (SelectedAllPlanes) { if (SelectedAllPlanes) {
for (var key in Planes) { for (var key in Planes) {
if (Planes[key].visible === false) { if (!Planes[key].visible || Planes[key].isFiltered()) {
Planes[key].selected = false; Planes[key].selected = false;
Planes[key].clearLines(); Planes[key].clearLines();
Planes[key].updateMarker(); Planes[key].updateMarker();
@ -1152,6 +1176,9 @@ function onDisplayUnitsChanged(e) {
localStorage['displayUnits'] = displayUnits; localStorage['displayUnits'] = displayUnits;
DisplayUnits = displayUnits; DisplayUnits = displayUnits;
// Update filters
updatePlaneFilter();
// Refresh data // Refresh data
refreshTableInfo(); refreshTableInfo();
refreshSelected(); refreshSelected();
@ -1169,6 +1196,46 @@ function onDisplayUnitsChanged(e) {
}); });
} }
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) { function getFlightAwareIdentLink(ident) {
if (ident !== null && ident !== "") { if (ident !== null && ident !== "") {
return "<a target=\"_blank\" href=\"https://flightaware.com/live/flight/" + ident.trim() + "\">" + ident + "</a>"; return "<a target=\"_blank\" href=\"https://flightaware.com/live/flight/" + ident.trim() + "\">" + ident + "</a>";

View file

@ -108,7 +108,9 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right:
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; } #tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
#units_selector { #units_container,
#altitude_filter_form {
font-size: small;
margin: 10px 0 10px 0; margin: 10px 0 10px 0;
} }
@ -133,3 +135,11 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right:
.pointer { cursor: pointer; } .pointer { cursor: pointer; }
.altitudeFilterInput {
width: 50px;
}
select.error, textarea.error, input.error {
color: #FF0000;
}