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 @@
+
+
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 @@
+
+
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 @@
+
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
+ };
+});