2015-01-25 12:02:20 +00:00
|
|
|
define([
|
2015-03-23 16:43:46 +00:00
|
|
|
'knockout', 'text!./Map.html', './Map/NavdbLayer', './Map/AILayer', './Map/RouteLayer'
|
2015-03-05 18:23:35 +00:00
|
|
|
], function(ko, htmlString, NavdbLayer ) {
|
2015-01-25 12:02:20 +00:00
|
|
|
|
2015-03-10 20:48:11 +00:00
|
|
|
function StoredSettings(key, settings, session ) {
|
|
|
|
this.key = key;
|
|
|
|
this.settings = settings;
|
|
|
|
if( session ) this.session = true;
|
|
|
|
else this.session = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
StoredSettings.prototype.save = function() {
|
|
|
|
if(typeof(Storage) === "undefined") {
|
|
|
|
console.log("Storage not supported :-(");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var storage = this.session ? sessionStorage : localStorage;
|
|
|
|
|
|
|
|
for( var setting in this.settings ) {
|
|
|
|
var settingKey = this.key + "_" + setting;
|
|
|
|
if( null == this.settings[setting] ) {
|
|
|
|
storage.removeItem(settingKey);
|
|
|
|
} else {
|
|
|
|
var t = JSON.stringify(this.settings[setting]);
|
|
|
|
storage.setItem(settingKey,JSON.stringify(this.settings[setting]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StoredSettings.prototype.load = function() {
|
|
|
|
if(typeof(Storage) === "undefined") {
|
|
|
|
console.log("Storage not supported :-(");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var storage = this.session ? sessionStorage : localStorage;
|
|
|
|
|
|
|
|
for( var setting in this.settings ) {
|
|
|
|
var settingKey = this.key + "_" + setting;
|
|
|
|
var storedSetting = storage.getItem(settingKey);
|
|
|
|
if( storedSetting != null ) {
|
|
|
|
this.settings[setting] = JSON.parse(storedSetting);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-25 12:02:20 +00:00
|
|
|
function ViewModel(params) {
|
|
|
|
var self = this;
|
2015-02-25 15:44:47 +00:00
|
|
|
|
2015-03-10 20:48:11 +00:00
|
|
|
this.storedSettings = new StoredSettings("flightgear_map", {
|
|
|
|
selectedBase: null,
|
|
|
|
selectedOverlays: [],
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
this.storedSettings.load();
|
|
|
|
self.selectedOverlays = this.storedSettings.settings.selectedOverlays;
|
|
|
|
|
2015-02-25 20:42:46 +00:00
|
|
|
var trackLayer = new L.GeoJSON(null, {});
|
2015-03-03 16:13:52 +00:00
|
|
|
|
|
|
|
trackLayer.maxTrackPoints = 1000;
|
|
|
|
|
|
|
|
trackLayer.track = {
|
|
|
|
"type" : "Feature",
|
|
|
|
"geometry" : {
|
|
|
|
"type" : "LineString",
|
|
|
|
"coordinates" : []
|
|
|
|
},
|
|
|
|
"properties" : {
|
|
|
|
"type" : "FlightHistory",
|
|
|
|
"last" : 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 20:42:46 +00:00
|
|
|
trackLayer.update = function(id) {
|
|
|
|
var self = this;
|
|
|
|
if (id != self.updateId)
|
|
|
|
return;
|
|
|
|
|
2015-03-03 16:13:52 +00:00
|
|
|
var url = "/flighthistory/track.json?count=" + self.maxTrackPoints + "&last=" + trackLayer.track.properties.last;
|
2015-02-25 20:42:46 +00:00
|
|
|
|
|
|
|
var jqxhr = $.get(url).done(function(data) {
|
|
|
|
self.clearLayers();
|
2015-03-03 16:13:52 +00:00
|
|
|
Array.prototype.push.apply(trackLayer.track.geometry.coordinates, data.geometry.coordinates);
|
|
|
|
if (data.properties) {
|
|
|
|
trackLayer.track.properties.last = data.properties.last || 0;
|
|
|
|
}
|
|
|
|
self.addData(trackLayer.track);
|
|
|
|
|
|
|
|
// update fast until we have all points
|
|
|
|
var updateDelay = data.geometry.coordinates.length < self.maxTrackPoints ? 120000 : 200;
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
self.update(id)
|
|
|
|
}, updateDelay);
|
|
|
|
|
2015-02-25 20:42:46 +00:00
|
|
|
}).fail(function() {
|
|
|
|
var r = confirm("Error loading flight history. Retry?");
|
|
|
|
if (!r)
|
|
|
|
self.updateId++;
|
|
|
|
}).always(function() {
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
trackLayer.updateId = 0;
|
|
|
|
trackLayer.start = function() {
|
|
|
|
this.update(++this.updateId);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
trackLayer.stop = function() {
|
|
|
|
++this.updateId;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
trackLayer.onAdd = function(map) {
|
|
|
|
this.start();
|
|
|
|
return L.GeoJSON.prototype.onAdd.call(this, map);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
trackLayer.onRemove = function(map) {
|
|
|
|
this.stop();
|
|
|
|
return L.GeoJSON.prototype.onRemove.call(this, map);
|
|
|
|
}
|
|
|
|
|
2015-03-14 17:56:13 +00:00
|
|
|
var NavDBLayerName = "Navigation Data",
|
|
|
|
TrackLayerName = "Flight History",
|
|
|
|
AILayerName = "Other Traffic";
|
|
|
|
|
|
|
|
|
2015-02-25 15:44:47 +00:00
|
|
|
self.overlays = {
|
2015-03-11 21:37:48 +00:00
|
|
|
"Flight History" : trackLayer,
|
2015-03-23 16:43:46 +00:00
|
|
|
"Route Manager" : L.routeLayer(),
|
2015-03-11 21:37:48 +00:00
|
|
|
"Navigation Data": L.navdbLayer(),
|
|
|
|
"Other Traffic": L.aiLayer(),
|
2015-03-05 18:23:35 +00:00
|
|
|
|
2022-08-01 11:05:59 +00:00
|
|
|
"OpenFlightMaps (AIRAC 2207)": new L.TileLayer("https://nwy-tiles-api.prod.newaydata.com/tiles/{z}/{x}/{y}.png?path=2207/aero/latest", {
|
2022-07-25 08:51:38 +00:00
|
|
|
maxZoom: 13,
|
|
|
|
minZoom: 7,
|
|
|
|
attribution: '<a target="_blank" href="http://openflightmaps.org">© open flightmaps association</a>'
|
|
|
|
}),
|
|
|
|
|
2015-10-27 21:11:32 +00:00
|
|
|
"OpenAIP": new L.TileLayer("http://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.png", {
|
|
|
|
maxZoom: 14,
|
|
|
|
minZoom: 4,
|
|
|
|
tms: true,
|
|
|
|
detectRetina: true,
|
|
|
|
subdomains: '12',
|
|
|
|
format: 'image/png',
|
|
|
|
transparent: true
|
|
|
|
}),
|
|
|
|
|
2018-01-30 10:21:02 +00:00
|
|
|
"VFRMap.com Sectionals (US)" : new L.TileLayer('http://vfrmap.com/20180104/tiles/vfrc/{z}/{y}/{x}.jpg', {
|
2015-02-25 15:44:47 +00:00
|
|
|
maxZoom : 12,
|
|
|
|
minZoom : 3,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://vfrmap.com">VFRMap.com</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
tms : true,
|
|
|
|
opacity : 0.5,
|
|
|
|
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
|
|
|
|
}),
|
|
|
|
|
2018-01-30 10:21:02 +00:00
|
|
|
"VFRMap.com - Low IFR (US)" : new L.TileLayer('http://vfrmap.com/20180104/tiles/ifrlc/{z}/{y}/{x}.jpg', {
|
2015-02-25 15:44:47 +00:00
|
|
|
maxZoom : 12,
|
|
|
|
minZoom : 5,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://vfrmap.com">VFRMap.com</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
tms : true,
|
|
|
|
opacity : 0.5,
|
|
|
|
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
|
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"Germany VFR" : new L.TileLayer(
|
2015-10-11 12:45:13 +00:00
|
|
|
'https://secais.dfs.de/static-maps/ICAO500-2015-EUR-Reprojected_07/tiles/{z}/{x}/{y}.png', {
|
2015-02-25 15:44:47 +00:00
|
|
|
minZoom : 5,
|
|
|
|
maxZoom : 15,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://www.dfs.de">DFS</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
|
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"Germany Lower Airspace" : new L.TileLayer('https://secais.dfs.de/static-maps/lower_20131114/tiles/{z}/{x}/{y}.png',
|
2015-02-25 15:44:47 +00:00
|
|
|
{
|
|
|
|
minZoom : 5,
|
|
|
|
maxZoom : 15,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://www.dfs.de">DFS</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
|
|
|
|
}),
|
|
|
|
|
|
|
|
"France VFR" : new L.TileLayer('http://carte.f-aero.fr/oaci/{z}/{x}/{y}.png', {
|
|
|
|
minZoom : 5,
|
|
|
|
maxZoom : 15,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
|
|
|
}),
|
|
|
|
|
|
|
|
"France VAC Landing" : new L.TileLayer('http://carte.f-aero.fr/vac-atterrissage/{z}/{x}/{y}.png', {
|
|
|
|
minZoom : 5,
|
|
|
|
maxZoom : 15,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
|
|
|
}),
|
|
|
|
|
|
|
|
"France VAC Approach" : new L.TileLayer('http://carte.f-aero.fr/vac-approche/{z}/{x}/{y}.png', {
|
|
|
|
minZoom : 5,
|
|
|
|
maxZoom : 15,
|
2015-02-25 20:42:46 +00:00
|
|
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"OpenWeatherMap - Clouds" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/clouds/{z}/{x}/{y}.png', {
|
2015-02-25 20:42:46 +00:00
|
|
|
maxZoom : 14,
|
|
|
|
minZoom : 0,
|
|
|
|
subdomains : '12',
|
|
|
|
format : 'image/png',
|
|
|
|
transparent : true,
|
|
|
|
opacity : 0.5,
|
|
|
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"OpenWeatherMap - Precipitation" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/precipitation/{z}/{x}/{y}.png', {
|
2015-02-25 15:44:47 +00:00
|
|
|
maxZoom : 14,
|
|
|
|
minZoom : 0,
|
|
|
|
subdomains : '12',
|
|
|
|
format : 'image/png',
|
|
|
|
transparent : true,
|
2015-02-25 20:42:46 +00:00
|
|
|
opacity : 0.5,
|
|
|
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"OpenWeatherMap - Isobares" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/pressure_cntr/{z}/{x}/{y}.png', {
|
2015-02-25 15:44:47 +00:00
|
|
|
maxZoom : 7,
|
|
|
|
minZoom : 0,
|
|
|
|
subdomains : '12',
|
|
|
|
format : 'image/png',
|
|
|
|
transparent : true,
|
2015-02-25 20:42:46 +00:00
|
|
|
opacity : 0.5,
|
|
|
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
|
|
|
}),
|
|
|
|
|
2015-03-04 11:16:17 +00:00
|
|
|
"OpenWeatherMap - Wind" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/wind/{z}/{x}/{y}.png', {
|
2015-02-25 20:42:46 +00:00
|
|
|
maxZoom : 7,
|
|
|
|
minZoom : 0,
|
|
|
|
subdomains : '12',
|
|
|
|
format : 'image/png',
|
|
|
|
transparent : true,
|
|
|
|
opacity : 0.5,
|
|
|
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
2015-02-25 15:44:47 +00:00
|
|
|
}),
|
|
|
|
}
|
2015-03-10 20:48:11 +00:00
|
|
|
|
2015-03-09 12:42:07 +00:00
|
|
|
self.mapResize = function(a,b) {
|
2015-03-14 17:56:13 +00:00
|
|
|
self.overlays[NavDBLayerName].invalidate();
|
2015-03-09 12:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.mapZoomend = function() {
|
2015-03-14 17:56:13 +00:00
|
|
|
self.overlays[NavDBLayerName].invalidate();
|
2015-03-09 12:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.mapMoveend = function() {
|
2015-03-14 17:56:13 +00:00
|
|
|
self.overlays[NavDBLayerName].invalidate();
|
2015-03-10 20:48:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.mapUnload = function(evt) {
|
2015-03-14 17:56:13 +00:00
|
|
|
var map = evt.target,
|
|
|
|
settings = self.storedSettings.settings;
|
2015-03-10 20:48:11 +00:00
|
|
|
settings.selectedOverlays.length = 0;
|
|
|
|
for( var layerName in self.overlays ) {
|
|
|
|
var layer = self.overlays[layerName];
|
2015-03-14 17:56:13 +00:00
|
|
|
if( layer.stop && typeof(layer.stop === 'function' )) {
|
|
|
|
layer.stop();
|
|
|
|
}
|
2015-03-10 20:48:11 +00:00
|
|
|
if( map.hasLayer(layer) ) {
|
|
|
|
settings.selectedOverlays.push(layerName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.storedSettings.save();
|
|
|
|
}
|
2015-01-25 12:02:20 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return component definition
|
|
|
|
return {
|
|
|
|
viewModel : ViewModel,
|
|
|
|
template : htmlString
|
|
|
|
};
|
|
|
|
});
|