Allow custom selection of columns in aircraft table (#72)

* Front-end/styling of window with checkbox options to customize plane table columns

* Toggle checkbox functionality with persistence

* Toggle correct columns for each checkbox

* Add several more column options and fix up logic to show/hide columns

* Functional select/deselect all checkboxes; Needs optimization

* Set overflow-x to scroll on aircraft table

* Select Columns button styling

* Refactor toggleAllColumns()

* Separate legend from table scrolling

* Move aircraft table styling into css file

* Spacing

Co-authored-by: erictran <eric.tran@flightaware.com>
This commit is contained in:
biggezy 2020-07-21 10:00:32 -05:00 committed by GitHub
parent 74ef2e92bd
commit 0dae3e4b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 374 additions and 73 deletions

View File

@ -224,71 +224,168 @@
<button id="altitude_filter_reset_button">Reset</button> <button id="altitude_filter_reset_button">Reset</button>
</form> </form>
<div id="planes_table"> <div>
<table id="tableinfo" style="width: 100%"> <button id="column_select">Select Columns</button>
<thead class="aircraft_table_header"> </div>
<tr>
<td id="icao" onclick="sortByICAO();">ICAO</td> <div id="column_select_window" class="hidden">
<td id="flag" onclick="sortByCountry()"><!-- column for flag image --></td> <div id="column_select_close_box"></div>
<td id="flight" onclick="sortByFlight();"> Ident </td> <div id="column_select_header">Columns</div>
<td id="registration" onclick="sortByRegistration();">Registration</td> <div class="columnOptionSelectAllContainer">
<td id="aircraft_type" onclick="sortByAircraftType();"> Aircraft type</td> <div class="columnSelectAllCheckbox" id="select_all_column_checkbox"></div>
<td id="squawk" onclick="sortBySquawk();">Squawk</td> <div class="columnOptionText">Select/Deselect All</div>
<td id="altitude" onclick="sortByAltitude();">Altitude (<span class="altitudeUnit"></span>)</td>
<td id="speed" onclick="sortBySpeed();">Speed (<span class="speedUnit"></span>)</td>
<td id="vert_rate" onclick="sortByVerticalRate();">Vertical Rate (<span class="verticalRateUnit"></span>)</td>
<td id="distance" onclick="sortByDistance();">Distance (<span class="distanceUnit"></span>)</td>
<td id="track" onclick="sortByTrack();">Heading</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</td>
<td id="flightaware_mode_s_link">FlightAware</td>
<td id="flightaware_photo_link">Photos</td>
</tr>
</thead>
<tbody>
<tr id="plane_row_template" class="plane_table_row hidden">
<td class="icaoCodeColumn">ICAO</td>
<td><img style="width: 20px; height: 12px;" src="about:blank" alt="Flag"></td>
<td>FLIGHT</td>
<td>REGISTRATION</td>
<td>AIRCRAFT_TYPE</td>
<td style="text-align: right">SQUAWK</td>
<td style="text-align: right">ALTITUDE</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">TRACK</td>
<td style="text-align: right">MSGS</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>
</tbody>
</table>
<div class="legend">
<div class="legendBox vPosition"></div>
<div class="legendTitle">ADS-B</div>
<div class="legendBox mlat"></div>
<div class="legendTitle">MLAT</div>
<div class="legendBox other"></div>
<div class="legendTitle">Other</div>
<div class="legendBox tisb"></div>
<div class="legendTitle">TIS-B</div>
</div> </div>
</div> <!-- planes_table --> <div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="icao_col_checkbox"></div>
<div class="columnOptionText">Icao</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="flag_col_checkbox"></div>
<div class="columnOptionText">Flag</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="ident_col_checkbox"></div>
<div class="columnOptionText">Ident</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="reg_col_checkbox"></div>
<div class="columnOptionText">Registration</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="ac_col_checkbox"></div>
<div class="columnOptionText">Aircraft Type</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="squawk_col_checkbox"></div>
<div class="columnOptionText">Squawk</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="alt_col_checkbox"></div>
<div class="columnOptionText">Altitude</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="speed_col_checkbox"></div>
<div class="columnOptionText">Speed</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="vrate_col_checkbox"></div>
<div class="columnOptionText">Vertical Rate</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="distance_col_checkbox"></div>
<div class="columnOptionText">Distance</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="heading_col_checkbox"></div>
<div class="columnOptionText">Heading</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="messages_col_checkbox"></div>
<div class="columnOptionText">Messages</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="msg_age_col_checkbox"></div>
<div class="columnOptionText">Message Age</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="rssi_col_checkbox"></div>
<div class="columnOptionText">RSSI</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="lat_col_checkbox"></div>
<div class="columnOptionText">Latitude</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="lon_col_checkbox"></div>
<div class="columnOptionText">Longitude</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="datasource_col_checkbox"></div>
<div class="columnOptionText">Data Source</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="airframes_col_checkbox"></div>
<div class="columnOptionText">Airframes.org</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="fa_modes_link_checkbox"></div>
<div class="columnOptionText">FlightAware</div>
</div>
<div class="columnOptionContainer">
<div class="columnSelectCheckbox" id="fa_photo_link_checkbox"></div>
<div class="columnOptionText">Photos</div>
</div>
</div>
<div id="planes_table_container">
<div id="planes_table">
<table id="tableinfo" style="width: 100%">
<thead class="aircraft_table_header">
<tr>
<td id="icao" onclick="sortByICAO();">ICAO</td>
<td id="flag" onclick="sortByCountry()"><!-- column for flag image --></td>
<td id="flight" onclick="sortByFlight();"> Ident </td>
<td id="registration" onclick="sortByRegistration();">Registration</td>
<td id="aircraft_type" onclick="sortByAircraftType();"> Aircraft type</td>
<td id="squawk" onclick="sortBySquawk();">Squawk</td>
<td id="altitude" onclick="sortByAltitude();">Altitude (<span class="altitudeUnit"></span>)</td>
<td id="speed" onclick="sortBySpeed();">Speed (<span class="speedUnit"></span>)</td>
<td id="vert_rate" onclick="sortByVerticalRate();">Vertical Rate (<span class="verticalRateUnit"></span>)</td>
<td id="distance" onclick="sortByDistance();">Distance (<span class="distanceUnit"></span>)</td>
<td id="track" onclick="sortByTrack();">Heading</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</td>
<td id="flightaware_mode_s_link">FlightAware</td>
<td id="flightaware_photo_link">Photos</td>
</tr>
</thead>
<tbody>
<tr id="plane_row_template" class="plane_table_row hidden">
<td class="icaoCodeColumn">ICAO</td>
<td><img style="width: 20px; height=12px" src="about:blank" alt="Flag"></td>
<td>FLIGHT</td>
<td>REGISTRATION</td>
<td>AIRCRAFT_TYPE</td>
<td style="text-align: right">SQUAWK</td>
<td style="text-align: right">ALTITUDE</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">TRACK</td>
<td style="text-align: right">MSGS</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>
</tbody>
</table>
</div> <!-- planes_table -->
<div>
<div class="legend">
<div class="legendBox vPosition"></div>
<div class="legendTitle">ADS-B</div>
<div class="legendBox mlat"></div>
<div class="legendTitle">MLAT</div>
<div class="legendBox other"></div>
<div class="legendTitle">Other</div>
<div class="legendBox tisb"></div>
<div class="legendTitle">TIS-B</div>
</div>
</div>
</div> <!-- planes_table_container -->
</div> </div>
</div> <!-- sidebar_canvas --> </div> <!-- sidebar_canvas -->

View File

@ -53,6 +53,30 @@ var layers;
// piaware vs flightfeeder // piaware vs flightfeeder
var isFlightFeeder = false; var isFlightFeeder = false;
var checkbox_div_map = new Map ([
['#icao_col_checkbox', '#icao'],
['#flag_col_checkbox', '#flag'],
['#ident_col_checkbox', '#flight'],
['#reg_col_checkbox', '#registration'],
['#ac_col_checkbox', '#aircraft_type'],
['#squawk_col_checkbox', '#squawk'],
['#alt_col_checkbox', '#altitude'],
['#speed_col_checkbox', '#speed'],
['#vrate_col_checkbox', '#vert_rate'],
['#distance_col_checkbox', '#distance'],
['#heading_col_checkbox', '#track'],
['#messages_col_checkbox', '#msgs'],
['#msg_age_col_checkbox', '#seen'],
['#rssi_col_checkbox', '#rssi'],
['#lat_col_checkbox', '#lat'],
['#lon_col_checkbox', '#lon'],
['#datasource_col_checkbox', '#data_source'],
['#airframes_col_checkbox', '#airframes_mode_s_link'],
['#fa_modes_link_checkbox', '#flightaware_mode_s_link'],
['#fa_photo_link_checkbox', '#flightaware_photo_link'],
]);
function processReceiverUpdate(data) { function processReceiverUpdate(data) {
// Loop through all the planes in the data packet // Loop through all the planes in the data packet
var now = data.now; var now = data.now;
@ -302,6 +326,14 @@ function initialize() {
$('#settings_infoblock').toggle(); $('#settings_infoblock').toggle();
}); });
$('#column_select').on('click', function() {
$('#column_select_window').toggle();
});
$('#column_select_close_box').on('click', function() {
$('#column_select_window').hide();
});
$('#settings_close').on('click', function() { $('#settings_close').on('click', function() {
$('#settings_infoblock').hide(); $('#settings_infoblock').hide();
}); });
@ -332,6 +364,17 @@ function initialize() {
toggleAllPlanes(true); toggleAllPlanes(true);
}) })
$('#select_all_column_checkbox').on('click', function() {
toggleAllColumns(true);
})
// Event handlers for to column checkboxes
checkbox_div_map.forEach(function (checkbox, div) {
$(div).on('click', function() {
toggleColumn(checkbox, div, true);
});
});
// 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() {
@ -344,6 +387,7 @@ function initialize() {
toggleAltitudeChart(false); toggleAltitudeChart(false);
toggleAllPlanes(false); toggleAllPlanes(false);
toggleGroupByDataType(false); toggleGroupByDataType(false);
toggleAllColumns(false);
// Get receiver metadata, reconfigure using it, then continue // Get receiver metadata, reconfigure using it, then continue
// with initialization // with initialization
@ -1626,16 +1670,42 @@ function setColumnVisibility() {
var mapIsVisible = $("#map_container").is(":visible"); var mapIsVisible = $("#map_container").is(":visible");
var infoTable = $("#tableinfo"); var infoTable = $("#tableinfo");
showColumn(infoTable, "#registration", !mapIsVisible); var defaultCheckBoxes = [
showColumn(infoTable, "#aircraft_type", !mapIsVisible); '#icao_col_checkbox',
showColumn(infoTable, "#vert_rate", !mapIsVisible); '#flag_col_checkbox',
showColumn(infoTable, "#rssi", !mapIsVisible); '#ident_col_checkbox',
showColumn(infoTable, "#lat", !mapIsVisible); '#squawk_col_checkbox',
showColumn(infoTable, "#lon", !mapIsVisible); '#alt_col_checkbox',
showColumn(infoTable, "#data_source", !mapIsVisible); '#speed_col_checkbox',
showColumn(infoTable, "#airframes_mode_s_link", !mapIsVisible); '#distance_col_checkbox',
showColumn(infoTable, "#flightaware_mode_s_link", !mapIsVisible); '#heading_col_checkbox',
showColumn(infoTable, "#flightaware_photo_link", !mapIsVisible); '#messages_col_checkbox',
'#msg_age_col_checkbox'
]
// Show default columns if checkboxes have not been set
for (var i=0; i < defaultCheckBoxes.length; i++) {
var checkBoxdiv = defaultCheckBoxes[i];
var columnDiv = checkbox_div_map.get(checkBoxdiv)
if (typeof localStorage[checkBoxdiv] === 'undefined') {
$(checkBoxdiv).addClass('settingsCheckboxChecked');
localStorage.setItem(checkBoxdiv, 'selected');
showColumn(infoTable, columnDiv, true);
}
}
// Now check local storage checkbox status
checkbox_div_map.forEach(function (div, checkbox) {
var status = localStorage.getItem(checkbox);
if (status === 'selected') {
$(checkbox).addClass('settingsCheckboxChecked');
showColumn(infoTable, div, true);
} else {
$(checkbox).removeClass('settingsCheckboxChecked');
showColumn(infoTable, div, false);
}
});
} }
function setSelectedInfoBlockVisibility() { function setSelectedInfoBlockVisibility() {
@ -1991,3 +2061,64 @@ function onSetRangeRings() {
createSiteCircleFeatures(); createSiteCircleFeatures();
} }
function toggleColumn(div, checkbox, toggled) {
if (typeof localStorage[checkbox] === 'undefined') {
localStorage.setItem(checkbox, 'deselected');
}
var status = localStorage.getItem(checkbox);
var infoTable = $("#tableinfo");
if (toggled === true) {
status = (status === 'deselected') ? 'selected' : 'deselected';
}
// Toggle checkbox and column visibility
if (status === 'selected') {
$(checkbox).addClass('settingsCheckboxChecked');
showColumn(infoTable, div, true);
} else {
$(checkbox).removeClass('settingsCheckboxChecked');
showColumn(infoTable, div, false);
$('#select_all_column_checkbox').removeClass('settingsCheckboxChecked');
localStorage.setItem('selectAllColumnsCheckbox', 'deselected');
}
localStorage.setItem(checkbox, status);
}
function toggleAllColumns(switchToggle) {
if (typeof localStorage['selectAllColumnsCheckbox'] === 'undefined') {
ocalStorage.setItem('selectAllColumnsCheckbox','deselected');
}
var infoTable = $("#tableinfo");
var selectAllColumnsCheckbox = localStorage.getItem('selectAllColumnsCheckbox');
if (switchToggle === true) {
selectAllColumnsCheckbox = (selectAllColumnsCheckbox === 'deselected') ? 'selected' : 'deselected';
checkbox_div_map.forEach(function (div, checkbox) {
if (selectAllColumnsCheckbox === 'deselected') {
$('#select_all_column_checkbox').removeClass('settingsCheckboxChecked');
$(checkbox).removeClass('settingsCheckboxChecked');
showColumn(infoTable, div, false);
} else {
$('#select_all_column_checkbox').addClass('settingsCheckboxChecked');
$(checkbox).addClass('settingsCheckboxChecked');
showColumn(infoTable, div, true);
}
localStorage.setItem(checkbox, selectAllColumnsCheckbox);
});
};
if (selectAllColumnsCheckbox === 'deselected') {
$('#select_all_column_checkbox').removeClass('settingsCheckboxChecked');
} else {
$('#select_all_column_checkbox').addClass('settingsCheckboxChecked');
}
localStorage.setItem('selectAllColumnsCheckbox', selectAllColumnsCheckbox);
}

View File

@ -45,6 +45,79 @@ html, body {
height: 100%; height: 100%;
} }
#planes_table_container {
width: 100%;
display: flex;
flex-direction: column;
}
#planes_table {
overflow-x: scroll;
}
#column_select {
position: relative;
float: right;
background-color: #002F5D;
color: #FFFFFF;
}
#column_select_window {
position: absolute;
right: 1px;
top: 80px;
width: 150px;
min-height: 180px;
background: #ffffff;
box-shadow: 4px 4px 10px #444444;
padding: 20px;
z-index: 9999;
display: none;
}
#column_select_header {
display: table;
background-color: #002F5D;
color: #ffffff;
font-size: smaller;
padding: 5px;
text-align: center;
width: 120px;
}
#column_select_close_box {
position: absolute;
right: 15px;
top: 21px;
background-image: url('images/close-settings.png');
background-size: cover;
width: 20px;
height: 20px;
cursor: pointer;
}
.columnOptionContainer {
position: relative;
display: table;
padding-top: 5px;
left: 20px;
}
.columnOptionSelectAllContainer {
position: relative;
display: table;
padding-top: 5px;
}
.columnOptionText {
position: relative;
line-height: 10px;
display: table-cell;
width: 100%;
left: 5px;
}
#toggle_sidebar_control { #toggle_sidebar_control {
display: block; display: block;
position: absolute; position: absolute;
@ -636,7 +709,7 @@ select.error, textarea.error, input.error {
padding-bottom: 10px; padding-bottom: 10px;
} }
.settingsCheckbox { .settingsCheckbox, .columnSelectCheckbox, .columnSelectAllCheckbox {
width: 20px; width: 20px;
height: 11px; height: 11px;
background-image: url('images/box-empty.png'); background-image: url('images/box-empty.png');