Phi: Some tweaks for the Airport selection page
- Add a busy message while loading airport list - Add METAR for the airport (if available) - Remove cyclic object reference by making map and layer private
This commit is contained in:
parent
89b304cd1f
commit
872b40828a
2 changed files with 96 additions and 62 deletions
|
@ -1,71 +1,69 @@
|
||||||
<style>
|
<style>
|
||||||
.ui-autocomplete {
|
.ui-autocomplete {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
/* prevent horizontal scrollbar */
|
/* prevent horizontal scrollbar */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric {
|
.metric {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<fieldset data-bind="visible: hasAirports">
|
<fieldset data-bind="visible: hasAirports">
|
||||||
<legend>Search (enter at least two characters of airport name or id)</legend>
|
<legend>Search (enter at least two characters of airport name or id)</legend>
|
||||||
<input type="text" data-bind="autocomplete: { minLength: 2, source: airports, select: onSelect }" style="width: 100%;">
|
<input type="text" data-bind="autocomplete: { minLength: 2, source: airports, select: onSelect }" style="width: 100%;">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<h1 data-bind="visible: isLoading">Please wait... Loading Airports...</h1>
|
||||||
<div style="width=100%" data-bind="with: selectedAirport">
|
<div style="" data-bind="with: selectedAirport">
|
||||||
<div style="float: left;">
|
<div style="float: left;">
|
||||||
<div style="font-size: 20pt; font-weight: bold;" data-bind="text: id"></div>
|
<div style="font-size: 20pt; font-weight: bold;" data-bind="text: id"></div>
|
||||||
<div>
|
<div>
|
||||||
<span style="font-size: 12pt; font-weight: normal;">Apt Elev </span>
|
<span style="font-size: 12pt; font-weight: normal;">Apt Elev </span> <span style="font-size: 14pt; font-weight: bold;"
|
||||||
<span style="font-size: 14pt; font-weight: bold;" data-bind="text: elevation"></span>
|
data-bind="text: elevation"></span> <span style="font-size: 14pt; font-weight: bold;">'</span>
|
||||||
<span style="font-size: 14pt; font-weight: bold;">'</span>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span style="font-size: 12pt; font-weight: normal;" data-bind="text: arpFormatted"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style="float: right;">
|
||||||
<span style="font-size: 12pt; font-weight: normal;" data-bind="text: arpFormatted"></span>
|
<div>
|
||||||
</div>
|
<span style="font-size: 20pt; font-weight: normal; float: right" data-bind="text: name"></span>
|
||||||
</div>
|
</div>
|
||||||
<div style="float: right;">
|
<div>
|
||||||
<div>
|
<!--
|
||||||
<span style="font-size: 20pt; font-weight: normal; float: right" data-bind="text: name"></span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<!--
|
|
||||||
<span style="font-size: 20pt; font-weight: bold;" data-bind="text: city"></span>
|
<span style="font-size: 20pt; font-weight: bold;" data-bind="text: city"></span>
|
||||||
<span style="font-size: 20pt; font-weight: bold;">, </span>
|
<span style="font-size: 20pt; font-weight: bold;">, </span>
|
||||||
<span style="font-size: 20pt; font-weight: bold;" data-bind="text: country"></span>
|
<span style="font-size: 20pt; font-weight: bold;" data-bind="text: country"></span>
|
||||||
-->
|
-->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="ui-helper-clearfix"></div>
|
<div class="ui-helper-clearfix"></div>
|
||||||
|
|
||||||
<fieldset data-bind="with: selectedAirport, visible: selectedAirport">
|
<fieldset data-bind="with: selectedAirport, visible: selectedAirport">
|
||||||
<legend>Communication</legend>
|
<legend>Communication</legend>
|
||||||
<table style="width: 100%">
|
<table style="width: 100%">
|
||||||
<tr data-bind="foreach: comm">
|
<tr data-bind="foreach: comm">
|
||||||
<td>
|
<td>
|
||||||
<div data-bind="text: name" style="text-align: center"></div>
|
<div data-bind="text: name" style="text-align: center"></div>
|
||||||
<div data-bind="foreach: frequencies" style="text-align: center">
|
<div data-bind="foreach: frequencies" style="text-align: center">
|
||||||
<span data-bind="text: $data"></span>
|
<span data-bind="text: $data"></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset data-bind="visible: selectedAirport">
|
<fieldset data-bind="visible: selectedAirport">
|
||||||
<div id="phi-environment-position-map" style="height: 400px;"></div>
|
<div id="phi-environment-position-map" style="height: 400px;"></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset data-bind="with: selectedAirport, visible: selectedAirport">
|
<fieldset data-bind="with: selectedAirport, visible: selectedAirport">
|
||||||
<legend>Runway Information</legend>
|
<legend>Runway Information</legend>
|
||||||
<table style="width: 100%">
|
<table style="width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left">RWY</th>
|
<th style="text-align: left">RWY</th>
|
||||||
<th style="text-align: right">True</th>
|
<th style="text-align: right">True</th>
|
||||||
|
@ -77,18 +75,28 @@ overflow-x: hidden;
|
||||||
<th style="text-align: left"></th>
|
<th style="text-align: left"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-bind="foreach: runway">
|
<tbody data-bind="foreach: runway">
|
||||||
<tr>
|
<tr>
|
||||||
<td><span data-bind="text: id"></span></td>
|
<td><span data-bind="text: id"></span></td>
|
||||||
<td style="text-align: right;"><span data-bind="text: heading"></span>°</td>
|
<td style="text-align: right;"><span data-bind="text: heading"></span>°</td>
|
||||||
<td><span data-bind="text: surface"></span></td>
|
<td><span data-bind="text: surface"></span></td>
|
||||||
<td><span data-bind="text: lengthFt"></span>ft <span data-bind="text: lengthM" class="metric"></span><span class="metric">m</span></td>
|
<td><span data-bind="text: lengthFt"></span>ft <span data-bind="text: lengthM" class="metric"></span><span
|
||||||
<td><span data-bind="text: widthFt"></span>ft <span data-bind="text: widthM" class="metric"></span><span class="metric">m</span></td>
|
class="metric">m</span></td>
|
||||||
<td><span data-bind="text: displacedThresholdFt"></span>ft <span data-bind="text: displacedThresholdM" class="metric"></span><span class="metric">m</span></td>
|
<td><span data-bind="text: widthFt"></span>ft <span data-bind="text: widthM" class="metric"></span><span
|
||||||
<td><span data-bind="text: stopwayFt"></span>ft <span data-bind="text: stopwayM" class="metric"></span><span class="metric">m</span></td>
|
class="metric">m</span></td>
|
||||||
<td><button data-bind="button: { text: false, icons: { primary: 'ui-icon-arrowreturnthick-1-e' } }, click: $parent.gotoRwy">Restart here</button></td>
|
<td><span data-bind="text: displacedThresholdFt"></span>ft <span data-bind="text: displacedThresholdM"
|
||||||
</tr>
|
class="metric"></span><span class="metric">m</span></td>
|
||||||
</tbody>
|
<td><span data-bind="text: stopwayFt"></span>ft <span data-bind="text: stopwayM" class="metric"></span><span
|
||||||
</table>
|
class="metric">m</span></td>
|
||||||
|
<td><button
|
||||||
|
data-bind="button: { text: false, icons: { primary: 'ui-icon-arrowreturnthick-1-e' } }, click: $parent.gotoRwy">Restart
|
||||||
|
here</button></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset data-bind="visible: metarValid">
|
||||||
|
<legend>Weather</legend>
|
||||||
|
<div data-bind="text: metar"></div>
|
||||||
|
</fieldset>
|
||||||
|
|
|
@ -2,6 +2,8 @@ define([
|
||||||
'jquery', 'knockout', 'text!./Position.html', 'sprintf', 'leaflet', 'fgcommand', 'kojqui/autocomplete'
|
'jquery', 'knockout', 'text!./Position.html', 'sprintf', 'leaflet', 'fgcommand', 'kojqui/autocomplete'
|
||||||
], function( jquery, ko, htmlString, sprintf, leaflet, fgcommand ) {
|
], function( jquery, ko, htmlString, sprintf, leaflet, fgcommand ) {
|
||||||
|
|
||||||
|
var MetarPropertiesPath = "/aaa";
|
||||||
|
|
||||||
function getAirportList(obs) {
|
function getAirportList(obs) {
|
||||||
if(typeof(Storage) !== "undefined") {
|
if(typeof(Storage) !== "undefined") {
|
||||||
var storedList = sessionStorage.getItem("phiPositionAirportlist");
|
var storedList = sessionStorage.getItem("phiPositionAirportlist");
|
||||||
|
@ -59,7 +61,6 @@ define([
|
||||||
|
|
||||||
function AirportViewModel(geoJson, id) {
|
function AirportViewModel(geoJson, id) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.geoJson = geoJson;
|
|
||||||
|
|
||||||
jquery.get("/navdb?q=airport&id=" + id ).done(function(data) {
|
jquery.get("/navdb?q=airport&id=" + id ).done(function(data) {
|
||||||
// expect geoJSON FeatureCollection
|
// expect geoJSON FeatureCollection
|
||||||
|
@ -82,6 +83,10 @@ define([
|
||||||
self.name(airport.properties.name);
|
self.name(airport.properties.name);
|
||||||
self.city(airport.properties.name);
|
self.city(airport.properties.name);
|
||||||
self.country(airport.properties.name);
|
self.country(airport.properties.name);
|
||||||
|
self.hasMetar(airport.properties.metar);
|
||||||
|
if(self.hasMetar()) {
|
||||||
|
fgcommand.requestMetar( self.id(), MetarPropertiesPath );
|
||||||
|
}
|
||||||
|
|
||||||
var comm = {};
|
var comm = {};
|
||||||
airport.properties.comm.forEach(function(c){
|
airport.properties.comm.forEach(function(c){
|
||||||
|
@ -100,9 +105,9 @@ define([
|
||||||
self.longitude(Number(arp[0]||0));
|
self.longitude(Number(arp[0]||0));
|
||||||
self.latitude(Number(arp[1]||0));
|
self.latitude(Number(arp[1]||0));
|
||||||
|
|
||||||
self.geoJson.clearLayers();
|
geoJson.clearLayers();
|
||||||
self.geoJson.addData(airport);
|
geoJson.addData(airport);
|
||||||
self.geoJson._map.setView([ self.latitude(), self.longitude() ], 13);
|
geoJson._map.setView([ self.latitude(), self.longitude() ], 13);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.id = ko.observable('');
|
self.id = ko.observable('');
|
||||||
|
@ -112,6 +117,7 @@ define([
|
||||||
self.elevation = ko.observable(0);
|
self.elevation = ko.observable(0);
|
||||||
self.longitude = ko.observable(0);
|
self.longitude = ko.observable(0);
|
||||||
self.latitude = ko.observable(0);
|
self.latitude = ko.observable(0);
|
||||||
|
self.hasMetar = ko.observable(false);
|
||||||
self.arpFormatted = ko.pureComputed(function() {
|
self.arpFormatted = ko.pureComputed(function() {
|
||||||
function dm(v) {
|
function dm(v) {
|
||||||
var s = v < 0;
|
var s = v < 0;
|
||||||
|
@ -189,12 +195,12 @@ define([
|
||||||
function ViewModel(params) {
|
function ViewModel(params) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.map = leaflet.map("phi-environment-position-map", {
|
var map = leaflet.map("phi-environment-position-map", {
|
||||||
dragging: false,
|
dragging: false,
|
||||||
touchZoom: false,
|
touchZoom: false,
|
||||||
scrollWheelZoom: false,
|
scrollWheelZoom: false,
|
||||||
});
|
});
|
||||||
self.geoJson = leaflet.geoJson(null,{
|
var geoJson = leaflet.geoJson(null,{
|
||||||
style : function(feature) {
|
style : function(feature) {
|
||||||
return {
|
return {
|
||||||
color : 'black',
|
color : 'black',
|
||||||
|
@ -206,8 +212,8 @@ define([
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.geoJson._map = self.map;
|
geoJson._map = map;
|
||||||
self.geoJson.addTo(self.map);
|
geoJson.addTo(map);
|
||||||
|
|
||||||
self.airports = ko.observableArray([]);
|
self.airports = ko.observableArray([]);
|
||||||
getAirportList(self.airports);
|
getAirportList(self.airports);
|
||||||
|
@ -215,14 +221,34 @@ define([
|
||||||
return self.airports().length;
|
return self.airports().length;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.isLoading = ko.pureComputed(function() {
|
||||||
|
return self.airports().length < 1;
|
||||||
|
});
|
||||||
|
|
||||||
self.selectedAirport = ko.observable();
|
self.selectedAirport = ko.observable();
|
||||||
|
|
||||||
|
self.metarValidFlag = ko.observable(0).extend({
|
||||||
|
observedProperty : MetarPropertiesPath + "/valid"
|
||||||
|
});
|
||||||
|
|
||||||
|
self.metarValid = ko.pureComputed(function(){
|
||||||
|
return self.metarValidFlag() && self.selectedAirport() && self.selectedAirport().hasMetar();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.metar = ko.observable(0).extend({
|
||||||
|
observedProperty : MetarPropertiesPath + "/data"
|
||||||
|
});
|
||||||
|
|
||||||
self.onSelect = function(ev,ui) {
|
self.onSelect = function(ev,ui) {
|
||||||
self.selectedAirport(new AirportViewModel(self.geoJson,getAirportId(ui.item.value)));
|
var id = getAirportId(ui.item.value);
|
||||||
|
self.selectedAirport(new AirportViewModel(geoJson,id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewModel.prototype.dispose = function() {
|
ViewModel.prototype.dispose = function() {
|
||||||
|
fgcommand.clearMetar(MetarPropertiesPath);
|
||||||
|
self.metar.dispose();
|
||||||
|
self.metarValidFlag.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return component definition
|
// Return component definition
|
||||||
|
|
Loading…
Add table
Reference in a new issue