// Marker.linkify() uses these URLs var callsign_url = null; var vessel_url = null; var flight_url = null; // reasonable default; will be overriden by server var retention_time = 2 * 60 * 60 * 1000; // Our Leaflet Map and layerControl var map = null; var layerControl; // Receiver location marker var receiverMarker = 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; // https://stackoverflow.com/a/46981806/420585 function fetchStyleSheet(url, media = 'screen') { let $dfd = $.Deferred(), finish = () => $dfd.resolve(), $link = $(document.createElement('link')).attr({ media, type: 'text/css', rel: 'stylesheet' }) .on('load', 'error', finish) .appendTo('head'), $img = $(document.createElement('img')) .on('error', finish); // Support browsers that don't fire events on link elements $link[0].href = $img[0].src = url; return $dfd.promise(); } // Show information bubble for a locator function showLocatorInfoWindow(locator, pos) { var p = new posObj(pos); L.popup(pos, { content: mapManager.lman.getInfoHTML(locator, p, receiverMarker) }).openOn(map); }; // Show information bubble for a marker function showMarkerInfoWindow(name, pos) { var marker = mapManager.mman.find(name); L.popup(pos, { content: marker.getInfoHTML(name, receiverMarker) }).openOn(map); }; // // Leaflet-SPECIFIC MAP MANAGER METHODS // MapManager.prototype.setReceiverName = function(name) { if (receiverMarker) receiverMarker.setTitle(name); } MapManager.prototype.removeReceiver = function() { if (receiverMarker) receiverMarker.setMap(); } MapManager.prototype.initializeMap = function(receiver_gps, api_key) { var receiverPos = [ receiver_gps.lat, receiver_gps.lon ]; if (map) { receiverMarker.setLatLng(receiverPos); receiverMarker.setMarkerOptions(this.config); receiverMarker.setMap(map); } else { var self = this; // load Leaflet CSS first fetchStyleSheet('https://unpkg.com/leaflet@1.9.4/dist/leaflet.css').done(function () { // now load Leaflet JS $.getScript('https://unpkg.com/leaflet@1.9.4/dist/leaflet.js').done(function () { // create map map = L.map('openwebrx-map').setView(receiverPos, 5); baseLayer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, noWrap: true, attribution: '© OpenStreetMap' }).addTo(map); // add night overlay $.getScript('https://unpkg.com/@joergdietrich/leaflet.terminator@1.0.0/L.Terminator.js').done(function () { var pane = map.createPane('nite'); pane.style.zIndex = 201; pane.style.pointerEvents = 'none !important'; pane.style.cursor = 'grab !important'; var t = L.terminator({ fillOpacity: 0.2, interactive: false, pane }); t.addTo(map); setInterval(function () { t.setTime(); }, 10000); // refresh every 10 secs }); // create layerControl and add more maps if (!layerControl) { var OpenTopoMap = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { maxZoom: 17, noWrap: true, attribution: 'Map data: © OpenStreetMap contributors, SRTM | Map style: © OpenTopoMap (CC-BY-SA)' }); var Stadia_AlidadeSmooth = L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png', { maxZoom: 20, noWrap: true, attribution: '© Stadia Maps, © OpenMapTiles © OpenStreetMap contributors', }); var Esri_WorldTopoMap = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', { noWrap: true, attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community' }); var Stadia_AlidadeSmoothDark = L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', { maxZoom: 20, noWrap: true, attribution: '© Stadia Maps, © OpenMapTiles © OpenStreetMap contributors' }); // used to open or collaps the layerControl by default function isMobile () { try { document.createEvent("TouchEvent"); return true; } catch (e) { return false; } } layerControl = L.control.layers({ 'OSM': baseLayer, 'StadiaAlidade': Stadia_AlidadeSmooth, 'StadiaAlidadeDark': Stadia_AlidadeSmoothDark, 'EsriWorldTopo': Esri_WorldTopoMap, 'OpenTopoMap': OpenTopoMap, }, null, { collapsed: isMobile(), hideSingleBase: true, position: 'bottomleft' } ).addTo(map); // move legend div to our layerControl $('
').insertAfter(layerControl._overlaysList); layerControl.legend = $('.openwebrx-map-legend').insertAfter($('#openwebrx-map-legend-separator')); } // layerControl // Load and initialize OWRX-specific map item managers $.getScript('static/lib/Leaflet.js').done(function() { // Process any accumulated updates self.processUpdates(updateQueue); updateQueue = []; if (!receiverMarker) { receiverMarker = new LMarker(); receiverMarker.setMarkerPosition(self.config['receiver_name'], receiverPos[0], receiverPos[1]); receiverMarker.addListener('click', function () { L.popup(receiverMarker.getPos(), { content: '