diff --git a/webgui/main.js b/webgui/main.js index d908011d8..ac5856e1d 100644 --- a/webgui/main.js +++ b/webgui/main.js @@ -9,13 +9,13 @@ require.config({ leaflet : '3rdparty/leaflet-0.7.3/leaflet', text : '3rdparty/require/text', flot : '3rdparty/flot/jquery.flot', - fgcommand: 'lib/fgcommand', + fgcommand : 'lib/fgcommand', } }); require([ 'knockout', 'jquery', 'themeswitch' -], function(ko,jquery) { +], function(ko, jquery) { function KnockProps(aliases) { @@ -105,8 +105,8 @@ require([ var p = (self.props[prop] = ko.pureComputed({ read : target, write : function(newValue) { - if( newValue == target() ) - return; + if (newValue == target()) + return; target(newValue); target.notifySubscribers(newValue); } @@ -116,8 +116,8 @@ require([ return p; } - - this.write = function(prop,value) { + + this.write = function(prop, value) { var path = this.aliases[prop] || ""; if (path.length == 0) { console.log("can't write " + prop + ": unknown alias."); @@ -126,10 +126,24 @@ require([ this.ws.send(JSON.stringify({ command : 'set', node : path, - value: value - })); + value : value + })); } + this.propsToObject = function(prop, map, result) { + result = result || {} + prop.children.forEach(function(prop) { + var target = map[prop.name] || null; + if (target) { + if (typeof (result[target]) === 'function') { + result[target](prop.value); + } else { + result[target] = prop.value; + } + } + }); + return result; + } } ko.extenders.fgprop = function(target, prop) { @@ -227,6 +241,10 @@ require([ "gnd-temp", "/environment/config/boundary/entry/temperature-degc" ], [ "gnd-dewp", "/environment/config/boundary/entry/dewpoint-degc" + ], [ + "metar", "/environment/metar/data" + ], [ + "metar-valid", "/environment/metar/valid" ], ]); diff --git a/webgui/topics/Aircraft/MassBalance.js b/webgui/topics/Aircraft/MassBalance.js index 5cac9cf40..41041f339 100644 --- a/webgui/topics/Aircraft/MassBalance.js +++ b/webgui/topics/Aircraft/MassBalance.js @@ -46,7 +46,7 @@ define([ // or // if some other part of your code calls ko.removeNode(element) var plot = ko.utils.domData.set(element, "flotchart-plot", null); - // TODO: unsubscribe from data and options observables? + // TODO: unsubscribe from data and options observables!! }); }, diff --git a/webgui/topics/Environment/Weather.html b/webgui/topics/Environment/Weather.html new file mode 100644 index 000000000..274418dd1 --- /dev/null +++ b/webgui/topics/Environment/Weather.html @@ -0,0 +1,7 @@ +

Basic Troposphere Weather Conditions

+ +
+ + +
+
diff --git a/webgui/topics/Environment/Weather.js b/webgui/topics/Environment/Weather.js new file mode 100644 index 000000000..92d23ecee --- /dev/null +++ b/webgui/topics/Environment/Weather.js @@ -0,0 +1,52 @@ +define([ + 'knockout', 'text!./Weather.html', 'kojqui/buttonset' +], function(ko, htmlString) { + + ko.components.register('Environment/Weather/METAR', { + require : 'topics/Environment/Weather/METAR' + }); + + ko.components.register('Environment/Weather/Clouds', { + require : 'topics/Environment/Weather/CloudsLayers' + }); + + ko.components.register('Environment/Weather/Boundary', { + require : 'topics/Environment/Weather/Boundary' + }); + + ko.components.register('Environment/Weather/Aloft', { + require : 'topics/Environment/Weather/Aloft' + }); + + function ViewModel(params) { + var self = this; + + self.topics = [ + 'METAR', + 'Clouds', + 'Boundary', + 'Aloft', + ]; + + self.selectedTopic = ko.observable(); + + self.selectedComponent = ko.pureComputed(function() { + return "Environment/Weather/" + self.selectedTopic(); + }); + + self.selectTopic = function(topic) { + self.selectedTopic(topic); + } + + self.selectTopic(self.topics[0]); + } + + ViewModel.prototype.dispose = function() { + } + + // Return component definition + return { + viewModel : ViewModel, + template : htmlString + }; +}); diff --git a/webgui/topics/Environment/Weather/Aloft.html b/webgui/topics/Environment/Weather/Aloft.html new file mode 100644 index 000000000..1fc6035f5 --- /dev/null +++ b/webgui/topics/Environment/Weather/Aloft.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + +
Altitude (ft)Wind (dir/kt)Vis (m)Temp (°C)Dewp (°C)Turbulence
+ diff --git a/webgui/topics/Environment/Weather/Aloft.js b/webgui/topics/Environment/Weather/Aloft.js new file mode 100644 index 000000000..265ec7290 --- /dev/null +++ b/webgui/topics/Environment/Weather/Aloft.js @@ -0,0 +1,36 @@ +define([ + 'jquery', 'knockout', 'text!./Aloft.html', './LayerData', 'kojqui/selectmenu' +], function(jquery, ko, htmlString, layerData ) { + + function ViewModel(params) { + var self = this; + + self.layerData = ko.observableArray([]); + + jquery.get('/json/environment/config/aloft?d=2', null, function(data) { + + var assemble = function(data) { + var l = []; + data.children.forEach(function(prop) { + if (prop.name === 'entry') { + var layer = new layerData(); + l.push(ko.utils.knockprops.propsToObject(prop, layer.PropertyMap, layer )); + } + }); + return l.reverse(); + } + + self.layerData(assemble(data)); + }); + + } + +// ViewModel.prototype.dispose = function() { +// } + + // Return component definition + return { + viewModel : ViewModel, + template : htmlString + }; +}); diff --git a/webgui/topics/Environment/Weather/Boundary.html b/webgui/topics/Environment/Weather/Boundary.html new file mode 100644 index 000000000..1fc6035f5 --- /dev/null +++ b/webgui/topics/Environment/Weather/Boundary.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + +
Altitude (ft)Wind (dir/kt)Vis (m)Temp (°C)Dewp (°C)Turbulence
+ diff --git a/webgui/topics/Environment/Weather/Boundary.js b/webgui/topics/Environment/Weather/Boundary.js new file mode 100644 index 000000000..2caf26052 --- /dev/null +++ b/webgui/topics/Environment/Weather/Boundary.js @@ -0,0 +1,36 @@ +define([ + 'jquery', 'knockout', 'text!./Boundary.html', './LayerData', 'kojqui/selectmenu' +], function(jquery, ko, htmlString, layerData ) { + + function ViewModel(params) { + var self = this; + + self.layerData = ko.observableArray([]); + + jquery.get('/json/environment/config/boundary?d=2', null, function(data) { + + var assemble = function(data) { + var l = []; + data.children.forEach(function(prop) { + if (prop.name === 'entry') { + var layer = new layerData(); + l.push(ko.utils.knockprops.propsToObject(prop, layer.PropertyMap, layer )); + } + }); + return l.reverse(); + } + + self.layerData(assemble(data)); + }); + + } + +// ViewModel.prototype.dispose = function() { +// } + + // Return component definition + return { + viewModel : ViewModel, + template : htmlString + }; +}); diff --git a/webgui/topics/Environment/Weather/CloudLayers.html b/webgui/topics/Environment/Weather/CloudLayers.html new file mode 100644 index 000000000..4666adc12 --- /dev/null +++ b/webgui/topics/Environment/Weather/CloudLayers.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +
CoverageBase (ft)Tops (ft)
diff --git a/webgui/topics/Environment/Weather/CloudsLayers.js b/webgui/topics/Environment/Weather/CloudsLayers.js new file mode 100644 index 000000000..e0cb91c1c --- /dev/null +++ b/webgui/topics/Environment/Weather/CloudsLayers.js @@ -0,0 +1,74 @@ +define([ + 'jquery', 'knockout', 'text!./CloudLayers.html', 'kojqui/selectmenu' +], function(jquery, ko, htmlString) { + + function ViewModel(params) { + var self = this; + + function CloudLayer() { + var self = this; + self.index = 0; + self.base = ko.observable(0); + self.coverage = [ + { + id : 4, + text : 'clear' + }, { + id : 3, + text : 'few' + }, { + id : 2, + text : 'scattered' + }, { + id : 1, + text : 'broken' + }, { + id : 0, + text : 'overcast' + } + ]; + self.thickness = ko.observable(0); + self.coverageId = ko.observable(0); + self.tops = ko.pureComputed(function() { + return self.base() + self.thickness(); + }); + } + + self.cloudLayers = ko.observableArray([]); + + jquery.get('/json/environment/clouds?d=2', null, function(data) { + + var assemble = function(data) { + + var PropertyMap = { + "index" : "index", + "elevation-ft" : "base", + "coverage-type" : "coverageId", + "thickness-ft" : "thickness", + }; + + var cloudLayers = []; + data.children.forEach(function(prop) { + if (prop.name === 'layer') { + var layer = new CloudLayer(); + cloudLayers.push(ko.utils.knockprops.propsToObject(prop, PropertyMap, layer)); + } + }); + + return cloudLayers.reverse(); + } + + self.cloudLayers(assemble(data)); + }); + + } + + ViewModel.prototype.dispose = function() { + } + + // Return component definition + return { + viewModel : ViewModel, + template : htmlString + }; +}); diff --git a/webgui/topics/Environment/Weather/LayerData.js b/webgui/topics/Environment/Weather/LayerData.js new file mode 100644 index 000000000..4bd3f9616 --- /dev/null +++ b/webgui/topics/Environment/Weather/LayerData.js @@ -0,0 +1,43 @@ +define([ + 'knockout', +], function(ko) { + + function LayerData() { + var self = this; + self.index = 0; + self.altitude = ko.observable(0); + self.windDir = ko.observable(0); + self.windSpeed = ko.observable(0); + self.visibility = ko.observable(0); + self.temperature = ko.observable(0); + self.dewpoint = ko.observable(0); + self.turbulence = [ + { + id : 0, + text : 'none' + }, { + id : 1, + text : 'light' + }, { + id : 2, + text : 'moderate' + }, { + id : 3, + text : 'severe' + } + ]; + self.turbulenceValue = ko.observable(0); + } + + LayerData.prototype.PropertyMap = { + "index": "index", + "elevation-ft": "altitude", + "wind-from-heading-deg": "windDir", + "wind-speed-kt": "windSpeed", + "visibility-m": "visibility", + "temperature-degc": "temperature", + "dewpoint-degc": "dewpoint", + }; + + return LayerData; +}); diff --git a/webgui/topics/Environment/Weather/METAR.html b/webgui/topics/Environment/Weather/METAR.html new file mode 100644 index 000000000..091f0270a --- /dev/null +++ b/webgui/topics/Environment/Weather/METAR.html @@ -0,0 +1,9 @@ +
+

+

+
+
+ METAR: + +

+
\ No newline at end of file diff --git a/webgui/topics/Environment/Weather/METAR.js b/webgui/topics/Environment/Weather/METAR.js new file mode 100644 index 000000000..4d2fd1cb4 --- /dev/null +++ b/webgui/topics/Environment/Weather/METAR.js @@ -0,0 +1,68 @@ +define([ + 'jquery', 'knockout', 'text!./METAR.html', 'jquery-ui/accordion', 'kojqui/button' +], function(jquery, ko, htmlString) { + + function WeatherScenarioVM() { + var self = this; + + self.index = 0; + self.name = "unnamed"; + self.metar = ko.observable("NIL"); + self.description = "NIL"; + + } + + var WeatherScenarioMapping = { + "index" : "index", + "description" : "description", + "name" : "name", + "metar" : "metar" + } + + function ViewModel(params) { + var self = this; + + self.scenarios = ko.observableArray([]); + self.selectScenario = function(foo) { + console.log(foo); + } + + jquery.get('/json/environment/weather-scenarios?d=2', null, function(data) { + + var assemble = function(data) { + var scenarios = []; + data.children.forEach(function(prop) { + if (prop.name === 'scenario') { + var scenario = new WeatherScenarioVM(); + scenarios.push(ko.utils.knockprops.propsToObject(prop, WeatherScenarioMapping, scenario)); + + // listen to the metar property for the live data scenario + if (scenario.name == "Live data") { + scenario.metar = ko.observable().extend({ + fgprop : 'metar' + }); + } + } + }); + return scenarios; + } + + self.scenarios(assemble(data)); + jquery("#weather-scenarios").accordion({ + collapsible : true, + heightStyle : "content", + active : false, + }); + }); + + } + + // ViewModel.prototype.dispose = function() { + // } + + // Return component definition + return { + viewModel : ViewModel, + template : htmlString + }; +});