Phi: some cleanup and a airport chart
- fix a cornercase bug in the RouteLayer - some cleanup in the map widget - add a airport chart as a start for a reposition dialog
This commit is contained in:
parent
f9923979b5
commit
c68f3f5cc9
4 changed files with 256 additions and 7 deletions
webgui
68
webgui/topics/Environment/Position.html
Normal file
68
webgui/topics/Environment/Position.html
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<fieldset data-bind="visible: hasAirports">
|
||||||
|
<legend>Airports</legend>
|
||||||
|
<input type="text" data-bind="autocomplete: { source: airports, select: onSelect }" style="width: 100%;">
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div style="width=100%" data-bind="with: selectedAirport">
|
||||||
|
<div style="float: left;">
|
||||||
|
<div style="font-size: 20pt; font-weight: bold;" data-bind="text: id"></div>
|
||||||
|
<div>
|
||||||
|
<span style="font-size: 12pt; font-weight: normal;">Apt Elev </span>
|
||||||
|
<span style="font-size: 14pt; font-weight: bold;" data-bind="text: elevation"></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 style="float: right;">
|
||||||
|
<div>
|
||||||
|
<!--
|
||||||
|
<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;" data-bind="text: country"></span>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span style="font-size: 14pt; font-weight: normal; float: right" data-bind="text: name"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui-helper-clearfix"></div>
|
||||||
|
|
||||||
|
<fieldset data-bind="with: selectedAirport">
|
||||||
|
<legend>Communication</legend>
|
||||||
|
<table style="width: 100%">
|
||||||
|
<tr data-bind="foreach: comm">
|
||||||
|
<td>
|
||||||
|
<div data-bind="text: name" style="text-align: center"></div>
|
||||||
|
<div data-bind="foreach: frequencies" style="text-align: center">
|
||||||
|
<span data-bind="text: $data"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<div id="phi-environment-position-map" style="height: 400px;"></div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset data-bind="with: selectedAirport">
|
||||||
|
<legend>Runway Information</legend>
|
||||||
|
<table style="width: 100%" data-bind="foreach: runway">
|
||||||
|
<tr>
|
||||||
|
<td><span data-bind="text: id"></span></td>
|
||||||
|
<td><span data-bind="text: heading"></span>°</td>
|
||||||
|
<td><span data-bind="text: surface"></span></td>
|
||||||
|
<td><span data-bind="text: lengthFt"></span>ft <span data-bind="text: lengthM"></span>m</td>
|
||||||
|
<td><span data-bind="text: widthFt"></span>ft <span data-bind="text: widthM"></span>m</td>
|
||||||
|
<td><span data-bind="text: displacedThresholdFt"></span>ft <span data-bind="text: displacedThresholdM"></span>m</td>
|
||||||
|
<td><span data-bind="text: stopwayFt"></span>ft <span data-bind="text: stopwayM"></span>m</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</fieldset>
|
||||||
|
|
180
webgui/topics/Environment/Position.js
Normal file
180
webgui/topics/Environment/Position.js
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
define([
|
||||||
|
'jquery', 'knockout', 'text!./Position.html', 'sprintf', 'leaflet', 'kojqui/autocomplete'
|
||||||
|
], function( jquery, ko, htmlString, sprintf, leaflet ) {
|
||||||
|
|
||||||
|
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;
|
||||||
|
self.geoJson = geoJson;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
self.geoJson.clearLayers();
|
||||||
|
self.geoJson.addData(airport);
|
||||||
|
self.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.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([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.map = leaflet.map("phi-environment-position-map", {
|
||||||
|
dragging: false,
|
||||||
|
touchZoom: false,
|
||||||
|
scrollWheelZoom: false,
|
||||||
|
});
|
||||||
|
self.geoJson = leaflet.geoJson(null,{
|
||||||
|
style : function(feature) {
|
||||||
|
return {
|
||||||
|
color : 'black',
|
||||||
|
weight : 3,
|
||||||
|
fill : 'true',
|
||||||
|
fillColor : '#606060',
|
||||||
|
fillOpacity : 1.0,
|
||||||
|
lineJoin : 'bevel',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.geoJson._map = self.map;
|
||||||
|
self.geoJson.addTo(self.map);
|
||||||
|
|
||||||
|
self.airports = ko.observableArray([]);
|
||||||
|
getAirportList(self.airports);
|
||||||
|
self.hasAirports = ko.pureComputed(function() {
|
||||||
|
return self.airports().length;
|
||||||
|
});
|
||||||
|
|
||||||
|
self.selectedAirport = ko.observable();
|
||||||
|
|
||||||
|
self.onSelect = function(ev,ui) {
|
||||||
|
self.selectedAirport(new AirportViewModel(self.geoJson,getAirportId(ui.item.value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.prototype.dispose = function() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
|
@ -14,7 +14,6 @@
|
||||||
options : {
|
options : {
|
||||||
|
|
||||||
style : function(feature) {
|
style : function(feature) {
|
||||||
console.log(this,feature);
|
|
||||||
if (feature.geometry.type == "LineString")
|
if (feature.geometry.type == "LineString")
|
||||||
return {
|
return {
|
||||||
'color' : '#4d56db',
|
'color' : '#4d56db',
|
||||||
|
@ -43,8 +42,10 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
stop : function() {
|
stop : function() {
|
||||||
this.waypointCountSubscription.dispose();
|
if (this.waypointCountSubscription) {
|
||||||
this.waypointCount.dispose();
|
this.waypointCountSubscription.dispose();
|
||||||
|
this.waypointCount.dispose();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
update : function(id) {
|
update : function(id) {
|
||||||
|
|
|
@ -28,11 +28,11 @@ define(
|
||||||
|
|
||||||
if (params && params.css) {
|
if (params && params.css) {
|
||||||
for ( var p in params.css) {
|
for ( var p in params.css) {
|
||||||
$(self.element).css(p, params.css[p]);
|
jquery(self.element).css(p, params.css[p]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($(self.element).height() < 1) {
|
if (jquery(self.element).height() < 1) {
|
||||||
$(self.element).css("min-height", $(self.element).width());
|
jquery(self.element).css("min-height", jquery(self.element).width());
|
||||||
}
|
}
|
||||||
|
|
||||||
var MapOptions = {
|
var MapOptions = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue