// // Map Locators Management // LocatorManager.strokeOpacity = 0.8; LocatorManager.fillOpacity = 0.35; LocatorManager.allRectangles = function() { return true; }; function LocatorManager() { // Current rectangles this.rectangles = {}; // Current color allocations this.colorKeys = {}; // The color scale used this.colorScale = chroma.scale(['red', 'blue', 'green']).mode('hsl'); // Current coloring mode this.colorMode = 'byband'; // Current filter this.rectangleFilter = LocatorManager.allRectangles; } LocatorManager.prototype.filter = function(data) { return this.rectangleFilter(data); } LocatorManager.prototype.find = function(id) { return id in this.rectangles? this.rectangles[id] : null; }; LocatorManager.prototype.add = function(id, rectangle) { this.rectangles[id] = rectangle; }; LocatorManager.prototype.ageAll = function() { var now = new Date().getTime(); var data = this.rectangles; $.each(data, function(id, x) { if (!x.age(now - x.lastseen)) delete data[id]; }); }; LocatorManager.prototype.clear = function() { // Remove all rectangles from the map $.each(this.rectangles, function(_, x) { x.setMap(); }); // Delete all rectangles this.rectangles = {}; }; LocatorManager.prototype.setFilter = function(map, filterBy = null) { if (!filterBy) { this.rectangleFilter = LocatorManager.allRectangles; } else { var key = this.colorMode.slice(2); this.rectangleFilter = function(x) { return x[key] === filterBy; }; } var filter = this.rectangleFilter; $.each(this.rectangles, function(_, x) { x.setMap(filter(x) ? map : undefined); }); }; LocatorManager.prototype.reColor = function() { var self = this; $.each(this.rectangles, function(_, x) { x.setColor(self.getColor(x)); }); }; LocatorManager.prototype.updateLegend = function() { if (!this.colorKeys) return; var filter = this.rectangleFilter; var mode = this.colorMode.slice(2); var list = $.map(this.colorKeys, function(value, key) { // Fake rectangle to test if the filter would match var fakeRectangle = Object.fromEntries([[mode, key]]); var disabled = filter(fakeRectangle) ? '' : ' disabled'; return '
  • ' + key + '
  • '; }); $(".openwebrx-map-legend .content").html(''); } LocatorManager.prototype.setColorMode = function(map, newColorMode) { this.colorMode = newColorMode; this.colorKeys = {}; this.setFilter(map); this.reColor(); this.updateLegend(); }; LocatorManager.prototype.getType = function(data) { switch (this.colorMode) { case 'byband': return data.band; case 'bymode': return data.mode; default: return ''; } }; LocatorManager.prototype.getColor = function(data) { var type = this.getType(data); if (!type) return "#ffffff00"; // If adding a new key... if (!this.colorKeys[type]) { var keys = Object.keys(this.colorKeys); // Add a new key keys.push(type); // Sort color keys keys.sort(function(a, b) { var pa = parseFloat(a); var pb = parseFloat(b); if (isNaN(pa) || isNaN(pb)) return a.localeCompare(b); return pa - pb; }); // Recompute colors var colors = this.colorScale.colors(keys.length); this.colorKeys = {}; for(var j=0 ; j' + message + ')'; }).join(""); return '

    Locator: ' + locator + distance + '

    Active Callsigns:
    '; }; // // Generic Map Locator // Derived classes have to implement: // setMap(), setCenter(), setColor(), setOpacity() // function Locator() {} Locator.prototype = new Locator(); Locator.prototype.update = function(update) { this.lastseen = update.lastseen; this.locator = update.location.locator; this.mode = update.mode; this.band = update.band; // Get locator's lat/lon const loc = update.location.locator; const lat = (loc.charCodeAt(1) - 65 - 9) * 10 + Number(loc[3]) + 0.5; const lon = (loc.charCodeAt(0) - 65 - 9) * 20 + Number(loc[2]) * 2 + 1.0; // Implementation-dependent function call this.setCenter(lat, lon); // Age locator this.age(new Date().getTime() - update.lastseen, update.location.ttl); }; Locator.prototype.age = function(age, ttl=retention_time) { if (age <= ttl) { this.setOpacity(Marker.getOpacityScale(age, ttl)); return true; } else { this.setMap(); return false; } };