1
0
Fork 0
fgdata/webgui/topics/Environment/Position.js
Torsten Dreyer 872b40828a 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
2015-03-30 21:15:16 +02:00

259 lines
7.5 KiB
JavaScript

define([
'jquery', 'knockout', 'text!./Position.html', 'sprintf', 'leaflet', 'fgcommand', 'kojqui/autocomplete'
], function( jquery, ko, htmlString, sprintf, leaflet, fgcommand ) {
var MetarPropertiesPath = "/aaa";
function getAirportList(obs) {
if(typeof(Storage) !== "undefined") {
var storedList = sessionStorage.getItem("phiPositionAirportlist");
if( storedList ) {
obs(JSON.parse(storedList));
return;
}
}
// get airport list only once
jquery.get("/navdb?q=airports").done(function(data) {
sessionStorage.setItem("phiPositionAirportlist",JSON.stringify(data));
obs(data);
}).fail(function() {
}).always(function() {
});
}
function getAirportId( txt ) {
var end = txt.lastIndexOf(')');
if( end < 0 ) return "";
var start = txt.lastIndexOf('(', end );
if( start < 0 ) return "";
return txt.substr(start+1,end-start-1);
}
function RunwayViewModel(rwy) {
var self = this;
self.id = ko.observable(rwy.id);
self.heading = ko.observable(Number(rwy.heading_deg||0).toFixed(0));
self.lengthM = ko.observable(Number(rwy.length_m||0).toFixed(0));
self.lengthFt = ko.pureComputed(function(){
return (self.lengthM()/0.3048).toFixed(0);
});
self.widthM = ko.observable(Number(rwy.width_m||0).toFixed(0));
self.widthFt = ko.pureComputed(function(){
return (self.widthM()/0.3048).toFixed(0);
});
self.displacedThresholdM = ko.observable(Number(rwy.dispacedThreshold_m||0).toFixed(0));
self.displacedThresholdFt = ko.pureComputed(function(){
return (self.displacedThresholdM()/0.3048).toFixed(0);
});
self.stopwayM = ko.observable(Number(rwy.stopway_m||0).toFixed(0));
self.stopwayFt = ko.pureComputed(function(){
return (self.stopwayM()/0.3048).toFixed(0);
});
self.surface = ko.observable(rwy.surface);
}
function AirportViewModel(geoJson, id) {
var self = this;
jquery.get("/navdb?q=airport&id=" + id ).done(function(data) {
// expect geoJSON FeatureCollection
if( "FeatureCollection" !== data.type )
return;
// expect one feature
if( !(data.features && data.features.length == 1) )
return;
var airport = data.features[0];
var rwy = self.runway();
airport.properties.runways.forEach(function(r){
rwy.push( new RunwayViewModel(r));
});
self.runway(rwy);
self.id(airport.properties.id);
self.name(airport.properties.name);
self.city(airport.properties.name);
self.country(airport.properties.name);
self.hasMetar(airport.properties.metar);
if(self.hasMetar()) {
fgcommand.requestMetar( self.id(), MetarPropertiesPath );
}
var comm = {};
airport.properties.comm.forEach(function(c){
var f = comm[c.id] || [];
f.push( c.mhz );
comm[c.id] = f;
});
var a = [];
for( var id in comm ) {
a.push({ name: id, frequencies: comm[id]} );
}
self.comm(a);
var arp = airport.geometry.geometries[0].coordinates;
self.elevation((Number(arp[2]||0)/0.3048).toFixed(0));
self.longitude(Number(arp[0]||0));
self.latitude(Number(arp[1]||0));
geoJson.clearLayers();
geoJson.addData(airport);
geoJson._map.setView([ self.latitude(), self.longitude() ], 13);
});
self.id = ko.observable('');
self.name = ko.observable('');
self.city = ko.observable('');
self.country = ko.observable('');
self.elevation = ko.observable(0);
self.longitude = ko.observable(0);
self.latitude = ko.observable(0);
self.hasMetar = ko.observable(false);
self.arpFormatted = ko.pureComputed(function() {
function dm(v) {
var s = v < 0;
if( s ) v = -v;
var d = v|0;
return {
's': s,
'd': d,
'm': (v-d)*60,
}
}
var lat = dm(self.latitude());
var lon = dm(self.longitude());
return sprintf.sprintf("%s%02d %3.1f %s%03d %3.1f",
lat.s ? 'S' : 'N', lat.d, lat.m, lon.s ? 'W' : 'E', lon.d, lon.m );
});
self.comm = ko.observableArray([]);
self.runway = ko.observableArray([]);
self.gotoRwy = function(ui,evt) {
var presets = {
children: [
{
'name': 'airport-id',
'value': self.id(),
},
{
'name': 'longitude-deg',
'value': -9999,
},
{
'name': 'latitude-deg',
'value': -9999,
},
{
'name': 'altitude-ft',
'value': -9999,
},
{
'name': 'airspeed-kt',
'value': 0,
},
{
'name': 'offset-distance-nm',
'value': 0,
},
{
'name': 'offset-azimuth-deg',
'value': 0,
},
{
'name': 'glideslope-deg',
'value': 0,
},
{
'name': 'heading-deg',
'value': 0,
},
{
'name': 'runway',
'value': ui.id(),
},
],
};
fgcommand.setPropertyValue( '/sim/presets', presets, function() {
fgcommand.reposition();
}, self );
}
}
function ViewModel(params) {
var self = this;
var map = leaflet.map("phi-environment-position-map", {
dragging: false,
touchZoom: false,
scrollWheelZoom: false,
});
var geoJson = leaflet.geoJson(null,{
style : function(feature) {
return {
color : 'black',
weight : 3,
fill : 'true',
fillColor : '#606060',
fillOpacity : 1.0,
lineJoin : 'bevel',
};
}
});
geoJson._map = map;
geoJson.addTo(map);
self.airports = ko.observableArray([]);
getAirportList(self.airports);
self.hasAirports = ko.pureComputed(function() {
return self.airports().length;
});
self.isLoading = ko.pureComputed(function() {
return self.airports().length < 1;
});
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) {
var id = getAirportId(ui.item.value);
self.selectedAirport(new AirportViewModel(geoJson,id));
}
}
ViewModel.prototype.dispose = function() {
fgcommand.clearMetar(MetarPropertiesPath);
self.metar.dispose();
self.metarValidFlag.dispose();
}
// Return component definition
return {
viewModel : ViewModel,
template : htmlString
};
});