define( [ 'knockout', 'jquery', 'leaflet', 'text!./map.html' ], function(ko, jquery, leaflet, htmlString) { function ViewModel(params, componentInfo) { var self = this; self.element = componentInfo.element; self.followAircraft = ko.observable(true); self.toggleFollowAircraft = function(a) { self.followAircraft(!self.followAircraft()); } self.altitude = ko.observable(0).extend({ fgprop : 'altitude' }); self.tas = ko.observable(0).extend({ fgprop : 'groundspeed' }); self.heading = ko.observable(0).extend({ fgprop : 'heading' }); if (params && params.css) { for ( var p in params.css) { $(self.element).css(p, params.css[p]); } } if ($(self.element).height() < 1) { $(self.element).css("min-height", $(self.element).width()); } var MapOptions = { attributionControl : false, dragging: false, }; if (params && params.map) { for ( var p in params.map) { MapOptions[p] = params.map[p]; } MapOptions = params.map; } self.map = leaflet.map(self.element, MapOptions).setView([ 53.5, 10.0 ], MapOptions.zoom || 13); var baseLayers = { "OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom : 18, attribution : 'Map data © OpenStreetMap contributors' }) } self.map.addLayer(baseLayers["OpenStreetMaps"]); if (params && params.hasFollowAircraft ) { self.map.on('dragstart', function(e) { self.followAircraft(false); }); var followAircraftControl = L.control(); followAircraftControl.onAdd = function(map) { this._div = L.DomUtil.create('div', 'followAircraft'); this._div.innerHTML = ''; return this._div; } followAircraftControl.addTo(self.map); } if (params && params.overlays) { L.control.layers(baseLayers, params.overlays).addTo(self.map); } L.RotatedMarker = L.Marker.extend({ options : { angle : 0 }, _setPos : function(pos) { L.Marker.prototype._setPos.call(this, pos); this._icon.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)'; } }); L.AircraftMarker = L.RotatedMarker .extend({ options : { angle : 0, clickable : false, keyboard : false, icon : L .divIcon({ iconSize : [ 60, 60 ], iconAnchor : [ 30, 30 ], className : 'aircraft-marker-icon', html : '', }), zIndexOffset : 10000, updateInterval : 100, }, initialize : function(latlng, options) { L.RotatedMarker.prototype.initialize(latlng, options); L.Util.setOptions(this, options); }, onAdd : function(map) { L.RotatedMarker.prototype.onAdd.call(this, map); this.popup = L.popup({ autoPan : false, keepInView : false, closeButton : false, className : 'aircraft-marker-popup', closeOnClick : false, maxWidth : 200, minWidth : 120, offset : [ 30, 30 ], }, this); this.popup .setContent('