openwebrxplus/htdocs/map-google.js

253 lines
8.6 KiB
JavaScript

// Reasonable defaults, will be overriden by server
var retention_time = 2 * 60 * 60 * 1000;
var call_retention_time = 15 * 60;
var max_calls = 5;
// 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(name = null) {
if (!infoWindow) {
infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(infoWindow, 'closeclick', function() {
delete infoWindow.name;
});
}
infoWindow.name = name;
return infoWindow;
};
// Show information bubble for a locator
function showLocatorInfoWindow(locator, pos) {
var iw = getInfoWindow(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(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(
'<h3>' + marker.config['receiver_name'] + '</h3>' +
'<div>Receiver Location</div>'
);
iw.open(map, marker);
};
//
// GOOGLE-SPECIFIC MAP MANAGER METHODS
//
MapManager.prototype.setReceiverName = function(name) {
if (receiverMarker) receiverMarker.setOptions({ title: name });
}
MapManager.prototype.removeReceiver = function() {
if (receiverMarker) receiverMarker.setMap();
}
MapManager.prototype.initializeMap = function(receiver_gps, api_key, weather_key) {
var receiverPos = { lat: receiver_gps.lat, lng: receiver_gps.lon };
if (map) {
receiverMarker.setOptions({
map : map,
position : receiverPos,
config : this.config
});
} else {
var self = this;
// 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) {
// Process caller-callee updates
if ('caller' in update) {
var call = new GCall();
call.create(update, map);
self.cman.add(call);
return;
}
// Process position updates
switch (update.location.type) {
case 'latlon':
var marker = self.mman.find(update.callsign);
// If new item, create a new marker for it
if (!marker) {
switch(update.mode) {
case 'HFDL': case 'VDL2': case 'ADSB': case 'ACARS':
marker = new GAircraftMarker();
break;
case 'APRS': case 'AIS': case 'HDR':
marker = new GAprsMarker();
break;
case 'KiwiSDR': case 'WebSDR': case 'OpenWebRX':
case 'Stations': case 'Repeaters':
marker = new GFeatureMarker();
// If no symbol or color supplied, use defaults by type
if (!update.location.symbol) update.location.symbol = self.mman.getSymbol(update.mode);
if (!update.location.color) update.location.color = self.mman.getColor(update.mode);
break;
default:
marker = new GSimpleMarker();
break;
}
self.mman.add(update.callsign, marker);
marker.addListener('click', function() {
showMarkerInfoWindow(update.callsign, marker.position);
});
}
// Keep track of new marker types as they may change
self.mman.addType(update.mode);
// Update marker attributes and age
marker.update(update);
// Assign marker to map
marker.setMap(self.mman.isEnabled(update.mode)? map : null);
// Apply marker options
if (marker instanceof GFeatureMarker) {
marker.setMarkerOptions({
symbol : update.location.symbol,
color : update.location.color
});
} else if (update.location.symbol) {
marker.setMarkerOptions({
symbol : update.location.symbol,
course : update.location.course,
speed : update.location.speed
});
}
if (expectedCallsign && expectedCallsign === update.callsign) {
map.panTo(marker.position);
showMarkerInfoWindow(update.callsign, marker.position);
expectedCallsign = false;
}
if (infoWindow && infoWindow.name && infoWindow.name === update.callsign) {
showMarkerInfoWindow(update.callsign, marker.position);
}
break;
case 'locator':
var rectangle = self.lman.find(update.location.locator);
// If new item, create a new locator for it
if (!rectangle) {
rectangle = new GLocator();
self.lman.add(update.location.locator, rectangle);
rectangle.rect.addListener('click', function() {
showLocatorInfoWindow(update.location.locator, rectangle.center);
});
}
// Update locator attributes, center, age
self.lman.update(update.location.locator, update, map);
if (expectedLocator && expectedLocator === update.location.locator) {
map.panTo(rectangle.center);
showLocatorInfoWindow(update.location.locator, rectangle.center);
expectedLocator = false;
}
if (infoWindow && infoWindow.locator && infoWindow.locator === update.location.locator) {
showLocatorInfoWindow(update.location.locator, rectangle.center);
}
break;
}
});
};