mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-08-13 16:07:30 +00:00
Add distance column for spots
This commit is contained in:
@@ -20,6 +20,20 @@ function calcBearing(lat1, lon1, lat2, lon2) {
|
|||||||
return bearing;
|
return bearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calcDistanceKm(lat1, lon1, lat2, lon2) {
|
||||||
|
const EARTH_RADIUS_KM = 6371;
|
||||||
|
lat1 *= Math.PI / 180;
|
||||||
|
lon1 *= Math.PI / 180;
|
||||||
|
lat2 *= Math.PI / 180;
|
||||||
|
lon2 *= Math.PI / 180;
|
||||||
|
const latDelta = lat2 - lat1;
|
||||||
|
const lonDelta = lon2 - lon1;
|
||||||
|
const a = Math.sin(latDelta / 2) ** 2 +
|
||||||
|
Math.cos(lat1) * Math.cos(lat2) * Math.sin(lonDelta / 2) ** 2;
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
return EARTH_RADIUS_KM * c;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a Maidenhead grid reference of arbitrary precision to the lat/long of the centre point of the square.
|
// Convert a Maidenhead grid reference of arbitrary precision to the lat/long of the centre point of the square.
|
||||||
// Returns null if the grid format is invalid.
|
// Returns null if the grid format is invalid.
|
||||||
function latLonForGridCentre(grid) {
|
function latLonForGridCentre(grid) {
|
||||||
|
|||||||
+33
-4
@@ -115,6 +115,7 @@ function updateTable() {
|
|||||||
const showMode = $("#tableShowMode")[0].checked;
|
const showMode = $("#tableShowMode")[0].checked;
|
||||||
const showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
||||||
|
const showDistance = $("#tableShowDistance")[0].checked && userPos != null;
|
||||||
const showType = $("#tableShowType")[0].checked;
|
const showType = $("#tableShowType")[0].checked;
|
||||||
const showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
const showDE = $("#tableShowDE")[0].checked;
|
const showDE = $("#tableShowDE")[0].checked;
|
||||||
@@ -141,6 +142,9 @@ function updateTable() {
|
|||||||
if (showBearing) {
|
if (showBearing) {
|
||||||
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Bearing</th>`);
|
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Bearing</th>`);
|
||||||
}
|
}
|
||||||
|
if (showDistance) {
|
||||||
|
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Distance</th>`);
|
||||||
|
}
|
||||||
if (showType) {
|
if (showType) {
|
||||||
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Type</th>`);
|
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Type</th>`);
|
||||||
}
|
}
|
||||||
@@ -191,6 +195,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
const showMode = $("#tableShowMode")[0].checked;
|
const showMode = $("#tableShowMode")[0].checked;
|
||||||
const showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
||||||
|
const showDistance = $("#tableShowDistance")[0].checked && userPos != null;
|
||||||
const showType = $("#tableShowType")[0].checked;
|
const showType = $("#tableShowType")[0].checked;
|
||||||
const showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
const showDE = $("#tableShowDE")[0].checked;
|
const showDE = $("#tableShowDE")[0].checked;
|
||||||
@@ -280,13 +285,27 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
bearingText = bearing.toFixed(0).padStart(3, '0') + "°";
|
bearingText = bearing.toFixed(0).padStart(3, '0') + "°";
|
||||||
if (s["dx_location_good"] == null || s["dx_location_good"] === false) {
|
if (s["dx_location_good"] == null || s["dx_location_good"] === false) {
|
||||||
if (s["dx_location_source"] === "HOME QTH") {
|
if (s["dx_location_source"] === "HOME QTH") {
|
||||||
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to a QRZ \"home\" location for a portable/mobile/alternative spot, so this bearing may not be accurate if the DX is close to you..'></i></span>";
|
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to a QRZ \"home\" location for a portable/mobile/alternative spot, so this bearing may not be accurate if the DX is close to you.'></i></span>";
|
||||||
} else {
|
} else {
|
||||||
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to just using the centre of a DXCC entity, so this bearing may not be accurate if the DX is close to you.'></i></span>";
|
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to just using the centre of a DXCC entity, so this bearing may not be accurate if the DX is close to you.'></i></span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format distance text
|
||||||
|
let distanceText = "---<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service, and we could not determine one. A distance to this DX is not available.'></i></span>";
|
||||||
|
if (userPos != null && s["dx_latitude"] != null && s["dx_longitude"] != null) {
|
||||||
|
const distance = calcDistanceKm(userPos[0], userPos[1], s["dx_latitude"], s["dx_longitude"]);
|
||||||
|
distanceText = distance.toFixed(0) + " km";
|
||||||
|
if (s["dx_location_good"] == null || s["dx_location_good"] === false) {
|
||||||
|
if (s["dx_location_source"] === "HOME QTH") {
|
||||||
|
distanceText = distanceText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to a QRZ \"home\" location for a portable/mobile/alternative spot, so this distance may not be accurate if the DX is close to you.'></i></span>";
|
||||||
|
} else {
|
||||||
|
distanceText = distanceText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to just using the centre of a DXCC entity, so this distance may not be accurate if the DX is close to you.'></i></span>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Format "type" (Sig or fallback to source)
|
// Format "type" (Sig or fallback to source)
|
||||||
let typeText = s["source"];
|
let typeText = s["source"];
|
||||||
if (s["sig"]) {
|
if (s["sig"]) {
|
||||||
@@ -354,6 +373,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
if (showBearing) {
|
if (showBearing) {
|
||||||
$tr.append(`<td class='nowrap hideonmobile'>${bearingText}</td>`);
|
$tr.append(`<td class='nowrap hideonmobile'>${bearingText}</td>`);
|
||||||
}
|
}
|
||||||
|
if (showDistance) {
|
||||||
|
$tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`);
|
||||||
|
}
|
||||||
if (showType) {
|
if (showType) {
|
||||||
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText}</td>`);
|
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText}</td>`);
|
||||||
}
|
}
|
||||||
@@ -394,6 +416,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
if (showBearing) {
|
if (showBearing) {
|
||||||
$td2floatright.append(`${bearingText} `);
|
$td2floatright.append(`${bearingText} `);
|
||||||
}
|
}
|
||||||
|
if (showDistance) {
|
||||||
|
$td2floatright.append(`${distanceText} `);
|
||||||
|
}
|
||||||
if (showDE) {
|
if (showDE) {
|
||||||
$td2floatright.append(` de ${de_call} `);
|
$td2floatright.append(` de ${de_call} `);
|
||||||
}
|
}
|
||||||
@@ -443,12 +468,14 @@ function loadOptions() {
|
|||||||
// Load settings from settings storage now all the controls are available
|
// Load settings from settings storage now all the controls are available
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
// Extra setting - the toggle for the "bearing" column is disabled if the user has not entered a valid grid, and
|
// Extra setting - the toggle for the "bearing" & "distance" columns are disabled if the user has not entered a
|
||||||
// normally this logic is handled on user input to the grid field, but we might have just loaded a value direct
|
// valid grid, and normally this logic is handled on user input to the grid field, but we might have just loaded
|
||||||
// into the field, so apply the same logic here.
|
// a value direct into the field, so apply the same logic here.
|
||||||
$("#tableShowBearing").prop('disabled', !isUserGridValid());
|
$("#tableShowBearing").prop('disabled', !isUserGridValid());
|
||||||
|
$("#tableShowDistance").prop('disabled', !isUserGridValid());
|
||||||
if (!isUserGridValid()) {
|
if (!isUserGridValid()) {
|
||||||
$("#tableShowBearing").prop('checked', false);
|
$("#tableShowBearing").prop('checked', false);
|
||||||
|
$("#tableShowDistance").prop('checked', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load spots (this will also set up the SSE connection to update them too)
|
// Load spots (this will also set up the SSE connection to update them too)
|
||||||
@@ -470,8 +497,10 @@ function userGridUpdated() {
|
|||||||
}
|
}
|
||||||
// Enable/disable bearing column depending on grid validity
|
// Enable/disable bearing column depending on grid validity
|
||||||
$("#tableShowBearing").prop('disabled', !userGridValid);
|
$("#tableShowBearing").prop('disabled', !userGridValid);
|
||||||
|
$("#tableShowDistance").prop('disabled', !userGridValid);
|
||||||
if (!userGridValid) {
|
if (!userGridValid) {
|
||||||
$("#tableShowBearing").prop('checked', false);
|
$("#tableShowBearing").prop('checked', false);
|
||||||
|
$("#tableShowDistance").prop('checked', false);
|
||||||
}
|
}
|
||||||
// Save settings even if not a valid grid, this allows the user to clear their grid and have it save.
|
// Save settings even if not a valid grid, this allows the user to clear their grid and have it save.
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/add-spot.js?v=1786601585"></script>
|
<script src="/static/js/add-spot.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-add-spot").addClass("active");
|
$("#nav-link-add-spot").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/alerts.js?v=1786601585"></script>
|
<script src="/static/js/alerts.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-alerts").addClass("active");
|
$("#nav-link-alerts").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -79,8 +79,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1786601585"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1786628955"></script>
|
||||||
<script src="/static/js/bands.js?v=1786601585"></script>
|
<script src="/static/js/bands.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-bands").addClass("active");
|
$("#nav-link-bands").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
{% extends "skeleton.html" %}
|
{% extends "skeleton.html" %}
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<link rel="stylesheet" href="/static/css/style.css?v=1786601585" type="text/css">
|
<link rel="stylesheet" href="/static/css/style.css?v=1786628955" type="text/css">
|
||||||
<link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
|
<link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
|
||||||
<link href="/static/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
|
<link href="/static/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
|
||||||
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
<script src="/static/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
|
<script src="/static/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
|
||||||
<script src="/static/vendor/js/tinycolor2-1.6.0.min.js"></script>
|
<script src="/static/vendor/js/tinycolor2-1.6.0.min.js"></script>
|
||||||
|
|
||||||
<script src="/static/js/utils.js?v=1786601585"></script>
|
<script src="/static/js/utils.js?v=1786628955"></script>
|
||||||
<script src="/static/js/ui-ham.js?v=1786601585"></script>
|
<script src="/static/js/ui-ham.js?v=1786628955"></script>
|
||||||
<script src="/static/js/geo.js?v=1786601585"></script>
|
<script src="/static/js/geo.js?v=1786628955"></script>
|
||||||
<script src="/static/js/common.js?v=1786601585"></script>
|
<script src="/static/js/common.js?v=1786628955"></script>
|
||||||
{% end %}
|
{% end %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@@ -44,6 +44,13 @@
|
|||||||
<label class="form-check-label" for="tableShowBearing">Bearing</label>
|
<label class="form-check-label" for="tableShowBearing">Bearing</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDistance"
|
||||||
|
value="tableShowDistance" oninput="columnsUpdated();">
|
||||||
|
<label class="form-check-label" for="tableShowDistance">Distance</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType"
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType"
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
|
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
|
||||||
<script src="/static/js/conditions.js?v=1786601585"></script>
|
<script src="/static/js/conditions.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-conditions").addClass("active");
|
$("#nav-link-conditions").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
+2
-2
@@ -112,8 +112,8 @@
|
|||||||
<script src="/static/vendor/js/leaflet-cqzones.js"></script>
|
<script src="/static/vendor/js/leaflet-cqzones.js"></script>
|
||||||
<script src="/static/vendor/js/leaflet-workedallbritainireland.js" type="module"></script>
|
<script src="/static/vendor/js/leaflet-workedallbritainireland.js" type="module"></script>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1786601585"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1786628955"></script>
|
||||||
<script src="/static/js/map.js?v=1786601585"></script>
|
<script src="/static/js/map.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-map").addClass("active");
|
$("#nav-link-map").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -118,8 +118,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1786601585"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1786628955"></script>
|
||||||
<script src="/static/js/spots.js?v=1786601585"></script>
|
<script src="/static/js/spots.js?v=1786628955"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-spots").addClass("active");
|
$("#nav-link-spots").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/status.js?v=1786601585"></script>
|
<script src="/static/js/status.js?v=1786628955"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#nav-link-status").addClass("active");
|
$("#nav-link-status").addClass("active");
|
||||||
|
|||||||
Reference in New Issue
Block a user