diff --git a/htdocs/lib/Map.js b/htdocs/lib/Map.js
new file mode 100644
index 00000000..22b96efd
--- /dev/null
+++ b/htdocs/lib/Map.js
@@ -0,0 +1,197 @@
+//
+// Map Manager handles web socket connection and traffic processing
+//
+
+function MapManager() {
+ var self = this;
+
+ // Determine web socket URL
+ var protocol = window.location.protocol.match(/https/) ? 'wss' : 'ws';
+ var href = window.location.href.replace(/\/[^\/]*$/,'');
+ href = protocol + '://' + href.split('://')[1];
+ this.ws_url = href + (href.endsWith('/')? '':'/') + 'ws/';
+
+ // Reset everything for now
+ this.reconnect_timeout = false;
+ this.config = {};
+
+ // Markers management (features, APRS, AIS, HFDL, etc)
+ this.mman = new MarkerManager();
+
+ // Locators management (FT8, FT4, WSPR, etc)
+ this.lman = new LocatorManager();
+
+ // Clock display
+ this.clock = new Clock($("#openwebrx-clock-utc"));
+
+ // Toggle color modes on click
+ $(function() {
+ $('#openwebrx-map-colormode').on('change', function() {
+ self.lman.setColorMode(map, $(this).val());
+ });
+ });
+
+ // Toggle legend box on/off when clicking the clock
+ $(function() {
+ $('#openwebrx-clock-utc').on('click', function() {
+ var el = document.getElementById('openwebrx-map-selectors');
+ if (el) {
+ el.style.display = el.style.display === 'none'?
+ 'block' : 'none';
+ }
+ });
+ });
+
+ // Fade out / remove positions after time
+ setInterval(function() {
+ self.lman.ageAll();
+ self.mman.ageAll();
+ }, 1000);
+
+ // Connect web socket
+ this.connect();
+}
+
+//
+// Process a message received over web socket
+//
+MapManager.prototype.process = function(e) {
+ if (typeof e.data != 'string') {
+ console.error("unsupported binary data on websocket; ignoring");
+ return
+ }
+
+ if (e.data.substr(0, 16) == "CLIENT DE SERVER") {
+ return
+ }
+
+ try {
+ var json = JSON.parse(e.data);
+ switch (json.type) {
+ case "update":
+ this.processUpdates(json.value);
+ break;
+
+ case 'receiver_details':
+ $('.webrx-top-container').header().setDetails(json.value);
+ break;
+
+ case "config":
+ Object.assign(this.config, json.value);
+ if ('receiver_gps' in this.config) {
+ // Passing API key even if this particular map
+ // engine does not need it (Google Maps do)
+ this.initializeMap(
+ this.config.receiver_gps,
+ this.config.google_maps_api_key
+ );
+ }
+ if ('receiver_name' in this.config) {
+ this.setReceiverName(this.config.receiver_name);
+ }
+ if ('map_position_retention_time' in this.config) {
+ retention_time = this.config.map_position_retention_time * 1000;
+ }
+ if ('callsign_url' in this.config) {
+ callsign_url = this.config.callsign_url;
+ }
+ if ('vessel_url' in this.config) {
+ vessel_url = this.config.vessel_url;
+ }
+ if ('flight_url' in this.config) {
+ flight_url = this.config.flight_url;
+ }
+ break;
+
+ default:
+ console.warn('received message of unknown type: ' + json.type);
+ }
+ } catch (e) {
+ // Don't lose exception
+ console.error(e);
+ }
+};
+
+//
+// Connect web socket
+//
+MapManager.prototype.connect = function() {
+ var ws = new WebSocket(this.ws_url);
+ var self = this;
+
+ // When socket opens...
+ ws.onopen = function() {
+ ws.send("SERVER DE CLIENT client=map.js type=map");
+ self.reconnect_timeout = false
+ };
+
+ // When socket closes...
+ ws.onclose = function() {
+ // Clear map
+ self.removeReceiver();
+ self.mman.clear();
+ self.lman.clear();
+
+ if (self.reconnect_timeout) {
+ // Max value: roundabout 8 and a half minutes
+ self.reconnect_timeout = Math.min(self.reconnect_timeout * 2, 512000);
+ } else {
+ // Initial value: 1s
+ self.reconnect_timeout = 1000;
+ }
+
+ // Try reconnecting after timeout
+ setTimeout(self.connect, self.reconnect_timeout);
+ };
+
+ // When socket receives a message...
+ ws.onmessage = function(e) {
+ self.process(e);
+ }
+
+ // When socket gets an error...
+ //ws.onerror = function() {
+ // console.info("websocket error");
+ //};
+
+ // http://stackoverflow.com/questions/4812686/closing-websocket-correctly-html5-javascript
+ window.onbeforeunload = function() {
+ ws.onclose = function () {};
+ ws.close();
+ };
+};
+
+//
+// Set up legend filter toggles inside given HTML element.
+//
+MapManager.prototype.setupLegendFilters = function($legend) {
+ var self = this;
+
+ $content = $legend.find('.content');
+ $content.on('click', 'li', function() {
+ var $el = $(this);
+ $lis = $content.find('li');
+ if ($lis.hasClass('disabled') && !$el.hasClass('disabled')) {
+ $lis.removeClass('disabled');
+ self.lman.setFilter(map);
+ } else {
+ $el.removeClass('disabled');
+ $lis.filter(function() {
+ return this != $el[0]
+ }).addClass('disabled');
+ self.lman.setFilter(map, $el.data('selector'));
+ }
+ });
+
+ $content1 = $legend.find('.features');
+ $content1.on('click', 'li', function() {
+ var $el = $(this);
+ var onoff = $el.hasClass('disabled');
+ if (onoff) {
+ $el.removeClass('disabled');
+ } else {
+ $el.addClass('disabled');
+ }
+ self.mman.toggle(map, $el.data('selector'), onoff);
+ });
+};
diff --git a/htdocs/lib/LocatorManager.js b/htdocs/lib/MapLocators.js
similarity index 85%
rename from htdocs/lib/LocatorManager.js
rename to htdocs/lib/MapLocators.js
index 3e2cf799..9e8f7523 100644
--- a/htdocs/lib/LocatorManager.js
+++ b/htdocs/lib/MapLocators.js
@@ -205,44 +205,3 @@ Locator.prototype.age = function(age) {
return false;
}
};
-
-//
-// GoogleMaps-specific Map Locator (derived from generic locator)
-//
-
-function GLocator() {
- this.rect = new google.maps.Rectangle();
- this.rect.setOptions({
- strokeWeight : 2,
- strokeColor : "#FFFFFF",
- fillColor : "#FFFFFF"
- });
-}
-
-GLocator.prototype = new Locator();
-
-GLocator.prototype.setMap = function(map) {
- this.rect.setMap(map);
-};
-
-GLocator.prototype.setCenter = function(lat, lon) {
- this.center = new google.maps.LatLng({lat: lat, lng: lon});
-
- this.rect.setOptions({ bounds : {
- north : lat - 0.5,
- south : lat + 0.5,
- west : lon - 1.0,
- east : lon + 1.0
- }});
-}
-
-GLocator.prototype.setColor = function(color) {
- this.rect.setOptions({ strokeColor: color, fillColor: color });
-};
-
-GLocator.prototype.setOpacity = function(opacity) {
- this.rect.setOptions({
- strokeOpacity : LocatorManager.strokeOpacity * opacity,
- fillOpacity : LocatorManager.fillOpacity * opacity
- });
-};
diff --git a/htdocs/lib/MarkerManager.js b/htdocs/lib/MapMarkers.js
similarity index 93%
rename from htdocs/lib/MarkerManager.js
rename to htdocs/lib/MapMarkers.js
index 0f41aa4f..e51c279a 100644
--- a/htdocs/lib/MarkerManager.js
+++ b/htdocs/lib/MapMarkers.js
@@ -564,53 +564,3 @@ AprsMarker.prototype.getInfoHTML = function(name, receiverMarker = null) {
+ ( this.band ? ' on ' + this.band : '' ) + ''
+ commentString + weatherString + detailsString + hopsString;
};
-
-//
-// GoogleMaps-Specific Markers (derived from generic markers)
-//
-
-function GMarker() {}
-GMarker.prototype = new google.maps.OverlayView();
-
-GMarker.prototype.setMarkerOptions = function(options) {
- this.setOptions(options);
- this.draw();
-};
-
-GMarker.prototype.onAdd = function() {
- // Create HTML elements representing the mark
- var div = this.create();
-
- var self = this;
- google.maps.event.addDomListener(div, "click", function(event) {
- event.stopPropagation();
- google.maps.event.trigger(self, "click", event);
- });
-
- var panes = this.getPanes();
- panes.overlayImage.appendChild(div);
-};
-
-GMarker.prototype.getAnchorPoint = function() {
- var offset = this.getAnchorOffset();
- return new google.maps.Point(offset[0], offset[1]);
-};
-
-GMarker.prototype.setMarkerOpacity = function(opacity) {
- this.setOptions({ opacity: opacity });
-};
-
-GMarker.prototype.setMarkerPosition = function(title, lat, lon) {
- this.setOptions({
- title : title,
- position : new google.maps.LatLng(lat, lon)
- });
-};
-
-// GoogleMaps-Specific FeatureMarker
-function GFeatureMarker() { $.extend(this, new FeatureMarker()); }
-GFeatureMarker.prototype = new GMarker();
-
-// GoogleMaps-Specific AprsMarker
-function GAprsMarker() { $.extend(this, new AprsMarker()); }
-GAprsMarker.prototype = new GMarker();
diff --git a/htdocs/map.js b/htdocs/map.js
index 73ec14fc..08e8ef31 100644
--- a/htdocs/map.js
+++ b/htdocs/map.js
@@ -6,406 +6,273 @@ var flight_url = null;
// reasonable default; will be overriden by server
var retention_time = 2 * 60 * 60 * 1000;
-// Function to toggle legend box on/off
-function toggleElement(el_name) {
- var el = document.getElementById(el_name);
- if (el) el.style.display = el.style.display === 'none'? 'block' : 'none';
+// Our Google Map
+var map = null;
+
+// Receiver location marker
+var receiverMarker = null;
+
+// Information bubble window
+var infoWindow = null;
+
+// Updates are queued here
+var updateQueue = [];
+
+// Web socket connection management, message processing
+var mapManager = new MapManager();
+
+var query = window.location.search.replace(/^\?/, '').split('&').map(function(v){
+ var s = v.split('=');
+ var r = {};
+ r[s[0]] = s.slice(1).join('=');
+ return r;
+}).reduce(function(a, b){
+ return a.assign(b);
+});
+
+var expectedCallsign = query.callsign? decodeURIComponent(query.callsign) : null;
+var expectedLocator = query.locator? query.locator : null;
+
+// Get information bubble window
+function getInfoWindow() {
+ if (!infoWindow) {
+ infoWindow = new google.maps.InfoWindow();
+ google.maps.event.addListener(infoWindow, 'closeclick', function() {
+ delete infoWindow.locator;
+ delete infoWindow.callsign;
+ });
+ }
+ delete infoWindow.locator;
+ delete infoWindow.callsign;
+ return infoWindow;
+};
+
+// Show information bubble for a locator
+function showLocatorInfoWindow(locator, pos) {
+ var iw = getInfoWindow();
+
+ iw.locator = locator;
+ iw.setContent(mapManager.lman.getInfoHTML(locator, pos, receiverMarker));
+ iw.setPosition(pos);
+ iw.open(map);
+};
+
+// Show information bubble for a marker
+function showMarkerInfoWindow(name, pos) {
+ var marker = mapManager.mman.find(name);
+ var iw = getInfoWindow();
+
+ iw.callsign = name;
+ iw.setContent(marker.getInfoHTML(name, receiverMarker));
+ iw.open(map, marker);
+};
+
+// Show information bubble for the receiver location
+function showReceiverInfoWindow(marker) {
+ var iw = getInfoWindow()
+ iw.setContent(
+ '
' + marker.config['receiver_name'] + '
' +
+ 'Receiver Location
'
+ );
+ iw.open(map, marker);
+};
+
+//
+// GOOGLE-SPECIFIC MAP MANAGER METHODS
+//
+
+MapManager.prototype.setReceiverName = function(name) {
+ if (this.receiverMarker) this.receiverMarker.setOptions({ title: name });
}
-$(function(){
- var query = window.location.search.replace(/^\?/, '').split('&').map(function(v){
- var s = v.split('=');
- var r = {};
- r[s[0]] = s.slice(1).join('=');
- return r;
- }).reduce(function(a, b){
- return a.assign(b);
- });
+MapManager.prototype.removeReceiver = function() {
+ if (this.receiverMarker) this.receiverMarker.setMap();
+}
- var expectedCallsign;
- if (query.callsign) expectedCallsign = decodeURIComponent(query.callsign);
- var expectedLocator;
- if (query.locator) expectedLocator = query.locator;
+MapManager.prototype.initializeMap = function(receiver_gps, api_key) {
+ var receiverPos = { lat: receiver_gps.lat, lng: receiver_gps.lon };
- var protocol = window.location.protocol.match(/https/) ? 'wss' : 'ws';
-
- var href = window.location.href;
- var index = href.lastIndexOf('/');
- if (index > 0) {
- href = href.substr(0, index + 1);
- }
- href = href.split("://")[1];
- href = protocol + "://" + href;
- if (!href.endsWith('/')) {
- href += '/';
- }
- var ws_url = href + "ws/";
-
- var map;
- var receiverMarker;
- var updateQueue = [];
-
- // marker and locator managers
- var markmanager = null;
- var locmanager = null;
-
- // clock
- var clock = new Clock($("#openwebrx-clock-utc"));
-
- $(function() {
- $('#openwebrx-map-colormode').on('change', function() {
- locmanager.setColorMode(map, $(this).val());
+ if (map) {
+ this.receiverMarker.setOptions({
+ map : map,
+ position : receiverPos,
+ config : this.config
});
- });
+ } else {
+ var self = this;
- var processUpdates = function(updates) {
- if (!markmanager || !locmanager) {
- updateQueue = updateQueue.concat(updates);
- return;
- }
- updates.forEach(function(update) {
- switch (update.location.type) {
- case 'latlon':
- var marker = markmanager.find(update.callsign);
- var markerClass = google.maps.Marker;
- var aprsOptions = {}
-
- if (update.location.symbol) {
- markerClass = GAprsMarker;
- aprsOptions.symbol = update.location.symbol;
- aprsOptions.course = update.location.course;
- aprsOptions.speed = update.location.speed;
- }
-
- // If new item, create a new marker for it
- if (!marker) {
- marker = new markerClass();
- markmanager.addType(update.mode);
- markmanager.add(update.callsign, marker);
- marker.addListener('click', function() {
- showMarkerInfoWindow(update.callsign, marker.pos);
- });
- }
-
- // Update marker attributes and age
- marker.update(update);
-
- // Assign marker to map
- marker.setMap(markmanager.isEnabled(update.mode)? map : undefined);
-
- // Apply marker options
- marker.setMarkerOptions(aprsOptions);
-
- if (expectedCallsign && expectedCallsign == update.callsign) {
- map.panTo(marker.pos);
- showMarkerInfoWindow(update.callsign, marker.pos);
- expectedCallsign = false;
- }
-
- if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign) {
- showMarkerInfoWindow(infowindow.callsign, marker.pos);
- }
- break;
-
- case 'feature':
- var marker = markmanager.find(update.callsign);
- var options = {}
-
- // If no symbol or color supplied, use defaults by type
- if (update.location.symbol) {
- options.symbol = update.location.symbol;
- } else {
- options.symbol = markmanager.getSymbol(update.mode);
- }
- if (update.location.color) {
- options.color = update.location.color;
- } else {
- options.color = markmanager.getColor(update.mode);
- }
-
- // If new item, create a new marker for it
- if (!marker) {
- marker = new GFeatureMarker();
- markmanager.addType(update.mode);
- markmanager.add(update.callsign, marker);
- marker.addListener('click', function() {
- showMarkerInfoWindow(update.callsign, marker.pos);
- });
- }
-
- // Update marker attributes and age
- marker.update(update);
-
- // Assign marker to map
- marker.setMap(markmanager.isEnabled(update.mode)? map : undefined);
-
- // Apply marker options
- marker.setMarkerOptions(options);
-
- if (expectedCallsign && expectedCallsign == update.callsign) {
- map.panTo(marker.pos);
- showMarkerInfoWindow(update.callsign, marker.pos);
- expectedCallsign = false;
- }
-
- if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign) {
- showMarkerInfoWindow(infowindow.callsign, marker.pos);
- }
- break;
-
- case 'locator':
- var rectangle = locmanager.find(update.callsign);
-
- // If new item, create a new locator for it
- if (!rectangle) {
- rectangle = new GLocator();
- locmanager.add(update.callsign, rectangle);
- rectangle.rect.addListener('click', function() {
- showLocatorInfoWindow(rectangle.locator, rectangle.center);
- });
- }
-
- // Update locator attributes, center, age
- rectangle.update(update);
-
- // Assign locator to map and set its color
- rectangle.setMap(locmanager.filter(rectangle)? map : undefined);
- rectangle.setColor(locmanager.getColor(rectangle));
-
- if (expectedLocator && expectedLocator == update.location.locator) {
- map.panTo(rectangle.center);
- showLocatorInfoWindow(expectedLocator, rectangle.center);
- expectedLocator = false;
- }
-
- if (infowindow && infowindow.locator && infowindow.locator == update.location.locator) {
- showLocatorInfoWindow(infowindow.locator, rectangle.center);
- }
- break;
- }
- });
- };
-
- var clearMap = function(){
- var reset = function(callsign, item) { item.setMap(); };
- receiverMarker.setMap();
- markmanager.clear();
- locmanager.clear();
- };
-
- var reconnect_timeout = false;
-
- var config = {}
-
- var connect = function(){
- var ws = new WebSocket(ws_url);
- ws.onopen = function(){
- ws.send("SERVER DE CLIENT client=map.js type=map");
- reconnect_timeout = false
- };
-
- ws.onmessage = function(e){
- if (typeof e.data != 'string') {
- console.error("unsupported binary data on websocket; ignoring");
- return
- }
- if (e.data.substr(0, 16) == "CLIENT DE SERVER") {
- return
- }
- try {
- var json = JSON.parse(e.data);
- switch (json.type) {
- case "config":
- Object.assign(config, json.value);
- if ('receiver_gps' in config) {
- var receiverPos = {
- lat: config.receiver_gps.lat,
- lng: config.receiver_gps.lon
- };
- if (!map) $.getScript("https://maps.googleapis.com/maps/api/js?key=" + config.google_maps_api_key).done(function(){
- map = new google.maps.Map($('.openwebrx-map')[0], {
- center: receiverPos,
- zoom: 5,
- });
-
- $.getScript("static/lib/nite-overlay.js").done(function(){
- nite.init(map);
- setInterval(function() { nite.refresh() }, 10000); // every 10s
- });
-
- $.getScript('static/lib/MarkerManager.js').done(function(){
- markmanager = new MarkerManager();
- if (locmanager) {
- processUpdates(updateQueue);
- updateQueue = [];
- }
- });
-
- $.getScript('static/lib/LocatorManager.js').done(function(){
- locmanager = new LocatorManager();
- if (markmanager) {
- processUpdates(updateQueue);
- updateQueue = [];
- }
- });
-
- var $legend = $(".openwebrx-map-legend");
- setupLegendFilters($legend);
- map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push($legend[0]);
-
- if (!receiverMarker) {
- receiverMarker = new google.maps.Marker();
- receiverMarker.addListener('click', function() {
- showReceiverInfoWindow(receiverMarker);
- });
- }
- receiverMarker.setOptions({
- map: map,
- position: receiverPos,
- title: config['receiver_name'],
- config: config
- });
-
- }); else {
- receiverMarker.setOptions({
- map: map,
- position: receiverPos,
- config: config
- });
- }
- }
- if ('receiver_name' in config && receiverMarker) {
- receiverMarker.setOptions({
- title: config['receiver_name']
- });
- }
- if ('map_position_retention_time' in config) {
- retention_time = config.map_position_retention_time * 1000;
- }
- if ('callsign_url' in config) {
- callsign_url = config['callsign_url'];
- }
- if ('vessel_url' in config) {
- vessel_url = config['vessel_url'];
- }
- if ('flight_url' in config) {
- flight_url = config['flight_url'];
- }
- break;
- case "update":
- processUpdates(json.value);
- break;
- case 'receiver_details':
- $('.webrx-top-container').header().setDetails(json['value']);
- break;
- default:
- console.warn('received message of unknown type: ' + json['type']);
- }
- } catch (e) {
- // don't lose exception
- console.error(e);
- }
- };
- ws.onclose = function(){
- clearMap();
- if (reconnect_timeout) {
- // max value: roundabout 8 and a half minutes
- reconnect_timeout = Math.min(reconnect_timeout * 2, 512000);
- } else {
- // initial value: 1s
- reconnect_timeout = 1000;
- }
- setTimeout(connect, reconnect_timeout);
- };
-
- window.onbeforeunload = function() { //http://stackoverflow.com/questions/4812686/closing-websocket-correctly-html5-javascript
- ws.onclose = function () {};
- ws.close();
- };
-
- /*
- ws.onerror = function(){
- console.info("websocket error");
- };
- */
- };
-
- connect();
-
- var getInfoWindow = function() {
- if (!infowindow) {
- infowindow = new google.maps.InfoWindow();
- google.maps.event.addListener(infowindow, 'closeclick', function() {
- delete infowindow.locator;
- delete infowindow.callsign;
+ // After Google Maps API loads...
+ $.getScript("https://maps.googleapis.com/maps/api/js?key=" + api_key).done(function() {
+ // Create a map instance
+ map = new google.maps.Map($('.openwebrx-map')[0], {
+ center : receiverPos,
+ zoom : 5,
});
+
+ // Load and initialize day-and-night overlay
+ $.getScript("static/lib/nite-overlay.js").done(function() {
+ nite.init(map);
+ setInterval(function() { nite.refresh() }, 10000); // every 10s
+ });
+
+ // Load and initialize OWRX-specific map item managers
+ $.getScript('static/lib/GoogleMaps.js').done(function() {
+ // Process any accumulated updates
+ self.processUpdates(updateQueue);
+ updateQueue = [];
+ });
+
+ // Create map legend selectors
+ var $legend = $(".openwebrx-map-legend");
+ self.setupLegendFilters($legend);
+ map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push($legend[0]);
+
+ // Create receiver marker
+ if (!receiverMarker) {
+ receiverMarker = new google.maps.Marker();
+ receiverMarker.addListener('click', function() {
+ showReceiverInfoWindow(receiverMarker);
+ });
+ }
+
+ // Set receiver marker position, name, etc.
+ receiverMarker.setOptions({
+ map : map,
+ position : receiverPos,
+ title : self.config['receiver_name'],
+ config : self.config
+ });
+ });
+ }
+};
+
+MapManager.prototype.processUpdates = function(updates) {
+ var self = this;
+
+ if (typeof(GMarker) == 'undefined') {
+ updateQueue = updateQueue.concat(updates);
+ return;
+ }
+
+ updates.forEach(function(update) {
+ switch (update.location.type) {
+ case 'latlon':
+ var marker = self.mman.find(update.callsign);
+ var markerClass = google.maps.Marker;
+ var aprsOptions = {}
+
+ if (update.location.symbol) {
+ markerClass = GAprsMarker;
+ aprsOptions.symbol = update.location.symbol;
+ aprsOptions.course = update.location.course;
+ aprsOptions.speed = update.location.speed;
+ }
+
+ // If new item, create a new marker for it
+ if (!marker) {
+ marker = new markerClass();
+ self.mman.addType(update.mode);
+ self.mman.add(update.callsign, marker);
+ marker.addListener('click', function() {
+ showMarkerInfoWindow(update.callsign, marker.pos);
+ });
+ }
+
+ // Update marker attributes and age
+ marker.update(update);
+
+ // Assign marker to map
+ marker.setMap(self.mman.isEnabled(update.mode)? map : undefined);
+
+ // Apply marker options
+ marker.setMarkerOptions(aprsOptions);
+
+ if (expectedCallsign && expectedCallsign == update.callsign) {
+ map.panTo(marker.pos);
+ showMarkerInfoWindow(update.callsign, marker.pos);
+ expectedCallsign = false;
+ }
+
+ if (infoWindow && infoWindow.callsign && infoWindow.callsign == update.callsign) {
+ showMarkerInfoWindow(infoWindow.callsign, marker.pos);
+ }
+ break;
+
+ case 'feature':
+ var marker = self.mman.find(update.callsign);
+ var options = {}
+
+ // If no symbol or color supplied, use defaults by type
+ if (update.location.symbol) {
+ options.symbol = update.location.symbol;
+ } else {
+ options.symbol = self.mman.getSymbol(update.mode);
+ }
+ if (update.location.color) {
+ options.color = update.location.color;
+ } else {
+ options.color = self.mman.getColor(update.mode);
+ }
+
+ // If new item, create a new marker for it
+ if (!marker) {
+ marker = new GFeatureMarker();
+ self.mman.addType(update.mode);
+ self.mman.add(update.callsign, marker);
+ marker.addListener('click', function() {
+ showMarkerInfoWindow(update.callsign, marker.pos);
+ });
+ }
+
+ // Update marker attributes and age
+ marker.update(update);
+
+ // Assign marker to map
+ marker.setMap(self.mman.isEnabled(update.mode)? map : undefined);
+
+ // Apply marker options
+ marker.setMarkerOptions(options);
+
+ if (expectedCallsign && expectedCallsign == update.callsign) {
+ map.panTo(marker.pos);
+ showMarkerInfoWindow(update.callsign, marker.pos);
+ expectedCallsign = false;
+ }
+
+ if (infoWindow && infoWindow.callsign && infoWindow.callsign == update.callsign) {
+ showMarkerInfoWindow(infoWindow.callsign, marker.pos);
+ }
+ break;
+
+ case 'locator':
+ var rectangle = self.lman.find(update.callsign);
+
+ // If new item, create a new locator for it
+ if (!rectangle) {
+ rectangle = new GLocator();
+ self.lman.add(update.callsign, rectangle);
+ rectangle.rect.addListener('click', function() {
+ showLocatorInfoWindow(rectangle.locator, rectangle.center);
+ });
+ }
+
+ // Update locator attributes, center, age
+ rectangle.update(update);
+
+ // Assign locator to map and set its color
+ rectangle.setMap(self.lman.filter(rectangle)? map : undefined);
+ rectangle.setColor(self.lman.getColor(rectangle));
+
+ if (expectedLocator && expectedLocator == update.location.locator) {
+ map.panTo(rectangle.center);
+ showLocatorInfoWindow(expectedLocator, rectangle.center);
+ expectedLocator = false;
+ }
+
+ if (infoWindow && infoWindow.locator && infoWindow.locator == update.location.locator) {
+ showLocatorInfoWindow(infoWindow.locator, rectangle.center);
+ }
+ break;
}
- delete infowindow.locator;
- delete infowindow.callsign;
- return infowindow;
- }
-
- var infowindow;
- var showLocatorInfoWindow = function(locator, pos) {
- var infowindow = getInfoWindow();
- infowindow.locator = locator;
- infowindow.setContent(locmanager.getInfoHTML(locator, pos, receiverMarker));
- infowindow.setPosition(pos);
- infowindow.open(map);
- };
-
- var showMarkerInfoWindow = function(name, pos) {
- var infowindow = getInfoWindow();
- var marker = markmanager.find(name);
-
- infowindow.callsign = name;
- infowindow.setContent(marker.getInfoHTML(name, receiverMarker));
- infowindow.open(map, marker);
- }
-
- var showReceiverInfoWindow = function(marker) {
- var infowindow = getInfoWindow()
- infowindow.setContent(
- '' + marker.config['receiver_name'] + '
' +
- 'Receiver location
'
- );
- infowindow.open(map, marker);
- }
-
- // Fade out / remove positions after time
- setInterval(function(){
- if (locmanager) locmanager.ageAll();
- if (markmanager) markmanager.ageAll();
- }, 1000);
-
- var setupLegendFilters = function($legend) {
- $content = $legend.find('.content');
- $content.on('click', 'li', function() {
- var $el = $(this);
- $lis = $content.find('li');
- if ($lis.hasClass('disabled') && !$el.hasClass('disabled')) {
- $lis.removeClass('disabled');
- locmanager.setFilter(map);
- } else {
- $el.removeClass('disabled');
- $lis.filter(function() {
- return this != $el[0]
- }).addClass('disabled');
- locmanager.setFilter(map, $el.data('selector'));
- }
- });
-
- $content1 = $legend.find('.features');
- $content1.on('click', 'li', function() {
- var $el = $(this);
- var onoff = $el.hasClass('disabled');
- if (onoff) {
- $el.removeClass('disabled');
- } else {
- $el.addClass('disabled');
- }
- markmanager.toggle(map, $el.data('selector'), onoff);
- });
- }
-
-});
+ });
+};
diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py
index d5d180e3..a11b0540 100644
--- a/owrx/controllers/assets.py
+++ b/owrx/controllers/assets.py
@@ -145,6 +145,9 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController):
"lib/jquery-3.2.1.min.js",
"lib/chroma.min.js",
"lib/Header.js",
+ "lib/MapLocators.js",
+ "lib/MapMarkers.js",
+ "lib/Map.js",
"lib/Clock.js",
"map.js",
],