diff --git a/templates/about.html b/templates/about.html index 6e89918..e2598b6 100644 --- a/templates/about.html +++ b/templates/about.html @@ -67,7 +67,7 @@

This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.

- + {% end %} \ No newline at end of file diff --git a/templates/add_spot.html b/templates/add_spot.html index 90c6ff8..c4bbeae 100644 --- a/templates/add_spot.html +++ b/templates/add_spot.html @@ -69,8 +69,8 @@ - - + + {% end %} \ No newline at end of file diff --git a/templates/alerts.html b/templates/alerts.html index 0782e4b..8e56d6e 100644 --- a/templates/alerts.html +++ b/templates/alerts.html @@ -56,8 +56,8 @@ - - + + {% end %} \ No newline at end of file diff --git a/templates/bands.html b/templates/bands.html index 62be938..dcf1eb2 100644 --- a/templates/bands.html +++ b/templates/bands.html @@ -62,9 +62,9 @@ - - - + + + {% end %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 091f2fc..9df4add 100644 --- a/templates/base.html +++ b/templates/base.html @@ -45,12 +45,11 @@ integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"> - - - - - + + + + diff --git a/templates/cards/basemap.html b/templates/cards/basemap.html new file mode 100644 index 0000000..299161d --- /dev/null +++ b/templates/cards/basemap.html @@ -0,0 +1,26 @@ +
+
+
Map Style
+

+ + +

+

+ + +

+
+
diff --git a/templates/cards/map-features.html b/templates/cards/map-features.html index 43ebbb2..018f02a 100644 --- a/templates/cards/map-features.html +++ b/templates/cards/map-features.html @@ -1,11 +1,41 @@
-
Map Features
+
Map Features
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/templates/conditions.html b/templates/conditions.html index ef08d66..9c345e6 100644 --- a/templates/conditions.html +++ b/templates/conditions.html @@ -223,8 +223,9 @@ - - + + + diff --git a/templates/map.html b/templates/map.html index 49737a2..00e5642 100644 --- a/templates/map.html +++ b/templates/map.html @@ -47,6 +47,9 @@
{% module Template("cards/spot-age.html", web_ui_options=web_ui_options) %}
+
+ {% module Template("cards/basemap.html", web_ui_options=web_ui_options) %} +
{% module Template("cards/map-features.html", web_ui_options=web_ui_options) %}
@@ -65,14 +68,20 @@ + + + + + + - - - + + + {% end %} \ No newline at end of file diff --git a/templates/spots.html b/templates/spots.html index 63e1574..94a24f6 100644 --- a/templates/spots.html +++ b/templates/spots.html @@ -87,9 +87,9 @@ - - - + + + {% end %} \ No newline at end of file diff --git a/templates/status.html b/templates/status.html index d37c08a..76ecce6 100644 --- a/templates/status.html +++ b/templates/status.html @@ -59,8 +59,8 @@ - - + + diff --git a/webassets/css/style.css b/webassets/css/style.css index 60afb58..8014847 100644 --- a/webassets/css/style.css +++ b/webassets/css/style.css @@ -220,11 +220,6 @@ div#map { font-family: var(--bs-body-font-family) !important; } -[data-bs-theme=dark] .leaflet-layer, -[data-bs-theme=dark] .leaflet-control-attribution { - filter: invert(100%) hue-rotate(180deg) brightness(95%) contrast(90%); -} - /* Make buttons overlaid on the map have a non-transparent fill so you can see the text better */ .btn-outline-secondary { --bs-btn-bg: var(--bs-body-bg) !important; diff --git a/webassets/js/map.js b/webassets/js/map.js index c09cc82..98de679 100644 --- a/webassets/js/map.js +++ b/webassets/js/map.js @@ -1,10 +1,27 @@ // How often to query the server? const REFRESH_INTERVAL_SEC = 60; +// Colours +const MAIDENHEAD_GRID_COLOR_LIGHT = 'rgba(200, 140, 140, 1.0)'; +const CQ_ZONES_COLOR_LIGHT = 'rgba(140, 200, 140, 1.0)'; +const ITU_ZONES_COLOR_LIGHT = 'rgba(200, 200, 140, 1.0)'; +const WAB_WAI_GRID_COLOR_LIGHT = 'rgba(140, 140, 200, 1.0)'; +const MAIDENHEAD_GRID_COLOR_DARK = 'rgba(120, 60, 60, 1.0)'; +const CQ_ZONES_COLOR_DARK = 'rgba(60, 120, 60, 1.0)'; +const ITU_ZONES_COLOR_DARK = 'rgba(120, 120, 60, 1.0)'; +const WAB_WAI_GRID_COLOR_DARK = 'rgba(60, 60, 120, 1.0)'; + // Map layers +var backgroundTileLayer; var markersLayer; var geodesicsLayer; var terminator; +var maidenheadGrid; +var cqZones; +var ituZones; +var wabwaiGrid; +// Tracks the currently-loaded basemap provider string to avoid unnecessary tile reloads +var loadedBasemap; // Load spots and populate the map. function loadSpots() { @@ -13,7 +30,9 @@ function loadSpots() { spots = jsonData; // Update map updateMap(); - terminator.setTime(); + if ($("#showTerminator")[0].checked) { + terminator.setTime(); + } }); } @@ -184,6 +203,15 @@ function loadOptions() { // Load settings from settings storage now all the controls are available loadSettings(); + // Apply basemap and overlay settings now that controls have their saved values + setBasemap($("#basemap").val()); + setBasemapOpacity(parseFloat($("#basemapOpacity").val())); + enableTerminator($("#showTerminator")[0].checked); + enableMaidenheadGrid($("#showMaidenheadGrid")[0].checked); + enableCQZones($("#showCQZones")[0].checked); + enableITUZones($("#showITUZones")[0].checked); + enableWABWAIGrid($("#showWABWAIGrid")[0].checked); + // Load spots and set up the timer loadSpots(); setInterval(loadSpots, REFRESH_INTERVAL_SEC * 1000); @@ -193,9 +221,118 @@ function loadOptions() { // Method called when any display property is changed to reload the map and persist the display settings. function displayUpdated() { updateMap(); + setBasemap($("#basemap").val()); + setBasemapOpacity(parseFloat($("#basemapOpacity").val())); + enableTerminator($("#showTerminator")[0].checked); + enableMaidenheadGrid($("#showMaidenheadGrid")[0].checked); + enableCQZones($("#showCQZones")[0].checked); + enableITUZones($("#showITUZones")[0].checked); + enableWABWAIGrid($("#showWABWAIGrid")[0].checked); saveSettings(); } +// Set the basemap +function setBasemap(basemapname) { + // Only change if we have to, to avoid a flash of reloading content + if (loadedBasemap !== basemapname) { + loadedBasemap = basemapname; + if (typeof backgroundTileLayer !== 'undefined') { + map.removeLayer(backgroundTileLayer); + } + backgroundTileLayer = L.tileLayer.provider(basemapname, { + opacity: parseFloat($("#basemapOpacity").val()), + edgeBufferTiles: 1 + }); + backgroundTileLayer.addTo(map); + backgroundTileLayer.bringToBack(); + + // Identify dark basemaps to ensure we use white text for unselected icons + // and change the background colour appropriately + const basemapIsDark = basemapname === "CartoDB.DarkMatter" || basemapname === "Esri.WorldImagery"; + $("#map").css('background-color', basemapIsDark ? "black" : "white"); + + // Change the colour of the grid and zone overlays to match + if (basemapIsDark) { + maidenheadGrid.options.color = MAIDENHEAD_GRID_COLOR_DARK; + cqZones.options.color = CQ_ZONES_COLOR_DARK; + ituZones.options.color = ITU_ZONES_COLOR_DARK; + wabwaiGrid.options.color = WAB_WAI_GRID_COLOR_DARK; + } else { + maidenheadGrid.options.color = MAIDENHEAD_GRID_COLOR_LIGHT; + cqZones.options.color = CQ_ZONES_COLOR_LIGHT; + ituZones.options.color = ITU_ZONES_COLOR_LIGHT; + wabwaiGrid.options.color = WAB_WAI_GRID_COLOR_LIGHT; + } + + // Force regenerate overlays in the new colours + map.removeLayer(maidenheadGrid); + map.removeLayer(cqZones); + map.removeLayer(ituZones); + map.removeLayer(wabwaiGrid); + enableMaidenheadGrid($("#showMaidenheadGrid")[0].checked); + enableCQZones($("#showCQZones")[0].checked); + enableITUZones($("#showITUZones")[0].checked); + enableWABWAIGrid($("#showWABWAIGrid")[0].checked); + } +} + +// Set the basemap opacity +function setBasemapOpacity(opacity) { + if (typeof backgroundTileLayer !== 'undefined') { + backgroundTileLayer.setOpacity(opacity); + } +} + +// Shows/hides the terminator/greyline overlay +function enableTerminator(show) { + if (show) { + terminator.setTime(); + terminator.addTo(map); + } else { + map.removeLayer(terminator); + } +} + +// Shows/hides the Maidenhead grid overlay +function enableMaidenheadGrid(show) { + if (show) { + maidenheadGrid.addTo(map); + backgroundTileLayer.bringToBack(); + } else { + map.removeLayer(maidenheadGrid); + } +} + +// Shows/hides the CQ zone overlay +function enableCQZones(show) { + if (show) { + cqZones.addTo(map); + backgroundTileLayer.bringToBack(); + } else { + map.removeLayer(cqZones); + } +} + +// Shows/hides the ITU zone overlay +function enableITUZones(show) { + if (show) { + ituZones.addTo(map); + backgroundTileLayer.bringToBack(); + } else { + map.removeLayer(ituZones); + } +} + +// Shows/hides the WAB/WAI grid overlay +function enableWABWAIGrid(show) { + if (show) { + wabwaiGrid.addTo(map); + backgroundTileLayer.bringToBack(); + } else { + map.removeLayer(wabwaiGrid); + } +} + // Set up the map function setUpMap() { // Create map @@ -206,8 +343,9 @@ function setUpMap() { }); // Add basemap - backgroundTileLayer = L.tileLayer.provider("OpenStreetMap.Mapnik", { - opacity: 1, + loadedBasemap = $("#basemap").val(); + backgroundTileLayer = L.tileLayer.provider(loadedBasemap, { + opacity: parseFloat($("#basemapOpacity").val()), edgeBufferTiles: 1 }); backgroundTileLayer.addTo(map); @@ -221,12 +359,50 @@ function setUpMap() { geodesicsLayer = new L.LayerGroup(); geodesicsLayer.addTo(map); - // Add terminator/greyline + // Add terminator/greyline (toggleable) terminator = L.terminator({ interactive: false }); terminator.setStyle({fillColor: '#00000050'}); - terminator.addTo(map); + if ($("#showTerminator")[0].checked) { + terminator.addTo(map); + } + + // Add Maidenhead grid (toggleable) + maidenheadGrid = L.maidenhead({ + color : MAIDENHEAD_GRID_COLOR_LIGHT + }); + if ($("#showMaidenheadGrid")[0].checked) { + maidenheadGrid.addTo(map); + backgroundTileLayer.bringToBack(); + } + + // Add CQ zone layer (toggleable) + cqZones = L.cqzones({ + color : CQ_ZONES_COLOR_LIGHT + }); + if ($("#showCQZones")[0].checked) { + cqZones.addTo(map); + backgroundTileLayer.bringToBack(); + } + + // Add ITU zone layer (toggleable) + ituZones = L.ituzones({ + color : ITU_ZONES_COLOR_LIGHT + }); + if ($("#showITUZones")[0].checked) { + ituZones.addTo(map); + backgroundTileLayer.bringToBack(); + } + + // Add WAB/WAI grid layer (toggleable) + wabwaiGrid = L.workedAllBritainIreland({ + color : WAB_WAI_GRID_COLOR_LIGHT + }); + if ($("#showWABWAIGrid")[0].checked) { + wabwaiGrid.addTo(map); + backgroundTileLayer.bringToBack(); + } // Display a default view. map.setView([30, 0], 3);