mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-06-24 05:35:10 +00:00
Fix some IDE warnings
This commit is contained in:
39
.idea/inspectionProfiles/Project_Default.xml
generated
39
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,6 +1,45 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Annotator" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="BadExpressionStatementJS" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="GrazieStyle" enabled="false" level="STYLE_SUGGESTION" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="HtmlUnknownAttribute" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="myValues">
|
||||||
|
<value>
|
||||||
|
<list size="0" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="myCustomValuesEnabled" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="HtmlUnknownTag" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="myValues">
|
||||||
|
<value>
|
||||||
|
<list size="6">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="nobr" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="noembed" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="comment" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="noscript" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="embed" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="script" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="myCustomValuesEnabled" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="HtmlUnknownTarget" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="HttpUrlsUsage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSDeprecatedSymbols" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSIgnoredPromiseFromCall" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSJQueryEfficiency" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSUnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSUnresolvedReference" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="OutdatedRequirementInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
<option name="processCode" value="true" />
|
<option name="processCode" value="true" />
|
||||||
<option name="processLiterals" value="true" />
|
<option name="processLiterals" value="true" />
|
||||||
|
|||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<settings>
|
|
||||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
|
||||||
<version value="1.0" />
|
|
||||||
</settings>
|
|
||||||
</component>
|
|
||||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$" libraries="{redoc.standalone}" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.idea/spothole.iml
generated
2
.idea/spothole.iml
generated
@@ -3,8 +3,10 @@
|
|||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/webassets/vendor" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.13 virtualenv at ~/code/spothole/.venv" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.13 virtualenv at ~/code/spothole/.venv" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="redoc.standalone" level="application" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/add-spot.js?v=1781809662"></script>
|
<script src="/js/add-spot.js?v=1781893916"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/alerts.js?v=1781809662"></script>
|
<script src="/js/alerts.js?v=1781893916"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1781809662"></script>
|
<script src="/js/spotsbandsandmap.js?v=1781893916"></script>
|
||||||
<script src="/js/bands.js?v=1781809662"></script>
|
<script src="/js/bands.js?v=1781893916"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "skeleton.html" %}
|
{% extends "skeleton.html" %}
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<link rel="stylesheet" href="/css/style.css?v=1781809662" type="text/css">
|
<link rel="stylesheet" href="/css/style.css?v=1781893916" type="text/css">
|
||||||
<link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
|
<link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
|
||||||
<link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
|
<link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
|
||||||
<link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
<link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
<script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
|
<script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
|
||||||
<script src="/vendor/js/tinycolor2-1.6.0.min.js"></script>
|
<script src="/vendor/js/tinycolor2-1.6.0.min.js"></script>
|
||||||
|
|
||||||
<script src="/js/utils.js?v=1781809662"></script>
|
<script src="/js/utils.js?v=1781893916"></script>
|
||||||
<script src="/js/ui-ham.js?v=1781809662"></script>
|
<script src="/js/ui-ham.js?v=1781893916"></script>
|
||||||
<script src="/js/geo.js?v=1781809662"></script>
|
<script src="/js/geo.js?v=1781893916"></script>
|
||||||
<script src="/js/common.js?v=1781809662"></script>
|
<script src="/js/common.js?v=1781893916"></script>
|
||||||
{% end %}
|
{% end %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/vendor/js/chart-4.4.9.umd.min.js"></script>
|
<script src="/vendor/js/chart-4.4.9.umd.min.js"></script>
|
||||||
<script src="/js/conditions.js?v=1781809662"></script>
|
<script src="/js/conditions.js?v=1781893916"></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>
|
||||||
|
|||||||
@@ -94,8 +94,8 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1781809662"></script>
|
<script src="/js/spotsbandsandmap.js?v=1781893916"></script>
|
||||||
<script src="/js/map.js?v=1781809662"></script>
|
<script src="/js/map.js?v=1781893916"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -104,8 +104,8 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1781809662"></script>
|
<script src="/js/spotsbandsandmap.js?v=1781893916"></script>
|
||||||
<script src="/js/spots.js?v=1781809662"></script>
|
<script src="/js/spots.js?v=1781893916"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/status.js?v=1781809662"></script>
|
<script src="/js/status.js?v=1781893916"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav -->
|
$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav -->
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ input#search {
|
|||||||
|
|
||||||
i#searchicon {
|
i#searchicon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0rem;
|
left: 0;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -217,7 +217,7 @@ div#map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-container {
|
.leaflet-container {
|
||||||
font-family: var(--bs-body-font-family) !important;
|
font-family: var(--bs-body-font-family) sans-serif !important;
|
||||||
}
|
}
|
||||||
.leaflet-control-attribution {
|
.leaflet-control-attribution {
|
||||||
background: none;
|
background: none;
|
||||||
|
|||||||
@@ -33,44 +33,44 @@ function addSpot() {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
|
|
||||||
// Unpack the user's entered values
|
// Unpack the user's entered values
|
||||||
var dx = $("#dx-call").val().toUpperCase();
|
const dx = $("#dx-call").val().toUpperCase();
|
||||||
var freqStr = $("#freq").val();
|
const freqStr = $("#freq").val();
|
||||||
var mode = $("#mode")[0].value;
|
const mode = $("#mode")[0].value;
|
||||||
var sig = $("#sig")[0].value;
|
const sig = $("#sig")[0].value;
|
||||||
var sigRef = $("#sig-ref").val();
|
const sigRef = $("#sig-ref").val();
|
||||||
var dxGrid = $("#dx-grid").val();
|
const dxGrid = $("#dx-grid").val();
|
||||||
var comment = $("#comment").val();
|
const comment = $("#comment").val();
|
||||||
var de = $("#de-call").val().toUpperCase();
|
const de = $("#de-call").val().toUpperCase();
|
||||||
|
|
||||||
var spot = {}
|
const spot = {};
|
||||||
if (dx != "") {
|
if (dx !== "") {
|
||||||
spot["dx_call"] = dx;
|
spot["dx_call"] = dx;
|
||||||
} else {
|
} else {
|
||||||
showAddSpotError("A DX callsign is required in order to spot.");
|
showAddSpotError("A DX callsign is required in order to spot.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (freqStr != "") {
|
if (freqStr !== "") {
|
||||||
spot["freq"] = parseFloat(freqStr) * 1000;
|
spot["freq"] = parseFloat(freqStr) * 1000;
|
||||||
} else {
|
} else {
|
||||||
showAddSpotError("A frequency is required in order to spot.");
|
showAddSpotError("A frequency is required in order to spot.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mode != "") {
|
if (mode !== "") {
|
||||||
spot["mode"] = mode;
|
spot["mode"] = mode;
|
||||||
}
|
}
|
||||||
if (sig != "") {
|
if (sig !== "") {
|
||||||
spot["sig"] = sig;
|
spot["sig"] = sig;
|
||||||
}
|
}
|
||||||
if (sigRef != "") {
|
if (sigRef !== "") {
|
||||||
spot["sig_refs"] = [{id: sigRef}];
|
spot["sig_refs"] = [{id: sigRef}];
|
||||||
}
|
}
|
||||||
if (dxGrid != "") {
|
if (dxGrid !== "") {
|
||||||
spot["dx_grid"] = dxGrid;
|
spot["dx_grid"] = dxGrid;
|
||||||
}
|
}
|
||||||
if (comment != "") {
|
if (comment !== "") {
|
||||||
spot["comment"] = comment;
|
spot["comment"] = comment;
|
||||||
}
|
}
|
||||||
if (de != "") {
|
if (de !== "") {
|
||||||
spot["de_call"] = de;
|
spot["de_call"] = de;
|
||||||
} else {
|
} else {
|
||||||
showAddSpotError("A spotter callsign is required in order to spot.");
|
showAddSpotError("A spotter callsign is required in order to spot.");
|
||||||
@@ -83,7 +83,7 @@ function addSpot() {
|
|||||||
contentType : 'application/json',
|
contentType : 'application/json',
|
||||||
type : 'POST',
|
type : 'POST',
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
success: async function (result) {
|
success: async function() {
|
||||||
$("#result-good").html("<div class='alert alert-success fade show mb-0 mt-4' role='alert'><i class='fa-solid fa-check'></i> Spot submitted. Returning you to the spots list...</div>");
|
$("#result-good").html("<div class='alert alert-success fade show mb-0 mt-4' role='alert'><i class='fa-solid fa-check'></i> Spot submitted. Returning you to the spots list...</div>");
|
||||||
$("#result-bad").html("");
|
$("#result-bad").html("");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -103,7 +103,7 @@ function addSpot() {
|
|||||||
|
|
||||||
// Show an "add spot" error.
|
// Show an "add spot" error.
|
||||||
function showAddSpotError(text) {
|
function showAddSpotError(text) {
|
||||||
var div = $("<div class='alert alert-danger alert-dismissible fade show mb-0 mt-4' role='alert'></div>");
|
const div = $("<div class='alert alert-danger alert-dismissible fade show mb-0 mt-4' role='alert'></div>");
|
||||||
div.append("<i class='fa-solid fa-triangle-exclamation'></i> ");
|
div.append("<i class='fa-solid fa-triangle-exclamation'></i> ");
|
||||||
div.append(document.createTextNode(text));
|
div.append(document.createTextNode(text));
|
||||||
div.append("<button type='button' class='btn-close' data-bs-dismiss='alert' aria-label='Close'></button>");
|
div.append("<button type='button' class='btn-close' data-bs-dismiss='alert' aria-label='Close'></button>");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const REFRESH_INTERVAL_SEC = 60 * 10;
|
const REFRESH_INTERVAL_SEC = 60 * 10;
|
||||||
|
|
||||||
// Storage for the alert data that the server gives us.
|
// Storage for the alert data that the server gives us.
|
||||||
var alerts = []
|
let alerts = [];
|
||||||
|
|
||||||
// Load alerts and populate the table.
|
// Load alerts and populate the table.
|
||||||
function loadAlerts() {
|
function loadAlerts() {
|
||||||
@@ -19,15 +19,15 @@ function loadAlerts() {
|
|||||||
|
|
||||||
// Build a query string for the API, based on the filters that the user has selected.
|
// Build a query string for the API, based on the filters that the user has selected.
|
||||||
function buildQueryString(includeCredentials) {
|
function buildQueryString(includeCredentials) {
|
||||||
var str = "?";
|
let str = "?";
|
||||||
["dx_continent", "source"].forEach(fn => {
|
["dx_continent", "source"].forEach(fn => {
|
||||||
if (!allFilterOptionsSelected(fn)) {
|
if (!allFilterOptionsSelected(fn)) {
|
||||||
str = str + getQueryStringFor(fn) + "&";
|
str = str + getQueryStringFor(fn) + "&";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
str = str + "limit=" + $("#alerts-to-fetch option:selected").val();
|
str = str + "limit=" + $("#alerts-to-fetch option:selected").val();
|
||||||
var maxDur = $("#max-duration option:selected").val();
|
const maxDur = $("#max-duration option:selected").val();
|
||||||
if (maxDur != "9999999999") {
|
if (maxDur !== "9999999999") {
|
||||||
str = str + "&max_duration=" + maxDur;
|
str = str + "&max_duration=" + maxDur;
|
||||||
}
|
}
|
||||||
if ($("#dxpeditions_skip_max_duration_check")[0].checked) {
|
if ($("#dxpeditions_skip_max_duration_check")[0].checked) {
|
||||||
@@ -42,16 +42,16 @@ function buildQueryString(includeCredentials) {
|
|||||||
// Update the alerts table
|
// Update the alerts table
|
||||||
function updateTable() {
|
function updateTable() {
|
||||||
// Use local time instead of UTC?
|
// Use local time instead of UTC?
|
||||||
var useLocalTime = $("#timeZone")[0].value == "local";
|
const useLocalTime = $("#timeZone")[0].value === "local";
|
||||||
|
|
||||||
// Table data toggles
|
// Table data toggles
|
||||||
var showStartTime = $("#tableShowStartTime")[0].checked;
|
const showStartTime = $("#tableShowStartTime")[0].checked;
|
||||||
var showEndTime = $("#tableShowEndTime")[0].checked;
|
const showEndTime = $("#tableShowEndTime")[0].checked;
|
||||||
var showDX = $("#tableShowDX")[0].checked;
|
const showDX = $("#tableShowDX")[0].checked;
|
||||||
var showFreqsModes = $("#tableShowFreqsModes")[0].checked;
|
const showFreqsModes = $("#tableShowFreqsModes")[0].checked;
|
||||||
var showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
var showSource = $("#tableShowSource")[0].checked;
|
const showSource = $("#tableShowSource")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
|
|
||||||
// Populate table with headers
|
// Populate table with headers
|
||||||
let table = $("#table");
|
let table = $("#table");
|
||||||
@@ -83,10 +83,10 @@ function updateTable() {
|
|||||||
// Split alerts into three types, each of which will get its own table header: On now, next 24h, and later. "On now"
|
// Split alerts into three types, each of which will get its own table header: On now, next 24h, and later. "On now"
|
||||||
// is considered to be events with an end_time where start<now<end, or events with no end time that started in the
|
// is considered to be events with an end_time where start<now<end, or events with no end time that started in the
|
||||||
// last hour.
|
// last hour.
|
||||||
onNow = alerts.filter(a => (a["end_time"] != null && a["end_time"] != 0 && moment.unix(a["end_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore())
|
const onNow = alerts.filter(a => (a["end_time"] != null && a["end_time"] !== 0 && moment.unix(a["end_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore())
|
||||||
|| ((a["end_time"] == null || a["end_time"] == 0) && moment.unix(a["start_time"]).utc().add(1, 'hours').isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore()));
|
|| ((a["end_time"] == null || a["end_time"] === 0) && moment.unix(a["start_time"]).utc().add(1, 'hours').isSameOrAfter() && moment.unix(a["start_time"]).utc().isBefore()));
|
||||||
next24h = alerts.filter(a => moment.unix(a["start_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().subtract(24, 'hours').isBefore());
|
const next24h = alerts.filter(a => moment.unix(a["start_time"]).utc().isSameOrAfter() && moment.unix(a["start_time"]).utc().subtract(24, 'hours').isBefore());
|
||||||
later = alerts.filter(a => moment.unix(a["start_time"]).utc().subtract(24, 'hours').isSameOrAfter());
|
const later = alerts.filter(a => moment.unix(a["start_time"]).utc().subtract(24, 'hours').isSameOrAfter());
|
||||||
|
|
||||||
if (onNow.length > 0) {
|
if (onNow.length > 0) {
|
||||||
table.find('tbody').append('<tr><td colspan="100" class="bg-primary-subtle" style="text-align:center;">On Now</td></tr>');
|
table.find('tbody').append('<tr><td colspan="100" class="bg-primary-subtle" style="text-align:center;">On Now</td></tr>');
|
||||||
@@ -103,14 +103,14 @@ function updateTable() {
|
|||||||
addAlertRowsToTable(table.find('tbody'), later);
|
addAlertRowsToTable(table.find('tbody'), later);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onNow.length == 0 && next24h.length == 0 && later.length == 0) {
|
if (onNow.length === 0 && next24h.length === 0 && later.length === 0) {
|
||||||
table.find('tbody').append('<tr class="bg-danger-subtle"><td colspan="100" style="text-align:center;">No alerts match your filters.</td></tr>');
|
table.find('tbody').append('<tr class="bg-danger-subtle"><td colspan="100" style="text-align:center;">No alerts match your filters.</td></tr>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a row to tbody for each alert in the provided list
|
// Add a row to tbody for each alert in the provided list
|
||||||
function addAlertRowsToTable(tbody, alerts) {
|
function addAlertRowsToTable(tbody, alerts) {
|
||||||
var count = 0;
|
let count = 0;
|
||||||
alerts.forEach(a => {
|
alerts.forEach(a => {
|
||||||
// Create row
|
// Create row
|
||||||
let $tr = $('<tr>');
|
let $tr = $('<tr>');
|
||||||
@@ -118,29 +118,29 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
// Apply striping to the table. We can't just use Bootstrap's table-striped class because we have all sorts of
|
// Apply striping to the table. We can't just use Bootstrap's table-striped class because we have all sorts of
|
||||||
// extra faff to deal with, like the mobile view having extra rows, and the On Now / Next 24h / Later banners
|
// extra faff to deal with, like the mobile view having extra rows, and the On Now / Next 24h / Later banners
|
||||||
// which cause the table-striped colouring to go awry.
|
// which cause the table-striped colouring to go awry.
|
||||||
if (count % 2 == 1) {
|
if (count % 2 === 1) {
|
||||||
$tr.addClass("table-active");
|
$tr.addClass("table-active");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use local time instead of UTC?
|
// Use local time instead of UTC?
|
||||||
var useLocalTime = $("#timeZone")[0].value == "local";
|
const useLocalTime = $("#timeZone")[0].value === "local";
|
||||||
|
|
||||||
// Table data toggles
|
// Table data toggles
|
||||||
var showStartTime = $("#tableShowStartTime")[0].checked;
|
const showStartTime = $("#tableShowStartTime")[0].checked;
|
||||||
var showEndTime = $("#tableShowEndTime")[0].checked;
|
const showEndTime = $("#tableShowEndTime")[0].checked;
|
||||||
var showDX = $("#tableShowDX")[0].checked;
|
const showDX = $("#tableShowDX")[0].checked;
|
||||||
var showFreqsModes = $("#tableShowFreqsModes")[0].checked;
|
const showFreqsModes = $("#tableShowFreqsModes")[0].checked;
|
||||||
var showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
var showSource = $("#tableShowSource")[0].checked;
|
const showSource = $("#tableShowSource")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
|
|
||||||
// Get times for the alert, and convert to local time if necessary.
|
// Get times for the alert, and convert to local time if necessary.
|
||||||
var start_time_utc = moment.unix(a["start_time"]).utc();
|
const start_time_utc = moment.unix(a["start_time"]).utc();
|
||||||
var start_time_local = start_time_utc.clone().local();
|
const start_time_local = start_time_utc.clone().local();
|
||||||
start_time = useLocalTime ? start_time_local : start_time_utc;
|
const start_time = useLocalTime ? start_time_local : start_time_utc;
|
||||||
var end_time_utc = moment.unix(a["end_time"]).utc();
|
const end_time_utc = moment.unix(a["end_time"]).utc();
|
||||||
var end_time_local = end_time_utc.clone().local();
|
const end_time_local = end_time_utc.clone().local();
|
||||||
end_time = useLocalTime ? end_time_local : end_time_utc;
|
const end_time = useLocalTime ? end_time_local : end_time_utc;
|
||||||
|
|
||||||
// Format the times for display. Start time is displayed as e.g. 7 Oct 12:34 unless the time is in a
|
// Format the times for display. Start time is displayed as e.g. 7 Oct 12:34 unless the time is in a
|
||||||
// different year to the current year, in which case the year is inserted between month and hour.
|
// different year to the current year, in which case the year is inserted between month and hour.
|
||||||
@@ -150,22 +150,22 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
// Overriding all of that, if the start time is 00:00 and the end time is 23:59 when considered in UTC, the
|
// Overriding all of that, if the start time is 00:00 and the end time is 23:59 when considered in UTC, the
|
||||||
// hours and minutes are stripped out from the display, as we assume the server is just giving us full days.
|
// hours and minutes are stripped out from the display, as we assume the server is just giving us full days.
|
||||||
// Finally, if there is no end date set, "---" is displayed.
|
// Finally, if there is no end date set, "---" is displayed.
|
||||||
var whole_days = start_time_utc.format("HH:mm") == "00:00" &&
|
const whole_days = start_time_utc.format("HH:mm") === "00:00" &&
|
||||||
(end_time_utc != null || end_time_utc > 0 || end_time_utc.format("HH:mm") == "23:59");
|
(end_time_utc === 0 || end_time_utc.format("HH:mm") === "23:59");
|
||||||
var hours_minutes_format = whole_days ? "" : " HH:mm";
|
const hours_minutes_format = whole_days ? "" : " HH:mm";
|
||||||
var start_time_formatted = start_time.format("D MMM" + hours_minutes_format);
|
let start_time_formatted = start_time.format("D MMM" + hours_minutes_format);
|
||||||
if (start_time.format("YYYY") != moment().format("YYYY")) {
|
if (start_time.format("YYYY") !== moment().format("YYYY")) {
|
||||||
start_time_formatted = start_time.format("D MMM YYYY" + hours_minutes_format);
|
start_time_formatted = start_time.format("D MMM YYYY" + hours_minutes_format);
|
||||||
} else if (useLocalTime && start_time.format("D MMM YYYY") == moment().format("D MMM YYYY")) {
|
} else if (useLocalTime && start_time.format("D MMM YYYY") === moment().format("D MMM YYYY")) {
|
||||||
start_time_formatted = start_time.format("[Today]" + hours_minutes_format);
|
start_time_formatted = start_time.format("[Today]" + hours_minutes_format);
|
||||||
}
|
}
|
||||||
var end_time_formatted = "---";
|
let end_time_formatted = "---";
|
||||||
if (end_time_utc != null && end_time_utc > 0 && end_time != null) {
|
if (end_time_utc > 0 && end_time != null) {
|
||||||
var end_time_formatted = whole_days ? start_time_formatted : end_time.format("HH:mm");
|
end_time_formatted = whole_days ? start_time_formatted : end_time.format("HH:mm");
|
||||||
if (end_time.format("D MMM") != start_time.format("D MMM")) {
|
if (end_time.format("D MMM") !== start_time.format("D MMM")) {
|
||||||
if (end_time.format("YYYY") != moment().format("YYYY")) {
|
if (end_time.format("YYYY") !== moment().format("YYYY")) {
|
||||||
end_time_formatted = end_time.format("D MMM YYYY" + hours_minutes_format);
|
end_time_formatted = end_time.format("D MMM YYYY" + hours_minutes_format);
|
||||||
} else if (useLocalTime && end_time.format("D MMM YYYY") == moment().format("D MMM YYYY")) {
|
} else if (useLocalTime && end_time.format("D MMM YYYY") === moment().format("D MMM YYYY")) {
|
||||||
end_time_formatted = end_time.format("[Today]" + hours_minutes_format);
|
end_time_formatted = end_time.format("[Today]" + hours_minutes_format);
|
||||||
} else {
|
} else {
|
||||||
end_time_formatted = end_time.format("D MMM" + hours_minutes_format);
|
end_time_formatted = end_time.format("D MMM" + hours_minutes_format);
|
||||||
@@ -174,52 +174,52 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format dx country
|
// Format dx country
|
||||||
var dx_country = a["dx_country"]
|
let dx_country = a["dx_country"];
|
||||||
if (dx_country == null) {
|
if (dx_country == null) {
|
||||||
dx_country = "Unknown or not a country"
|
dx_country = "Unknown or not a country"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format DX flag
|
// Format DX flag
|
||||||
var dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
let dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
||||||
if (a["dx_dxcc_id"] && a["dx_dxcc_id"] != null && a["dx_dxcc_id"] != 0) {
|
if (a["dx_dxcc_id"] && a["dx_dxcc_id"] != null && a["dx_dxcc_id"] !== 0) {
|
||||||
dx_flag = `<img src="img/flags/${a['dx_dxcc_id']}.png" class="flag" width="24" alt="${dx_country}" title="${dx_country}"/>`;
|
dx_flag = `<img src="img/flags/${a['dx_dxcc_id']}.png" class="flag" width="24" alt="${dx_country}" title="${dx_country}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format dx calls
|
// Format dx calls
|
||||||
var dx_calls_html = "";
|
let dx_calls_html = "";
|
||||||
if (a["dx_calls"] != null) {
|
if (a["dx_calls"] != null) {
|
||||||
dx_calls_html = a["dx_calls"].map(call => `<a class='dx-link' href='https://qrz.com/db/${call}' target='_new'>${call}</a>`).join(", ");
|
dx_calls_html = a["dx_calls"].map(call => `<a class='dx-link' href='https://qrz.com/db/${call}' target='_new'>${call}</a>`).join(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format DXpedition country
|
// Format DXpedition country
|
||||||
var dx_country_html = "";
|
let dx_country_html = "";
|
||||||
if (a["is_dxpedition"] == true && a["dx_country"] != null && a["dx_country"] != "") {
|
if (a["is_dxpedition"] === true && a["dx_country"] != null && a["dx_country"] !== "") {
|
||||||
dx_country_html = `<br/>${a["dx_country"]}`;
|
dx_country_html = `<br/>${a["dx_country"]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format freqs & modes
|
// Format freqs & modes
|
||||||
var freqsModesText = "";
|
let freqsModesText = "";
|
||||||
if (a["freqs_modes"] != null) {
|
if (a["freqs_modes"] != null) {
|
||||||
freqsModesText = escapeHtml(a["freqs_modes"]);
|
freqsModesText = escapeHtml(a["freqs_modes"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format comment
|
// Format comment
|
||||||
var commentText = "";
|
let commentText = "";
|
||||||
if (a["comment"] != null) {
|
if (a["comment"] != null) {
|
||||||
commentText = escapeHtml(a["comment"]);
|
commentText = escapeHtml(a["comment"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sig or fallback to source
|
// Sig or fallback to source
|
||||||
var sigSourceText = a["source"];
|
let sigSourceText = a["source"];
|
||||||
if (a["sig"]) {
|
if (a["sig"]) {
|
||||||
sigSourceText = a["sig"];
|
sigSourceText = a["sig"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format sig_refs
|
// Format sig_refs
|
||||||
var sig_refs = "";
|
let sig_refs = "";
|
||||||
if (a["sig_refs"] != null) {
|
if (a["sig_refs"] != null) {
|
||||||
var items = []
|
const items = [];
|
||||||
for (var i = 0; i < a["sig_refs"].length; i++) {
|
for (let i = 0; i < a["sig_refs"].length; i++) {
|
||||||
if (a["sig_refs"][i]["url"] != null) {
|
if (a["sig_refs"][i]["url"] != null) {
|
||||||
items[i] = `<a href='${encodeURI(a["sig_refs"][i]["url"])}' title='${escapeHtml(a["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(a["sig_refs"][i]["id"])}</a>`
|
items[i] = `<a href='${encodeURI(a["sig_refs"][i]["url"])}' title='${escapeHtml(a["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(a["sig_refs"][i]["id"])}</a>`
|
||||||
} else {
|
} else {
|
||||||
@@ -254,11 +254,11 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
tbody.append($tr);
|
tbody.append($tr);
|
||||||
|
|
||||||
// Second row for mobile view only, containing source, ref, freqs/modes & comment
|
// Second row for mobile view only, containing source, ref, freqs/modes & comment
|
||||||
$tr2 = $("<tr class='hidenotonmobile'>");
|
const $tr2 = $("<tr class='hidenotonmobile'>");
|
||||||
if (count % 2 == 1) {
|
if (count % 2 === 1) {
|
||||||
$tr2.addClass("table-active");
|
$tr2.addClass("table-active");
|
||||||
}
|
}
|
||||||
$td2 = $("<td colspan='100'>");
|
const $td2 = $("<td colspan='100'>");
|
||||||
if (showSource) {
|
if (showSource) {
|
||||||
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], "fa-globe-africa")}'></i></span> `);
|
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], "fa-globe-africa")}'></i></span> `);
|
||||||
}
|
}
|
||||||
@@ -319,7 +319,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
// Reload alerts on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
// Reload alerts on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
||||||
// after some time has passed with it in the background.
|
// after some time has passed with it in the background.
|
||||||
addEventListener("visibilitychange", (event) => {
|
addEventListener("visibilitychange", () => {
|
||||||
if (!document.hidden) {
|
if (!document.hidden) {
|
||||||
loadAlerts();
|
loadAlerts();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function loadSpots() {
|
|||||||
|
|
||||||
// Build a query string for the API, based on the filters that the user has selected.
|
// Build a query string for the API, based on the filters that the user has selected.
|
||||||
function buildQueryString(includeCredentials) {
|
function buildQueryString(includeCredentials) {
|
||||||
var str = "?";
|
let str = "?";
|
||||||
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
||||||
if (!allFilterOptionsSelected(fn)) {
|
if (!allFilterOptionsSelected(fn)) {
|
||||||
str = str + getQueryStringFor(fn) + "&";
|
str = str + getQueryStringFor(fn) + "&";
|
||||||
@@ -43,7 +43,7 @@ function buildQueryString(includeCredentials) {
|
|||||||
// Update the bands display
|
// Update the bands display
|
||||||
function updateBands() {
|
function updateBands() {
|
||||||
// Stop here if nothing to display
|
// Stop here if nothing to display
|
||||||
var bandsContainer = $("#bands-container");
|
const bandsContainer = $("#bands-container");
|
||||||
if (spots.length === 0) {
|
if (spots.length === 0) {
|
||||||
bandsContainer.html("<div class='alert alert-danger' role='alert'>No spots match your filters.</div>");
|
bandsContainer.html("<div class='alert alert-danger' role='alert'>No spots match your filters.</div>");
|
||||||
return;
|
return;
|
||||||
@@ -52,7 +52,7 @@ function updateBands() {
|
|||||||
// Do some harsher de-duping. Because we only display callsign, frequency and mode here, the previous
|
// Do some harsher de-duping. Because we only display callsign, frequency and mode here, the previous
|
||||||
// de-duplication could have let some through that don't look like dupes on the map, but would do here.
|
// de-duplication could have let some through that don't look like dupes on the map, but would do here.
|
||||||
// Typically that's a person activating two programs at the same time, e.g. POTA & WWFF.
|
// Typically that's a person activating two programs at the same time, e.g. POTA & WWFF.
|
||||||
spotList = removeDuplicatesForBandPanel(spots);
|
const spotList = removeDuplicatesForBandPanel(spots);
|
||||||
|
|
||||||
// Convert to a map of band names to the spots on that band. Bands with no
|
// Convert to a map of band names to the spots on that band. Bands with no
|
||||||
// spots in view will not be present.
|
// spots in view will not be present.
|
||||||
@@ -67,10 +67,10 @@ function updateBands() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Track if any columns end up taller than expected, so we can resize the container and avoid vertical scroll.
|
// Track if any columns end up taller than expected, so we can resize the container and avoid vertical scroll.
|
||||||
var maxHeightBand = 0;
|
let maxHeightBand = 0;
|
||||||
|
|
||||||
// Build up table content for each band
|
// Build up table content for each band
|
||||||
var table = $('<table id="bands-table">').append('<thead><tr></tr></thead><tbody><tr></tr></tbody>');
|
const table = $('<table id="bands-table">').append('<thead><tr></tr></thead><tbody><tr></tr></tbody>');
|
||||||
bandToSpots.forEach(function (spotList, bandName) {
|
bandToSpots.forEach(function (spotList, bandName) {
|
||||||
// Get the colours for the band from the first spot, and prepare the header
|
// Get the colours for the band from the first spot, and prepare the header
|
||||||
table.find('thead tr').append(`<th style='background-color:${bandToColor(spotList[0].band)}; color:${bandToContrastColor(spotList[0].band)}'>${spotList[0].band}</th>`);
|
table.find('thead tr').append(`<th style='background-color:${bandToColor(spotList[0].band)}; color:${bandToContrastColor(spotList[0].band)}'>${spotList[0].band}</th>`);
|
||||||
@@ -82,7 +82,7 @@ function updateBands() {
|
|||||||
|
|
||||||
// Print the frequency band markers. This is 41 steps to divide the band evenly into 40 markers. One in every
|
// Print the frequency band markers. This is 41 steps to divide the band evenly into 40 markers. One in every
|
||||||
// four will show the actual frequency, the others will just be dashes.
|
// four will show the actual frequency, the others will just be dashes.
|
||||||
bandMarkersDiv = $('<div class="band-markers">');
|
const bandMarkersDiv = $('<div class="band-markers">');
|
||||||
const freqStep = (band.end_freq - band.start_freq) / 40.0;
|
const freqStep = (band.end_freq - band.start_freq) / 40.0;
|
||||||
for (let i = 0; i <= 40; i++) {
|
for (let i = 0; i <= 40; i++) {
|
||||||
if (i % 4 === 0) {
|
if (i % 4 === 0) {
|
||||||
@@ -95,8 +95,8 @@ function updateBands() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the spots list
|
// Prepare the spots list
|
||||||
var bandSpotsDiv = $("<div class='band-spots'>");
|
const bandSpotsDiv = $("<div class='band-spots'>");
|
||||||
var lastSpotPxDownBand = -999;
|
let lastSpotPxDownBand = -999;
|
||||||
// Sort by frequency so have a consistent order in which to plan where they will appear on the band div.
|
// Sort by frequency so have a consistent order in which to plan where they will appear on the band div.
|
||||||
spotList.sort(function(a, b) { return a.freq - b.freq; });
|
spotList.sort(function(a, b) { return a.freq - b.freq; });
|
||||||
// First calculate how we should be displaying the spots. There are three "modes" to try to place them in a
|
// First calculate how we should be displaying the spots. There are three "modes" to try to place them in a
|
||||||
@@ -118,8 +118,8 @@ function updateBands() {
|
|||||||
// Mode 1 or 2. Run through adding things to the list forwards as a test.
|
// Mode 1 or 2. Run through adding things to the list forwards as a test.
|
||||||
spotList.forEach(s => {
|
spotList.forEach(s => {
|
||||||
// Work out how far down the div to draw it
|
// Work out how far down the div to draw it
|
||||||
var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
const percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
||||||
var pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX;
|
let pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX;
|
||||||
if (pxDownBand < lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX) {
|
if (pxDownBand < lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX) {
|
||||||
pxDownBand = lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap
|
pxDownBand = lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap
|
||||||
}
|
}
|
||||||
@@ -135,8 +135,8 @@ function updateBands() {
|
|||||||
lastSpotPxDownBand = 999999;
|
lastSpotPxDownBand = 999999;
|
||||||
spotList.reverse().forEach(s => {
|
spotList.reverse().forEach(s => {
|
||||||
// Work out how far down the div to draw it
|
// Work out how far down the div to draw it
|
||||||
var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
const percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
||||||
var pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX;
|
let pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX;
|
||||||
if (pxDownBand > lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX) {
|
if (pxDownBand > lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX) {
|
||||||
pxDownBand = lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap
|
pxDownBand = lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap
|
||||||
}
|
}
|
||||||
@@ -155,19 +155,19 @@ function updateBands() {
|
|||||||
// Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some
|
// Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some
|
||||||
// spots have gone off the end of the band markers and stretched their div, we need to resize the canvas to
|
// spots have gone off the end of the band markers and stretched their div, we need to resize the canvas to
|
||||||
// match, otherwise we have nowhere to draw their connecting lines.
|
// match, otherwise we have nowhere to draw their connecting lines.
|
||||||
var canvasHeight = Math.max(BAND_COLUMN_HEIGHT_PX, lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX);
|
const canvasHeight = Math.max(BAND_COLUMN_HEIGHT_PX, lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX);
|
||||||
maxHeightBand = Math.max(maxHeightBand, canvasHeight);
|
maxHeightBand = Math.max(maxHeightBand, canvasHeight);
|
||||||
|
|
||||||
// Draw horizontal or diagonal lines to join up the "real" frequency with where the spot div ended up
|
// Draw horizontal or diagonal lines to join up the "real" frequency with where the spot div ended up
|
||||||
var bandLinesCanvas = $(`<canvas class='band-lines-canvas' width='${BAND_COLUMN_CANVAS_WIDTH_PX}px' height='${canvasHeight}px' style='height:${canvasHeight}px !important;'>`);
|
const bandLinesCanvas = $(`<canvas class='band-lines-canvas' width='${BAND_COLUMN_CANVAS_WIDTH_PX}px' height='${canvasHeight}px' style='height:${canvasHeight}px !important;'>`);
|
||||||
spotList.forEach(s => {
|
spotList.forEach(s => {
|
||||||
// Work out how far down the div to draw it
|
// Work out how far down the div to draw it
|
||||||
var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
const percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
||||||
var pxDownBandFreq = (percentDownBand + 0.015) * BAND_COLUMN_HEIGHT_PX; // same fudge but add half to put the left end of the line in the right place
|
const pxDownBandFreq = (percentDownBand + 0.015) * BAND_COLUMN_HEIGHT_PX; // same fudge but add half to put the left end of the line in the right place
|
||||||
var pxDownBandLabel = s["pxDownBandLabel"] + (BAND_COLUMN_SPOT_DIV_HEIGHT_PX / 1.75); // line should be to the vertical text-centre spot, not to the top corner
|
const pxDownBandLabel = s["pxDownBandLabel"] + (BAND_COLUMN_SPOT_DIV_HEIGHT_PX / 1.75); // line should be to the vertical text-centre spot, not to the top corner
|
||||||
|
|
||||||
// Draw the line on the canvas
|
// Draw the line on the canvas
|
||||||
var ctx = bandLinesCanvas[0].getContext('2d');
|
const ctx = bandLinesCanvas[0].getContext('2d');
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.lineWidth = 2;
|
ctx.lineWidth = 2;
|
||||||
ctx.lineCap = "round";
|
ctx.lineCap = "round";
|
||||||
@@ -178,8 +178,8 @@ function updateBands() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Assemble the table cell
|
// Assemble the table cell
|
||||||
td = $("<td>");
|
const td = $("<td>");
|
||||||
container = $("<div class='band-container'>");
|
const container = $("<div class='band-container'>");
|
||||||
container.append(bandLinesCanvas);
|
container.append(bandLinesCanvas);
|
||||||
container.append(bandMarkersDiv);
|
container.append(bandMarkersDiv);
|
||||||
container.append(bandSpotsDiv);
|
container.append(bandSpotsDiv);
|
||||||
@@ -213,7 +213,6 @@ function removeDuplicatesForBandPanel(spotList) {
|
|||||||
if (s.dx_call === check.dx_call && s.freq === check.freq && s.mode === check.mode) {
|
if (s.dx_call === check.dx_call && s.freq === check.freq && s.mode === check.mode) {
|
||||||
// Find which one to keep and which to delete
|
// Find which one to keep and which to delete
|
||||||
const checkSpotNewer = check.time > s.time;
|
const checkSpotNewer = check.time > s.time;
|
||||||
const keepSpot = checkSpotNewer ? check : s;
|
|
||||||
const deleteSpot = checkSpotNewer ? s : check;
|
const deleteSpot = checkSpotNewer ? s : check;
|
||||||
// Aggregate list of spots to remove
|
// Aggregate list of spots to remove
|
||||||
spotsToRemove.push(deleteSpot.uid);
|
spotsToRemove.push(deleteSpot.uid);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Storage for the options that the server gives us. This will define our filters.
|
// Storage for the options that the server gives us. This will define our filters.
|
||||||
var options = {};
|
let options = {};
|
||||||
// Last time we updated the spots/alerts list on display.
|
// Last time we updated the spots/alerts list on display.
|
||||||
var lastUpdateTime;
|
let lastUpdateTime;
|
||||||
// Normally load user settings from local storage, unless embedded mode is in use
|
// Normally load user settings from local storage, unless embedded mode is in use
|
||||||
let useLocalStorage = true;
|
let useLocalStorage = true;
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ function saveSettings() {
|
|||||||
});
|
});
|
||||||
// Password fields are only saved if the corresponding "remember password" checkbox is ticked.
|
// Password fields are only saved if the corresponding "remember password" checkbox is ticked.
|
||||||
$(".password-field").each(function () {
|
$(".password-field").each(function () {
|
||||||
var pwKey = "#" + $(this)[0].id + ":value";
|
const pwKey = "#" + $(this)[0].id + ":value";
|
||||||
var rememberCheckboxId = $(this).data("remember-checkbox");
|
const rememberCheckboxId = $(this).data("remember-checkbox");
|
||||||
if (rememberCheckboxId && $("#" + rememberCheckboxId)[0] && $("#" + rememberCheckboxId)[0].checked) {
|
if (rememberCheckboxId && $("#" + rememberCheckboxId)[0] && $("#" + rememberCheckboxId)[0].checked) {
|
||||||
localStorage.setItem(pwKey, JSON.stringify($(this)[0].value));
|
localStorage.setItem(pwKey, JSON.stringify($(this)[0].value));
|
||||||
} else {
|
} else {
|
||||||
@@ -39,7 +39,7 @@ function loadSettings() {
|
|||||||
Object.keys(localStorage).forEach(function (key) {
|
Object.keys(localStorage).forEach(function (key) {
|
||||||
if (key.startsWith("#") && key.includes(":")) {
|
if (key.startsWith("#") && key.includes(":")) {
|
||||||
// Split the key back into an element ID and a property
|
// Split the key back into an element ID and a property
|
||||||
var split = key.split(":");
|
const split = key.split(":");
|
||||||
$(split[0]).prop(split[1], JSON.parse(localStorage.getItem(key)));
|
$(split[0]).prop(split[1], JSON.parse(localStorage.getItem(key)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -76,21 +76,13 @@ function loadURLParams() {
|
|||||||
updateFilterFromParam(params, "de_continent", "de_continent");
|
updateFilterFromParam(params, "de_continent", "de_continent");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update an HTML checkbox element so that its selected matches the given parameter (which must have a true or false value)
|
|
||||||
function updateCheckboxFromParam(params, paramName, checkboxID) {
|
|
||||||
let v = params.get(paramName);
|
|
||||||
if (v != null) {
|
|
||||||
$("#" + checkboxID).prop("checked", (v === "true") ? true : false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update an HTML select element so that its value matches the given parameter
|
// Update an HTML select element so that its value matches the given parameter
|
||||||
function updateSelectFromParam(params, paramName, selectID) {
|
function updateSelectFromParam(params, paramName, selectID) {
|
||||||
let v = params.get(paramName);
|
let v = params.get(paramName);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
$("#" + selectID).prop("value", v);
|
$("#" + selectID).prop("value", v);
|
||||||
// Extra check if this is the "color scheme" select
|
// Extra check if this is the "color scheme" select
|
||||||
if (selectID == "color-scheme") {
|
if (selectID === "color-scheme") {
|
||||||
setColorScheme(v);
|
setColorScheme(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,16 +120,16 @@ function getSelectedFilterOptions(parameter) {
|
|||||||
// For a parameter, such as dx_continent, return true if all possible options are enabled. (In this case, we don't need
|
// For a parameter, such as dx_continent, return true if all possible options are enabled. (In this case, we don't need
|
||||||
// to bother sending this as one of the query parameters to the API; no parameter provided implies "send everything".)
|
// to bother sending this as one of the query parameters to the API; no parameter provided implies "send everything".)
|
||||||
function allFilterOptionsSelected(parameter) {
|
function allFilterOptionsSelected(parameter) {
|
||||||
var filter = $(".filter-button-" + parameter).filter(function () {
|
const filter = $(".filter-button-" + parameter).filter(function () {
|
||||||
return !this.checked;
|
return !this.checked;
|
||||||
}).get();
|
}).get();
|
||||||
return filter.length == 0;
|
return filter.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate a filter card with inline checkboxes plus All/None links.
|
// Generate a filter card with inline checkboxes plus All/None links.
|
||||||
function generateMultiToggleFilterCard(elementID, filterQuery, options) {
|
function generateMultiToggleFilterCard(elementID, filterQuery, options) {
|
||||||
var $row = $('<div>');
|
const $row = $('<div>');
|
||||||
options.forEach(o => {
|
options.forEach(o => {
|
||||||
$row.append(`<div class="form-check form-check-inline"><input type="checkbox" class="form-check-input filter-button-${filterQuery} storeable-checkbox" id="filter-button-${filterQuery}-${o}" value="${o}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" for="filter-button-${filterQuery}-${o}">${o}</label></div>`);
|
$row.append(`<div class="form-check form-check-inline"><input type="checkbox" class="form-check-input filter-button-${filterQuery} storeable-checkbox" id="filter-button-${filterQuery}-${o}" value="${o}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" for="filter-button-${filterQuery}-${o}">${o}</label></div>`);
|
||||||
});
|
});
|
||||||
@@ -161,12 +153,13 @@ function updateRefreshDisplay() {
|
|||||||
let updatingString = "Updating..."
|
let updatingString = "Updating..."
|
||||||
if (secSinceUpdate < REFRESH_INTERVAL_SEC) {
|
if (secSinceUpdate < REFRESH_INTERVAL_SEC) {
|
||||||
count = REFRESH_INTERVAL_SEC - secSinceUpdate;
|
count = REFRESH_INTERVAL_SEC - secSinceUpdate;
|
||||||
|
let number;
|
||||||
if (count <= 60) {
|
if (count <= 60) {
|
||||||
var number = count.toFixed(0);
|
number = count.toFixed(0);
|
||||||
updatingString = "<span class='nowrap'>Updating in " + number + " second" + (number != "1" ? "s" : "") + ".</span>";
|
updatingString = "<span class='nowrap'>Updating in " + number + " second" + (number !== "1" ? "s" : "") + ".</span>";
|
||||||
} else {
|
} else {
|
||||||
var number = Math.round(count / 60.0).toFixed(0);
|
number = Math.round(count / 60.0).toFixed(0);
|
||||||
updatingString = "<span class='nowrap'>Updating in " + number + " minute" + (number != "1" ? "s" : "") + ".</span>";
|
updatingString = "<span class='nowrap'>Updating in " + number + " minute" + (number !== "1" ? "s" : "") + ".</span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$("#timing-container").html("Last updated at " + lastUpdateTime.format('HH:mm') + " UTC. " + updatingString);
|
$("#timing-container").html("Last updated at " + lastUpdateTime.format('HH:mm') + " UTC. " + updatingString);
|
||||||
@@ -188,7 +181,7 @@ function columnsUpdated() {
|
|||||||
// Function to set the colour scheme based on the state of the UI select box
|
// Function to set the colour scheme based on the state of the UI select box
|
||||||
function setColorSchemeFromUI() {
|
function setColorSchemeFromUI() {
|
||||||
let theme = $("#color-scheme option:selected").val();
|
let theme = $("#color-scheme option:selected").val();
|
||||||
if (theme != "") {
|
if (theme !== "") {
|
||||||
setColorScheme(theme);
|
setColorScheme(theme);
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
@@ -196,8 +189,8 @@ function setColorSchemeFromUI() {
|
|||||||
|
|
||||||
// Function to set the color scheme. Supported values: "dark", "light", "auto"
|
// Function to set the color scheme. Supported values: "dark", "light", "auto"
|
||||||
function setColorScheme(mode) {
|
function setColorScheme(mode) {
|
||||||
let effectiveModeDark = mode == "dark";
|
let effectiveModeDark = mode === "dark";
|
||||||
if (mode == "auto") {
|
if (mode === "auto") {
|
||||||
effectiveModeDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
effectiveModeDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
}
|
}
|
||||||
$("html").attr("data-bs-theme", effectiveModeDark ? "dark" : "light");
|
$("html").attr("data-bs-theme", effectiveModeDark ? "dark" : "light");
|
||||||
@@ -283,16 +276,16 @@ function closeDataPanel() {
|
|||||||
// Build a query string fragment containing any QRZ.com / HamQTH credentials the user has supplied,
|
// Build a query string fragment containing any QRZ.com / HamQTH credentials the user has supplied,
|
||||||
// provided the corresponding "enabled" checkbox is ticked.
|
// provided the corresponding "enabled" checkbox is ticked.
|
||||||
function getCredentialQueryString() {
|
function getCredentialQueryString() {
|
||||||
var str = "";
|
let str = "";
|
||||||
if ($("#qrz-enabled")[0] && $("#qrz-enabled")[0].checked) {
|
if ($("#qrz-enabled")[0] && $("#qrz-enabled")[0].checked) {
|
||||||
var qrzUsername = $("#qrz-username").val();
|
const qrzUsername = $("#qrz-username").val();
|
||||||
var qrzPassword = $("#qrz-password").val();
|
const qrzPassword = $("#qrz-password").val();
|
||||||
if (qrzUsername) str += "&qrz_username=" + encodeURIComponent(qrzUsername);
|
if (qrzUsername) str += "&qrz_username=" + encodeURIComponent(qrzUsername);
|
||||||
if (qrzPassword) str += "&qrz_password=" + encodeURIComponent(qrzPassword);
|
if (qrzPassword) str += "&qrz_password=" + encodeURIComponent(qrzPassword);
|
||||||
}
|
}
|
||||||
if ($("#hamqth-enabled")[0] && $("#hamqth-enabled")[0].checked) {
|
if ($("#hamqth-enabled")[0] && $("#hamqth-enabled")[0].checked) {
|
||||||
var hamqthUsername = $("#hamqth-username").val();
|
const hamqthUsername = $("#hamqth-username").val();
|
||||||
var hamqthPassword = $("#hamqth-password").val();
|
const hamqthPassword = $("#hamqth-password").val();
|
||||||
if (hamqthUsername) str += "&hamqth_username=" + encodeURIComponent(hamqthUsername);
|
if (hamqthUsername) str += "&hamqth_username=" + encodeURIComponent(hamqthUsername);
|
||||||
if (hamqthPassword) str += "&hamqth_password=" + encodeURIComponent(hamqthPassword);
|
if (hamqthPassword) str += "&hamqth_password=" + encodeURIComponent(hamqthPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ function calcBearing(lat1, lon1, lat2, lon2) {
|
|||||||
lon1 *= Math.PI / 180;
|
lon1 *= Math.PI / 180;
|
||||||
lat2 *= Math.PI / 180;
|
lat2 *= Math.PI / 180;
|
||||||
lon2 *= Math.PI / 180;
|
lon2 *= Math.PI / 180;
|
||||||
var lonDelta = lon2 - lon1;
|
const lonDelta = lon2 - lon1;
|
||||||
var y = Math.sin(lonDelta) * Math.cos(lat2);
|
const y = Math.sin(lonDelta) * Math.cos(lat2);
|
||||||
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lonDelta);
|
const x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lonDelta);
|
||||||
var bearing = Math.atan2(y, x);
|
let bearing = Math.atan2(y, x);
|
||||||
bearing = bearing * (180 / Math.PI);
|
bearing = bearing * (180 / Math.PI);
|
||||||
if ( bearing < 0 ) { bearing += 360; }
|
if ( bearing < 0 ) { bearing += 360; }
|
||||||
return bearing;
|
return bearing;
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ const ITU_ZONES_COLOR_DARK = 'rgba(120, 120, 60, 1.0)';
|
|||||||
const WAB_WAI_GRID_COLOR_DARK = 'rgba(60, 60, 120, 1.0)';
|
const WAB_WAI_GRID_COLOR_DARK = 'rgba(60, 60, 120, 1.0)';
|
||||||
|
|
||||||
// Map layers
|
// Map layers
|
||||||
var backgroundTileLayer;
|
let backgroundTileLayer;
|
||||||
var markersLayer;
|
let markersLayer;
|
||||||
var geodesicsLayer;
|
let geodesicsLayer;
|
||||||
var oms;
|
let oms;
|
||||||
var terminator;
|
let terminator;
|
||||||
var maidenheadGrid;
|
let maidenheadGrid;
|
||||||
var cqZones;
|
let cqZones;
|
||||||
var ituZones;
|
let ituZones;
|
||||||
var wabwaiGrid;
|
let wabwaiGrid;
|
||||||
// Tracks the currently-loaded basemap provider string to avoid unnecessary tile reloads
|
// Tracks the currently-loaded basemap provider string to avoid unnecessary tile reloads
|
||||||
var loadedBasemap;
|
let loadedBasemap;
|
||||||
// Tracks whether this is the first display of markers after page load
|
// Tracks whether this is the first display of markers after page load
|
||||||
var firstLoad = true;
|
let firstLoad = true;
|
||||||
|
|
||||||
// Load spots and populate the map.
|
// Load spots and populate the map.
|
||||||
function loadSpots() {
|
function loadSpots() {
|
||||||
@@ -41,7 +41,7 @@ function loadSpots() {
|
|||||||
|
|
||||||
// Build a query string for the API, based on the filters that the user has selected.
|
// Build a query string for the API, based on the filters that the user has selected.
|
||||||
function buildQueryString(includeCredentials) {
|
function buildQueryString(includeCredentials) {
|
||||||
var str = "?";
|
let str = "?";
|
||||||
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
||||||
if (!allFilterOptionsSelected(fn)) {
|
if (!allFilterOptionsSelected(fn)) {
|
||||||
str = str + getQueryStringFor(fn) + "&";
|
str = str + getQueryStringFor(fn) + "&";
|
||||||
@@ -65,7 +65,7 @@ function updateMap() {
|
|||||||
|
|
||||||
// Make new markers for all spots that match the filter
|
// Make new markers for all spots that match the filter
|
||||||
spots.forEach(function (s) {
|
spots.forEach(function (s) {
|
||||||
var m = L.marker([s["dx_latitude"], s["dx_longitude"]], {icon: getIcon(s)});
|
const m = L.marker([s["dx_latitude"], s["dx_longitude"]], {icon: getIcon(s)});
|
||||||
m.bindPopup(getTooltipText(s));
|
m.bindPopup(getTooltipText(s));
|
||||||
markersLayer.addLayer(m);
|
markersLayer.addLayer(m);
|
||||||
oms.addMarker(m);
|
oms.addMarker(m);
|
||||||
@@ -73,7 +73,7 @@ function updateMap() {
|
|||||||
// Create geodesics if required
|
// Create geodesics if required
|
||||||
if ($("#mapShowGeodesics")[0].checked && s["de_latitude"] != null && s["de_longitude"] != null) {
|
if ($("#mapShowGeodesics")[0].checked && s["de_latitude"] != null && s["de_longitude"] != null) {
|
||||||
try {
|
try {
|
||||||
var geodesic = L.geodesic([[s["de_latitude"], s["de_longitude"]], m.getLatLng()], {
|
const geodesic = L.geodesic([[s["de_latitude"], s["de_longitude"]], m.getLatLng()], {
|
||||||
color: bandToColor(s['band']),
|
color: bandToColor(s['band']),
|
||||||
wrap: false,
|
wrap: false,
|
||||||
steps: 5
|
steps: 5
|
||||||
@@ -88,7 +88,7 @@ function updateMap() {
|
|||||||
// On first load, zoom to the extent of the markers
|
// On first load, zoom to the extent of the markers
|
||||||
if (firstLoad) {
|
if (firstLoad) {
|
||||||
if (markersLayer.getLayers().length >= 2) {
|
if (markersLayer.getLayers().length >= 2) {
|
||||||
var group = new L.featureGroup(markersLayer.getLayers());
|
const group = new L.featureGroup(markersLayer.getLayers());
|
||||||
map.fitBounds(group.getBounds().pad(0.1));
|
map.fitBounds(group.getBounds().pad(0.1));
|
||||||
}
|
}
|
||||||
firstLoad = false;
|
firstLoad = false;
|
||||||
@@ -110,48 +110,50 @@ function getIcon(s) {
|
|||||||
// Tooltip text for the markers
|
// Tooltip text for the markers
|
||||||
function getTooltipText(s) {
|
function getTooltipText(s) {
|
||||||
// Format DX call
|
// Format DX call
|
||||||
var dx_call = s["dx_call"];
|
let dx_call = s["dx_call"];
|
||||||
if (dx_call == null) {
|
if (dx_call == null) {
|
||||||
dx_call = "";
|
dx_call = "";
|
||||||
dx_flag = "";
|
|
||||||
}
|
}
|
||||||
if (s["dx_ssid"] != null) {
|
if (s["dx_ssid"] != null) {
|
||||||
dx_call = dx_call + "-" + s["dx_ssid"];
|
dx_call = dx_call + "-" + s["dx_ssid"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format DX flag
|
// Format DX flag
|
||||||
var dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
let dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
||||||
if (s["dx_flag"] && s["dx_flag"] != null && s["dx_flag"] != "") {
|
if (dx_call == null) {
|
||||||
|
dx_flag = "";
|
||||||
|
}
|
||||||
|
if (s["dx_flag"] && s["dx_flag"] != null && s["dx_flag"] !== "") {
|
||||||
dx_flag = s["dx_flag"];
|
dx_flag = s["dx_flag"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the frequency
|
// Format the frequency
|
||||||
var freq_string = "Unknown"
|
let freq_string = "Unknown";
|
||||||
if (s["freq"] != null) {
|
if (s["freq"] != null) {
|
||||||
var mhz = Math.floor(s["freq"] / 1000000.0);
|
const mhz = Math.floor(s["freq"] / 1000000.0);
|
||||||
var khz = Math.floor((s["freq"] - (mhz * 1000000.0)) / 1000.0);
|
const khz = Math.floor((s["freq"] - (mhz * 1000000.0)) / 1000.0);
|
||||||
var hz = Math.floor(s["freq"] - (mhz * 1000000.0) - (khz * 1000.0));
|
const hz = Math.floor(s["freq"] - (mhz * 1000000.0) - (khz * 1000.0));
|
||||||
var hz_string = (hz > 0) ? hz.toFixed(0)[0] : "";
|
const hz_string = (hz > 0) ? hz.toFixed(0)[0] : "";
|
||||||
freq_string = `<span class='freq-mhz freq-mhz-pad'>${mhz.toFixed(0)}</span><span class='freq-khz'>${khz.toFixed(0).padStart(3, '0')}</span><span class='freq-hz hideonmobile'>${hz_string}</span>`
|
freq_string = `<span class='freq-mhz freq-mhz-pad'>${mhz.toFixed(0)}</span><span class='freq-khz'>${khz.toFixed(0).padStart(3, '0')}</span><span class='freq-hz hideonmobile'>${hz_string}</span>`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format comment
|
// Format comment
|
||||||
var commentText = "";
|
let commentText = "";
|
||||||
if (s["comment"] != null) {
|
if (s["comment"] != null) {
|
||||||
commentText = escapeHtml(s["comment"]);
|
commentText = escapeHtml(s["comment"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sig or fallback to source
|
// Sig or fallback to source
|
||||||
var sigSourceText = s["source"];
|
let sigSourceText = s["source"];
|
||||||
if (s["sig"]) {
|
if (s["sig"]) {
|
||||||
sigSourceText = s["sig"];
|
sigSourceText = s["sig"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format sig_refs
|
// Format sig_refs
|
||||||
var sig_refs = "";
|
let sig_refs = "";
|
||||||
if (s["sig_refs"] != null) {
|
if (s["sig_refs"] != null) {
|
||||||
var items = []
|
const items = [];
|
||||||
for (var i = 0; i < s["sig_refs"].length; i++) {
|
for (let i = 0; i < s["sig_refs"].length; i++) {
|
||||||
if (s["sig_refs"][i]["url"] != null) {
|
if (s["sig_refs"][i]["url"] != null) {
|
||||||
items[i] = `<a href='${s["sig_refs"][i]["url"]}' title='${s["sig_refs"][i]["name"]}' target='_new' class='sig-ref-link'>${s["sig_refs"][i]["id"]}</a>`
|
items[i] = `<a href='${s["sig_refs"][i]["url"]}' title='${s["sig_refs"][i]["name"]}' target='_new' class='sig-ref-link'>${s["sig_refs"][i]["id"]}</a>`
|
||||||
} else {
|
} else {
|
||||||
@@ -162,7 +164,7 @@ function getTooltipText(s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DX
|
// DX
|
||||||
ttt = `<span class='nowrap'><span class='icon-wrapper'>${dx_flag}</span> <a href='https://www.qrz.com/db/${dx_call}' target='_blank' class="dx-link">${dx_call}</a></span><br/>`;
|
let ttt = `<span class='nowrap'><span class='icon-wrapper'>${dx_flag}</span> <a href='https://www.qrz.com/db/${dx_call}' target='_blank' class="dx-link">${dx_call}</a></span><br/>`;
|
||||||
|
|
||||||
// Frequency & band
|
// Frequency & band
|
||||||
ttt += `<span class='icon-wrapper'><i class='fa-solid fa-radio markerPopupIcon'></i></span> ${freq_string}`;
|
ttt += `<span class='icon-wrapper'><i class='fa-solid fa-radio markerPopupIcon'></i></span> ${freq_string}`;
|
||||||
@@ -273,7 +275,7 @@ function setBasemap(basemapname) {
|
|||||||
backgroundTileLayer.addTo(map);
|
backgroundTileLayer.addTo(map);
|
||||||
backgroundTileLayer.bringToBack();
|
backgroundTileLayer.bringToBack();
|
||||||
if (basemapname === "OpenStreetMap.Mapnik.Dark") {
|
if (basemapname === "OpenStreetMap.Mapnik.Dark") {
|
||||||
var container = backgroundTileLayer.getContainer();
|
const container = backgroundTileLayer.getContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
container.style.filter = 'invert(100%) hue-rotate(180deg) brightness(80%)';
|
container.style.filter = 'invert(100%) hue-rotate(180deg) brightness(80%)';
|
||||||
}
|
}
|
||||||
@@ -409,7 +411,7 @@ function setUpMap() {
|
|||||||
backgroundTileLayer.addTo(map);
|
backgroundTileLayer.addTo(map);
|
||||||
backgroundTileLayer.bringToBack();
|
backgroundTileLayer.bringToBack();
|
||||||
if (loadedBasemap === "OpenStreetMap.Mapnik.Dark") {
|
if (loadedBasemap === "OpenStreetMap.Mapnik.Dark") {
|
||||||
var container = backgroundTileLayer.getContainer();
|
const container = backgroundTileLayer.getContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
container.style.filter = 'invert(100%) hue-rotate(180deg) brightness(80%)';
|
container.style.filter = 'invert(100%) hue-rotate(180deg) brightness(80%)';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function startSSEConnection() {
|
|||||||
|
|
||||||
evtSource.onmessage = function(event) {
|
evtSource.onmessage = function(event) {
|
||||||
// Get the new spot
|
// Get the new spot
|
||||||
newSpot = JSON.parse(event.data);
|
const newSpot = JSON.parse(event.data);
|
||||||
// Awful fudge to ensure new incoming spots at the top of the list don't have timestamps that make them look
|
// Awful fudge to ensure new incoming spots at the top of the list don't have timestamps that make them look
|
||||||
// like they belong further down the list. If the spot is older than the latest one we already have, bump its
|
// like they belong further down the list. If the spot is older than the latest one we already have, bump its
|
||||||
// time up to match it. This isn't great but since we poll spot providers every 2 minutes anyway, it shouldn't
|
// time up to match it. This isn't great but since we poll spot providers every 2 minutes anyway, it shouldn't
|
||||||
@@ -63,7 +63,7 @@ function startSSEConnection() {
|
|||||||
}
|
}
|
||||||
// If we had zero spots before (i.e. one now), the table will have a "No spots" row that we need to remove now
|
// If we had zero spots before (i.e. one now), the table will have a "No spots" row that we need to remove now
|
||||||
// that we have one.
|
// that we have one.
|
||||||
if (spots.length == 1) {
|
if (spots.length === 1) {
|
||||||
$("#table tbody tr").last().remove();
|
$("#table tbody tr").last().remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ function startSSEConnection() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
evtSource.onerror = function(err) {
|
evtSource.onerror = function() {
|
||||||
if (evtSource != null) {
|
if (evtSource != null) {
|
||||||
evtSource.close();
|
evtSource.close();
|
||||||
}
|
}
|
||||||
@@ -87,14 +87,14 @@ function startSSEConnection() {
|
|||||||
|
|
||||||
// Build a query string for the API, based on the filters that the user has selected.
|
// Build a query string for the API, based on the filters that the user has selected.
|
||||||
function buildQueryString(includeCredentials) {
|
function buildQueryString(includeCredentials) {
|
||||||
var str = "?";
|
let str = "?";
|
||||||
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
["dx_continent", "de_continent", "mode", "source", "band", "sig"].forEach(fn => {
|
||||||
if (!allFilterOptionsSelected(fn)) {
|
if (!allFilterOptionsSelected(fn)) {
|
||||||
str = str + getQueryStringFor(fn) + "&";
|
str = str + getQueryStringFor(fn) + "&";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
str = str + "limit=" + $("#spots-to-fetch option:selected").val();
|
str = str + "limit=" + $("#spots-to-fetch option:selected").val();
|
||||||
if ($("#search").val() != "") {
|
if ($("#search").val() !== "") {
|
||||||
str = str + "&text_includes=" + encodeURIComponent($("#search").val());
|
str = str + "&text_includes=" + encodeURIComponent($("#search").val());
|
||||||
}
|
}
|
||||||
if (includeCredentials) {
|
if (includeCredentials) {
|
||||||
@@ -106,22 +106,22 @@ function buildQueryString(includeCredentials) {
|
|||||||
// Update the spots table
|
// Update the spots table
|
||||||
function updateTable() {
|
function updateTable() {
|
||||||
// Use local time instead of UTC?
|
// Use local time instead of UTC?
|
||||||
var useLocalTime = $("#timeZone")[0].value == "local";
|
const useLocalTime = $("#timeZone")[0].value === "local";
|
||||||
|
|
||||||
// Get user grid if valid, this will be null if it's not.
|
// Get user grid if valid, this will be null if it's not.
|
||||||
var userPos = latLonForGridCentre($("#userGrid").val());
|
const userPos = latLonForGridCentre($("#userGrid").val());
|
||||||
|
|
||||||
// Table data toggles
|
// Table data toggles
|
||||||
var showTime = $("#tableShowTime")[0].checked;
|
const showTime = $("#tableShowTime")[0].checked;
|
||||||
var showDX = $("#tableShowDX")[0].checked;
|
const showDX = $("#tableShowDX")[0].checked;
|
||||||
var showFreq = $("#tableShowFreq")[0].checked;
|
const showFreq = $("#tableShowFreq")[0].checked;
|
||||||
var showMode = $("#tableShowMode")[0].checked;
|
const showMode = $("#tableShowMode")[0].checked;
|
||||||
var showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
var showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
||||||
var showType = $("#tableShowType")[0].checked;
|
const showType = $("#tableShowType")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
var showDE = $("#tableShowDE")[0].checked;
|
const showDE = $("#tableShowDE")[0].checked;
|
||||||
var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
||||||
|
|
||||||
// Populate table with headers
|
// Populate table with headers
|
||||||
let table = $("#table");
|
let table = $("#table");
|
||||||
@@ -158,7 +158,7 @@ function updateTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table.find('tbody').empty();
|
table.find('tbody').empty();
|
||||||
if (spots.length == 0) {
|
if (spots.length === 0) {
|
||||||
table.find('tbody').append('<tr class="bg-danger-subtle"><td colspan="100" style="text-align:center;">No spots match your filters.</td></tr>');
|
table.find('tbody').append('<tr class="bg-danger-subtle"><td colspan="100" style="text-align:center;">No spots match your filters.</td></tr>');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,22 +182,22 @@ function addSpotToTopOfTable(s, highlightNew) {
|
|||||||
// highlightNew = false for an initial load, true for new SSE-loaded spots
|
// highlightNew = false for an initial load, true for new SSE-loaded spots
|
||||||
function createNewTableRowsForSpot(s, highlightNew) {
|
function createNewTableRowsForSpot(s, highlightNew) {
|
||||||
// Use local time instead of UTC?
|
// Use local time instead of UTC?
|
||||||
var useLocalTime = $("#timeZone")[0].value == "local";
|
const useLocalTime = $("#timeZone")[0].value === "local";
|
||||||
|
|
||||||
// Get user grid if valid, this will be null if it's not.
|
// Get user grid if valid, this will be null if it's not.
|
||||||
var userPos = latLonForGridCentre($("#userGrid").val());
|
const userPos = latLonForGridCentre($("#userGrid").val());
|
||||||
|
|
||||||
// Table data toggles
|
// Table data toggles
|
||||||
var showTime = $("#tableShowTime")[0].checked;
|
const showTime = $("#tableShowTime")[0].checked;
|
||||||
var showDX = $("#tableShowDX")[0].checked;
|
const showDX = $("#tableShowDX")[0].checked;
|
||||||
var showFreq = $("#tableShowFreq")[0].checked;
|
const showFreq = $("#tableShowFreq")[0].checked;
|
||||||
var showMode = $("#tableShowMode")[0].checked;
|
const showMode = $("#tableShowMode")[0].checked;
|
||||||
var showComment = $("#tableShowComment")[0].checked;
|
const showComment = $("#tableShowComment")[0].checked;
|
||||||
var showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
|
||||||
var showType = $("#tableShowType")[0].checked;
|
const showType = $("#tableShowType")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
const showRef = $("#tableShowRef")[0].checked;
|
||||||
var showDE = $("#tableShowDE")[0].checked;
|
const showDE = $("#tableShowDE")[0].checked;
|
||||||
var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
||||||
|
|
||||||
// Create row
|
// Create row
|
||||||
let $tr = $('<tr>');
|
let $tr = $('<tr>');
|
||||||
@@ -205,13 +205,13 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
// Apply striping to the table. We can't just use Bootstrap's table-striped class because we have all sorts of
|
// Apply striping to the table. We can't just use Bootstrap's table-striped class because we have all sorts of
|
||||||
// extra faff to deal with, like the mobile view having extra rows, and the On Now / Next 24h / Later banners
|
// extra faff to deal with, like the mobile view having extra rows, and the On Now / Next 24h / Later banners
|
||||||
// which cause the table-striped colouring to go awry.
|
// which cause the table-striped colouring to go awry.
|
||||||
if (rowCount % 2 == 1) {
|
if (rowCount % 2 === 1) {
|
||||||
$tr.addClass("table-active");
|
$tr.addClass("table-active");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show faded out if QRT or already worked
|
// Show faded out if QRT or already worked
|
||||||
let alreadyWorkedThis = alreadyWorked(s["dx_call"], s["band"], s["mode"]);
|
let alreadyWorkedThis = alreadyWorked(s["dx_call"], s["band"], s["mode"]);
|
||||||
if (s["qrt"] == true || alreadyWorkedThis) {
|
if (s["qrt"] === true || alreadyWorkedThis) {
|
||||||
$tr.addClass("table-faded");
|
$tr.addClass("table-faded");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,65 +222,67 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format a UTC or local time for display
|
// Format a UTC or local time for display
|
||||||
var time = moment.unix(s["time"]).utc();
|
const time = moment.unix(s["time"]).utc();
|
||||||
if (useLocalTime) {
|
if (useLocalTime) {
|
||||||
time.local();
|
time.local();
|
||||||
}
|
}
|
||||||
var time_formatted = time.format("HH:mm");
|
const time_formatted = time.format("HH:mm");
|
||||||
|
|
||||||
// Format DX call
|
// Format DX call
|
||||||
var dx_call = s["dx_call"];
|
let dx_call = s["dx_call"];
|
||||||
if (dx_call == null) {
|
if (dx_call == null) {
|
||||||
dx_call = "";
|
dx_call = "";
|
||||||
dx_flag = "";
|
|
||||||
}
|
}
|
||||||
if (s["dx_ssid"] != null) {
|
if (s["dx_ssid"] != null) {
|
||||||
dx_call = dx_call + "-" + s["dx_ssid"];
|
dx_call = dx_call + "-" + s["dx_ssid"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format dx country
|
// Format dx country
|
||||||
var dx_country = s["dx_country"];
|
let dx_country = s["dx_country"];
|
||||||
if (dx_country == null) {
|
if (dx_country == null) {
|
||||||
dx_country = "Unknown or not a country";
|
dx_country = "Unknown or not a country";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format DX flag
|
// Format DX flag
|
||||||
var dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
let dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
||||||
if (s["dx_dxcc_id"] && s["dx_dxcc_id"] != null && s["dx_dxcc_id"] != 0) {
|
if (dx_call == null) {
|
||||||
|
dx_flag = "";
|
||||||
|
}
|
||||||
|
if (s["dx_dxcc_id"] && s["dx_dxcc_id"] != null && s["dx_dxcc_id"] !== 0) {
|
||||||
dx_flag = `<img src="img/flags/${s['dx_dxcc_id']}.png" class="flag" width="24" alt="${dx_country}" title="${dx_country}"/>`;
|
dx_flag = `<img src="img/flags/${s['dx_dxcc_id']}.png" class="flag" width="24" alt="${dx_country}" title="${dx_country}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the frequency
|
// Format the frequency
|
||||||
var freq_string = "Unknown"
|
let freq_string = "Unknown";
|
||||||
if (s["freq"] != null) {
|
if (s["freq"] != null) {
|
||||||
var mhz = Math.floor(s["freq"] / 1000000.0);
|
const mhz = Math.floor(s["freq"] / 1000000.0);
|
||||||
var khz = Math.floor((s["freq"] - (mhz * 1000000.0)) / 1000.0);
|
const khz = Math.floor((s["freq"] - (mhz * 1000000.0)) / 1000.0);
|
||||||
var hz = Math.floor(s["freq"] - (mhz * 1000000.0) - (khz * 1000.0));
|
const hz = Math.floor(s["freq"] - (mhz * 1000000.0) - (khz * 1000.0));
|
||||||
var hz_string = (hz > 0) ? hz.toFixed(0)[0] : "";
|
const hz_string = (hz > 0) ? hz.toFixed(0)[0] : "";
|
||||||
freq_string = `<span class='freq-mhz freq-mhz-pad'>${mhz.toFixed(0)}</span><span class='freq-khz'>${khz.toFixed(0).padStart(3, '0')}</span><span class='freq-hz hideonmobile'>${hz_string}</span>`
|
freq_string = `<span class='freq-mhz freq-mhz-pad'>${mhz.toFixed(0)}</span><span class='freq-khz'>${khz.toFixed(0).padStart(3, '0')}</span><span class='freq-hz hideonmobile'>${hz_string}</span>`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the mode
|
// Format the mode
|
||||||
mode_string = s["mode"];
|
let mode_string = s["mode"];
|
||||||
if (s["mode"] == null) {
|
if (s["mode"] == null) {
|
||||||
mode_string = "";
|
mode_string = "";
|
||||||
} else if (s["mode_source"] == "BANDPLAN") {
|
} else if (s["mode_source"] === "BANDPLAN") {
|
||||||
mode_string = mode_string + "<span class='mode-q hideonmobile'><i class='fa-solid fa-circle-question' title='The mode was not reported via the spotting service. This is a guess based on the frequency.'></i></span>";
|
mode_string = mode_string + "<span class='mode-q hideonmobile'><i class='fa-solid fa-circle-question' title='The mode was not reported via the spotting service. This is a guess based on the frequency.'></i></span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format comment
|
// Format comment
|
||||||
var commentText = "";
|
let commentText = "";
|
||||||
if (s["comment"] != null) {
|
if (s["comment"] != null) {
|
||||||
commentText = escapeHtml(s["comment"]);
|
commentText = escapeHtml(s["comment"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format bearing text
|
// Format bearing text
|
||||||
var bearingText = "---<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 bearing to this DX is not available.'></i></span>";
|
let bearingText = "---<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 bearing to this DX is not available.'></i></span>";
|
||||||
if (userPos != null && s["dx_latitude"] != null && s["dx_longitude"] != null) {
|
if (userPos != null && s["dx_latitude"] != null && s["dx_longitude"] != null) {
|
||||||
var bearing = calcBearing(userPos[0], userPos[1], s["dx_latitude"], s["dx_longitude"]);
|
const bearing = calcBearing(userPos[0], userPos[1], s["dx_latitude"], s["dx_longitude"]);
|
||||||
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>";
|
||||||
@@ -289,16 +291,16 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format "type" (Sig or fallback to source)
|
// Format "type" (Sig or fallback to source)
|
||||||
var typeText = s["source"];
|
let typeText = s["source"];
|
||||||
if (s["sig"]) {
|
if (s["sig"]) {
|
||||||
typeText = s["sig"];
|
typeText = s["sig"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format sig_refs
|
// Format sig_refs
|
||||||
var sig_refs = "";
|
let sig_refs = "";
|
||||||
if (s["sig_refs"] != null) {
|
if (s["sig_refs"] != null) {
|
||||||
var items = []
|
const items = [];
|
||||||
for (var i = 0; i < s["sig_refs"].length; i++) {
|
for (let i = 0; i < s["sig_refs"].length; i++) {
|
||||||
if (s["sig_refs"][i]["url"] != null) {
|
if (s["sig_refs"][i]["url"] != null) {
|
||||||
items[i] = `<span style="white-space: nowrap;"><a href='${encodeURI(s["sig_refs"][i]["url"])}' title='${escapeHtml(s["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(s["sig_refs"][i]["id"])}</a></span>`
|
items[i] = `<span style="white-space: nowrap;"><a href='${encodeURI(s["sig_refs"][i]["url"])}' title='${escapeHtml(s["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(s["sig_refs"][i]["id"])}</a></span>`
|
||||||
} else {
|
} else {
|
||||||
@@ -309,19 +311,19 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format de country
|
// Format de country
|
||||||
var de_country = s["de_country"];
|
let de_country = s["de_country"];
|
||||||
if (de_country == null) {
|
if (de_country == null) {
|
||||||
de_country = "Unknown or not a country";
|
de_country = "Unknown or not a country";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format DE flag
|
// Format DE flag
|
||||||
var de_flag = "<i class='fa-solid fa-circle-question'></i>";
|
let de_flag = "<i class='fa-solid fa-circle-question'></i>";
|
||||||
if (s["de_dxcc_id"] && s["de_dxcc_id"] != null && s["de_dxcc_id"] != 0) {
|
if (s["de_dxcc_id"] && s["de_dxcc_id"] != null && s["de_dxcc_id"] !== 0) {
|
||||||
de_flag = `<img src="img/flags/${s['de_dxcc_id']}.png" class="flag" width="24" alt="${de_country}" title="${de_country}"/>`;
|
de_flag = `<img src="img/flags/${s['de_dxcc_id']}.png" class="flag" width="24" alt="${de_country}" title="${de_country}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format de call
|
// Format de call
|
||||||
var de_call = s["de_call"];
|
let de_call = s["de_call"];
|
||||||
if (de_call == null) {
|
if (de_call == null) {
|
||||||
de_call = "";
|
de_call = "";
|
||||||
de_flag = "";
|
de_flag = "";
|
||||||
@@ -331,10 +333,10 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format band name
|
// Format band name
|
||||||
var bandFullName = s['band'] ? s['band'] + " band": "Unknown band";
|
const bandFullName = s['band'] ? s['band'] + " band" : "Unknown band";
|
||||||
|
|
||||||
// Format "worked" checkbox
|
// Format "worked" checkbox
|
||||||
var workedCheckbox = `<input type="checkbox" ${alreadyWorkedThis ? "checked" : ""} onClick="setWorkedState('${s['dx_call']}', '${s['band']}', '${s['mode']}', ${alreadyWorkedThis ? "false" : "true"});" title="Check this box to record that you have worked this callsign on their current band and mode.">`;
|
const workedCheckbox = `<input type="checkbox" ${alreadyWorkedThis ? "checked" : ""} onClick="setWorkedState('${s['dx_call']}', '${s['band']}', '${s['mode']}', ${alreadyWorkedThis ? "false" : "true"});" title="Check this box to record that you have worked this callsign on their current band and mode.">`;
|
||||||
|
|
||||||
// Populate the row
|
// Populate the row
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
@@ -369,21 +371,21 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Second row for mobile view only, containing type, ref & comment
|
// Second row for mobile view only, containing type, ref & comment
|
||||||
$tr2 = $("<tr class='hidenotonmobile'>");
|
const $tr2 = $("<tr class='hidenotonmobile'>");
|
||||||
|
|
||||||
// Apply styles as per the first row
|
// Apply styles as per the first row
|
||||||
if (rowCount % 2 == 1) {
|
if (rowCount % 2 === 1) {
|
||||||
$tr2.addClass("table-active");
|
$tr2.addClass("table-active");
|
||||||
}
|
}
|
||||||
if (s["qrt"] == true || alreadyWorkedThis) {
|
if (s["qrt"] === true || alreadyWorkedThis) {
|
||||||
$tr2.addClass("table-faded");
|
$tr2.addClass("table-faded");
|
||||||
}
|
}
|
||||||
if (highlightNew) {
|
if (highlightNew) {
|
||||||
$tr2.addClass("new");
|
$tr2.addClass("new");
|
||||||
}
|
}
|
||||||
|
|
||||||
$td2 = $("<td colspan='100'>");
|
const $td2 = $("<td colspan='100'>");
|
||||||
$td2floatleft = $(`<div style="float: left;">`);
|
const $td2floatleft = $(`<div style="float: left;">`);
|
||||||
if (showType) {
|
if (showType) {
|
||||||
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText} `);
|
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText} `);
|
||||||
}
|
}
|
||||||
@@ -391,7 +393,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
$td2floatleft.append(`${sig_refs} `);
|
$td2floatleft.append(`${sig_refs} `);
|
||||||
}
|
}
|
||||||
$td2.append($td2floatleft);
|
$td2.append($td2floatleft);
|
||||||
$td2floatright = $(`<div style="float: right;">`);
|
const $td2floatright = $(`<div style="float: right;">`);
|
||||||
if (showBearing) {
|
if (showBearing) {
|
||||||
$td2floatright.append(`${bearingText} `);
|
$td2floatright.append(`${bearingText} `);
|
||||||
}
|
}
|
||||||
@@ -459,13 +461,13 @@ function loadOptions() {
|
|||||||
|
|
||||||
// Work out if the user's entered grid is a valid Maidenhead grid
|
// Work out if the user's entered grid is a valid Maidenhead grid
|
||||||
function isUserGridValid() {
|
function isUserGridValid() {
|
||||||
userGrid = $("#userGrid").val().toUpperCase();
|
const userGrid = $("#userGrid").val().toUpperCase();
|
||||||
return latLonForGridCentre(userGrid) != null;
|
return latLonForGridCentre(userGrid) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method called when the user's grid input is changed.
|
// Method called when the user's grid input is changed.
|
||||||
function userGridUpdated() {
|
function userGridUpdated() {
|
||||||
var userGridValid = isUserGridValid();
|
const userGridValid = isUserGridValid();
|
||||||
if (userGridValid) {
|
if (userGridValid) {
|
||||||
updateTable();
|
updateTable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Storage for the spot data that the server gives us.
|
// Storage for the spot data that the server gives us.
|
||||||
var spots = []
|
let spots = [];
|
||||||
// List of people the user has worked. Each entry has the format callsign-band-mode. These can be added to the list by
|
// List of people the user has worked. Each entry has the format callsign-band-mode. These can be added to the list by
|
||||||
// ticking the checkbox on a row of the table, and cleared from the Display menu. Where a row would be added to the
|
// ticking the checkbox on a row of the table, and cleared from the Display menu. Where a row would be added to the
|
||||||
// table and the callsign-band-mode is in this list, it is shown struck through as already worked. This is persisted
|
// table and the callsign-band-mode is in this list, it is shown struck through as already worked. This is persisted
|
||||||
@@ -9,9 +9,9 @@ let worked = []
|
|||||||
// Dynamically add CSS code for the band checkboxes to show in the appropriate colour.
|
// Dynamically add CSS code for the band checkboxes to show in the appropriate colour.
|
||||||
// Some band names contain decimal points which are not allowed in CSS classes, so we text-replace them to "p".
|
// Some band names contain decimal points which are not allowed in CSS classes, so we text-replace them to "p".
|
||||||
function addBandToggleColourCSS(band_options) {
|
function addBandToggleColourCSS(band_options) {
|
||||||
var $style = $('<style>');
|
const $style = $('<style>');
|
||||||
band_options.forEach(o => {
|
band_options.forEach(o => {
|
||||||
var domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$style.append(`#filter-button-label-band-${domSafeName} { padding-left: 0.3em; border-left: 5px solid ${bandToColor(o['name'])};}`);
|
$style.append(`#filter-button-label-band-${domSafeName} { padding-left: 0.3em; border-left: 5px solid ${bandToColor(o['name'])};}`);
|
||||||
});
|
});
|
||||||
$('html > head').append($style);
|
$('html > head').append($style);
|
||||||
@@ -19,9 +19,9 @@ function addBandToggleColourCSS(band_options) {
|
|||||||
|
|
||||||
// Generate bands filter card. This one is a special case.
|
// Generate bands filter card. This one is a special case.
|
||||||
function generateBandsMultiToggleFilterCard(band_options) {
|
function generateBandsMultiToggleFilterCard(band_options) {
|
||||||
var $grid = $('<div class="row row-cols-3 row-cols-md-2 row-cols-lg-3 row-cols-xxl-4 g-1 mb-1">');
|
const $grid = $('<div class="row row-cols-3 row-cols-md-2 row-cols-lg-3 row-cols-xxl-4 g-1 mb-1">');
|
||||||
band_options.forEach(o => {
|
band_options.forEach(o => {
|
||||||
var domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-band storeable-checkbox" id="filter-button-band-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked> <label class="form-check-label" id="filter-button-label-band-${domSafeName}" for="filter-button-band-${domSafeName}">${o['name']}</label></div></div>`);
|
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-band storeable-checkbox" id="filter-button-band-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked> <label class="form-check-label" id="filter-button-label-band-${domSafeName}" for="filter-button-band-${domSafeName}">${o['name']}</label></div></div>`);
|
||||||
});
|
});
|
||||||
$("#band-options").append($grid);
|
$("#band-options").append($grid);
|
||||||
@@ -40,9 +40,9 @@ function setHamHFBandToggles() {
|
|||||||
|
|
||||||
// Generate SIGs filter card. This one is also a special case.
|
// Generate SIGs filter card. This one is also a special case.
|
||||||
function generateSIGsMultiToggleFilterCard(sig_options) {
|
function generateSIGsMultiToggleFilterCard(sig_options) {
|
||||||
var $grid = $('<div class="row row-cols-2 row-cols-xxl-3 g-1 mb-1">');
|
const $grid = $('<div class="row row-cols-2 row-cols-xxl-3 g-1 mb-1">');
|
||||||
sig_options.forEach(o => {
|
sig_options.forEach(o => {
|
||||||
var domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${sigToIcon(o['name'], 'fa-tower-cell')}"></i> ${o['name']}</label></div></div>`);
|
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${sigToIcon(o['name'], 'fa-tower-cell')}"></i> ${o['name']}</label></div></div>`);
|
||||||
});
|
});
|
||||||
// Bonus "NO_SIG" / "General DX" option
|
// Bonus "NO_SIG" / "General DX" option
|
||||||
@@ -53,9 +53,9 @@ function generateSIGsMultiToggleFilterCard(sig_options) {
|
|||||||
|
|
||||||
// Generate modes filter card. This one is also a special case.
|
// Generate modes filter card. This one is also a special case.
|
||||||
function generateModesMultiToggleFilterCard(mode_options) {
|
function generateModesMultiToggleFilterCard(mode_options) {
|
||||||
var $grid = $('<div class="row row-cols-3 row-cols-md-2 row-cols-lg-3 g-1 mb-1">');
|
const $grid = $('<div class="row row-cols-3 row-cols-md-2 row-cols-lg-3 g-1 mb-1">');
|
||||||
mode_options.forEach(o => {
|
mode_options.forEach(o => {
|
||||||
var domSafeName = o.replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o.replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-mode storeable-checkbox" id="filter-button-mode-${domSafeName}" value="${o}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-mode-${domSafeName}" for="filter-button-mode-${domSafeName}">${o}</label></div></div>`);
|
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-mode storeable-checkbox" id="filter-button-mode-${domSafeName}" value="${o}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-mode-${domSafeName}" for="filter-button-mode-${domSafeName}">${o}</label></div></div>`);
|
||||||
});
|
});
|
||||||
$("#mode-options").append($grid);
|
$("#mode-options").append($grid);
|
||||||
@@ -84,10 +84,10 @@ function setDigiModeToggles() {
|
|||||||
// set which ones are enabled by default based on config rather than having them all enabled by default. We also sanitise
|
// set which ones are enabled by default based on config rather than having them all enabled by default. We also sanitise
|
||||||
// names here for HTML elements.
|
// names here for HTML elements.
|
||||||
function generateSourcesMultiToggleFilterCard(source_options, sources_enabled_by_default) {
|
function generateSourcesMultiToggleFilterCard(source_options, sources_enabled_by_default) {
|
||||||
var $grid = $('<div class="row row-cols-2 row-cols-xxl-3 g-1 mb-1">');
|
const $grid = $('<div class="row row-cols-2 row-cols-xxl-3 g-1 mb-1">');
|
||||||
source_options.forEach(o => {
|
source_options.forEach(o => {
|
||||||
var enable = sources_enabled_by_default.includes(o);
|
const enable = sources_enabled_by_default.includes(o);
|
||||||
var domSafeName = o.replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o.replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-source storeable-checkbox" id="filter-button-source-${domSafeName}" value="${o}" autocomplete="off" onClick="filtersUpdated()" ${enable ? "checked" : ""}><label class="form-check-label" for="filter-button-source-${domSafeName}">${o}</label></div></div>`);
|
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-source storeable-checkbox" id="filter-button-source-${domSafeName}" value="${o}" autocomplete="off" onClick="filtersUpdated()" ${enable ? "checked" : ""}><label class="form-check-label" for="filter-button-source-${domSafeName}">${o}</label></div></div>`);
|
||||||
});
|
});
|
||||||
$("#source-options").append($grid);
|
$("#source-options").append($grid);
|
||||||
@@ -115,7 +115,7 @@ function alreadyWorked(callsign, band, mode) {
|
|||||||
|
|
||||||
// Reload spots on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
// Reload spots on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
||||||
// after some time has passed with it in the background.
|
// after some time has passed with it in the background.
|
||||||
addEventListener("visibilitychange", (event) => {
|
addEventListener("visibilitychange", () => {
|
||||||
if (!document.hidden) {
|
if (!document.hidden) {
|
||||||
loadSpots();
|
loadSpots();
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ addEventListener("visibilitychange", (event) => {
|
|||||||
// Startup
|
// Startup
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Load worked list
|
// Load worked list
|
||||||
var tmpWorked = JSON.parse(localStorage.getItem("worked"));
|
const tmpWorked = JSON.parse(localStorage.getItem("worked"));
|
||||||
if (tmpWorked) {
|
if (tmpWorked) {
|
||||||
worked = tmpWorked;
|
worked = tmpWorked;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,16 +296,6 @@ function setBandColorScheme(scheme) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of known bands
|
|
||||||
function getKnownBands() {
|
|
||||||
return Array.from(Object.keys(BAND_COLOR_SCHEMES[bandColorScheme]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of available band colour schemes
|
|
||||||
function getAvailableBandColorSchemes() {
|
|
||||||
return Array.from(Object.keys(BAND_COLOR_SCHEMES));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Band name to colour (in the current colour scheme). If the band is unknown, black will be returned.
|
// Band name to colour (in the current colour scheme). If the band is unknown, black will be returned.
|
||||||
function bandToColor(band) {
|
function bandToColor(band) {
|
||||||
let col = (band != null) ? BAND_COLOR_SCHEMES[bandColorScheme][band] : null;
|
let col = (band != null) ? BAND_COLOR_SCHEMES[bandColorScheme][band] : null;
|
||||||
@@ -324,22 +314,6 @@ function bandToContrastColor(band) {
|
|||||||
return (lum > 128) ? "#000000" : "#ffffff";
|
return (lum > 128) ? "#000000" : "#ffffff";
|
||||||
}
|
}
|
||||||
|
|
||||||
const MODE_TYPE_COLOR_SCHEMES = {
|
|
||||||
"CW": "red",
|
|
||||||
"PHONE": "green",
|
|
||||||
"DATA": "blue"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode type (CW, PHONE, DATA) to colour. If the mode type is unknown, black will be returned.
|
|
||||||
function modeTypeToColor(modeType) {
|
|
||||||
let col = (modeType != null) ? MODE_TYPE_COLOR_SCHEMES[modeType.toUpperCase()] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
return "#000000";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SIG_ICONS = {
|
const SIG_ICONS = {
|
||||||
"POTA": "fa-tree",
|
"POTA": "fa-tree",
|
||||||
"SOTA": "fa-mountain-sun",
|
"SOTA": "fa-mountain-sun",
|
||||||
@@ -365,31 +339,6 @@ const SIG_ICONS = {
|
|||||||
"TOTA": "fa-toilet"
|
"TOTA": "fa-toilet"
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIG_NAMES = {
|
|
||||||
"POTA": "Parks on the Air",
|
|
||||||
"SOTA": "Summits on the Air",
|
|
||||||
"WWFF": "Worldwide Flora & Fauna",
|
|
||||||
"GMA": "Global Mountain Activity",
|
|
||||||
"WWBOTA": "Bunkers on the Air",
|
|
||||||
"HEMA": "Humps Excluding Marilyns Award",
|
|
||||||
"IOTA": "Islands on the Air",
|
|
||||||
"MOTA": "Mills on the Air",
|
|
||||||
"ARLHS": "Amateur Radio Lighthouse Society",
|
|
||||||
"ILLW": "International Lighthouse Lightship Weekend",
|
|
||||||
"SIOTA": "Silos on the Air",
|
|
||||||
"WCA": "World Castles Award",
|
|
||||||
"ZLOTA": "New Zealand on the Air",
|
|
||||||
"WOTA": "Wainwrights on the Air",
|
|
||||||
"BOTA": "Beaches on the Air",
|
|
||||||
"KRMNPA": "Keith Roget Memorial National Parks Award",
|
|
||||||
"LLOTA": "Lagos y Lagunas on the Air",
|
|
||||||
"WWTOTA": "Towers on the Air",
|
|
||||||
"WAB": "Worked All Britain",
|
|
||||||
"WAI": "Worked All Ireland",
|
|
||||||
"Tiles": "Tiles on the Air",
|
|
||||||
"TOTA": "Toilets on the Air"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Font Awesome icon for a given SIG. If the SIG is unknown, the provided default symbol will be returned
|
// Get the Font Awesome icon for a given SIG. If the SIG is unknown, the provided default symbol will be returned
|
||||||
function sigToIcon(sig, defaultIcon) {
|
function sigToIcon(sig, defaultIcon) {
|
||||||
let col = (sig != null) ? SIG_ICONS[sig] : null;
|
let col = (sig != null) ? SIG_ICONS[sig] : null;
|
||||||
@@ -404,35 +353,3 @@ function sigToIcon(sig, defaultIcon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the full name for a given SIG abbreviation. If the SIG is unknown, an empty string will be returned.
|
|
||||||
function sigToName(sig) {
|
|
||||||
let col = (sig != null) ? SIG_NAMES[sig] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
let col = (sig != null) ? SIG_NAMES[sig.toUpperCase()] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of known SIGs
|
|
||||||
function getKnownSIGs() {
|
|
||||||
return Array.from(Object.keys(SIG_ICONS));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format a Maidenhead grid with alternating alphabetic blocks in lower case
|
|
||||||
function formatGrid(grid) {
|
|
||||||
grid = grid.toUpperCase();
|
|
||||||
if (grid.length >= 6) {
|
|
||||||
grid = grid.substring(0, 4) + grid.substring(4, 6).toLowerCase() + grid.substring(6);
|
|
||||||
}
|
|
||||||
if (grid.length >= 12) {
|
|
||||||
grid = grid.substring(0, 10) + grid.substring(10, 12).toLowerCase() + grid.substring(14);
|
|
||||||
}
|
|
||||||
return grid;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user