mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-04-30 10:45:57 +00:00
131 lines
8.2 KiB
JavaScript
131 lines
8.2 KiB
JavaScript
// Storage for the spot data that the server gives us.
|
|
var spots = []
|
|
// 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
|
|
// table and the callsign-band-mode is in this list, it is shown struck through as already worked. This is persisted
|
|
// to localStorage.
|
|
let worked = []
|
|
|
|
// 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".
|
|
function addBandToggleColourCSS(band_options) {
|
|
var $style = $('<style>');
|
|
band_options.forEach(o => {
|
|
var 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'])};}`);
|
|
});
|
|
$('html > head').append($style);
|
|
}
|
|
|
|
// Generate bands filter card. This one is a special case.
|
|
function generateBandsMultiToggleFilterCard(band_options) {
|
|
var $grid = $('<div class="row row-cols-4 g-1 mb-1">');
|
|
band_options.forEach(o => {
|
|
var 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>`);
|
|
});
|
|
$("#band-options").append($grid);
|
|
$("#band-options").append(`<div class="mt-1"><a href="#" onclick="toggleFilterButtons('band', true); return false;">All</a> <a href="#" onclick="toggleFilterButtons('band', false); return false;">None</a> <a href="#" onclick="setHamHFBandToggles(); return false;">Ham HF only</a></div>`);
|
|
}
|
|
|
|
// Set the band toggles so that only the amateur radio HF bands are selected. This includes 160m and 6m because that's
|
|
// widely expected by hams to be included. Special case of toggleFilterButtons().
|
|
function setHamHFBandToggles() {
|
|
const hamHFBands = ["160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m", "6m"];
|
|
$(".filter-button-band").each(function() {
|
|
$(this).prop('checked', hamHFBands.includes($(this).val().replace("filter-button-band-", "")));
|
|
});
|
|
filtersUpdated();
|
|
}
|
|
|
|
// Generate SIGs filter card. This one is also a special case.
|
|
function generateSIGsMultiToggleFilterCard(sig_options) {
|
|
var $grid = $('<div class="row row-cols-3 g-1 mb-1">');
|
|
sig_options.forEach(o => {
|
|
var 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>`);
|
|
});
|
|
// Bonus "NO_SIG" / "General DX" option
|
|
$grid.append(`<div class="col-8"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-NO_SIG" value="NO_SIG" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-NO_SIG" for="filter-button-sig-NO_SIG"><i class="fa-solid fa-tower-cell"></i> General DX</label></div></div>`);
|
|
$("#sig-options").append($grid);
|
|
$("#sig-options").append(`<div class="mt-1"><a href="#" onclick="toggleFilterButtons('sig', true); return false;">All</a> <a href="#" onclick="toggleFilterButtons('sig', false); return false;">None</a></div>`);
|
|
}
|
|
|
|
// Generate modes filter card. This one is also a special case.
|
|
function generateModesMultiToggleFilterCard(mode_options) {
|
|
var $grid = $('<div class="row row-cols-3 g-1 mb-1">');
|
|
mode_options.forEach(o => {
|
|
var 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>`);
|
|
});
|
|
$("#mode-options").append($grid);
|
|
$("#mode-options").append(`<div class="mt-1"><a href="#" onclick="toggleFilterButtons('mode', true); return false;">All</a> <a href="#" onclick="toggleFilterButtons('mode', false); return false;">None</a> <a href="#" onclick="setVoiceModeToggles(); return false;">Voice only</a> <a href="#" onclick="setDigiModeToggles(); return false;">Digimodes only</a></div>`);
|
|
}
|
|
|
|
// Set the mode toggles that relate to Analog Voice.
|
|
function setVoiceModeToggles() {
|
|
const modes = ["PHONE", "SSB", "LSB", "USB", "AM", "FM", "DV", "DMR", "DSTAR", "C4FM", "M17"];
|
|
$(".filter-button-mode").each(function() {
|
|
$(this).prop('checked', modes.includes($(this).val().replace("filter-button-mode-", "")));
|
|
});
|
|
filtersUpdated();
|
|
}
|
|
|
|
// Set the mode toggles that relate to Digimodes.
|
|
function setDigiModeToggles() {
|
|
const modes = ["DATA", "FT8", "FT4", "RTTY", "SSTV", "JS8", "HELL", "PSK", "OLIVIA", "PKT", "MSK144"];
|
|
$(".filter-button-mode").each(function() {
|
|
$(this).prop('checked', modes.includes($(this).val().replace("filter-button-mode-", "")));
|
|
});
|
|
filtersUpdated();
|
|
}
|
|
|
|
// Generate Sources filter card. This one is a minor special case as we create the checkboxes in the normal way, but
|
|
// 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.
|
|
function generateSourcesMultiToggleFilterCard(source_options, sources_enabled_by_default) {
|
|
var $grid = $('<div class="row row-cols-3 g-1 mb-1">');
|
|
source_options.forEach(o => {
|
|
var enable = sources_enabled_by_default.includes(o);
|
|
var 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>`);
|
|
});
|
|
$("#source-options").append($grid);
|
|
$("#source-options").append(`<div class="mt-1"><a href="#" onclick="toggleFilterButtons('source', true); return false;">All</a> <a href="#" onclick="toggleFilterButtons('source', false); return false;">None</a></div>`);
|
|
}
|
|
|
|
// Method called when any filter is changed to reload the spots and persist the filter settings.
|
|
function filtersUpdated() {
|
|
loadSpots();
|
|
saveSettings();
|
|
}
|
|
|
|
// Function to update the band colour scheme in spots, bands and map pages
|
|
function setBandColorSchemeFromUI() {
|
|
setBandColorScheme($("#band-color-scheme option:selected").val());
|
|
saveSettings();
|
|
// Fudge a full reload because we need to update not just colours in the list/map/bands but also the filters
|
|
window.location.reload();
|
|
}
|
|
|
|
// Query if a callsign-band-mode combination as has already been worked
|
|
function alreadyWorked(callsign, band, mode) {
|
|
return worked.includes(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
|
|
// after some time has passed with it in the background.
|
|
addEventListener("visibilitychange", (event) => {
|
|
if (!document.hidden) {
|
|
loadSpots();
|
|
}
|
|
});
|
|
|
|
// Startup
|
|
$(document).ready(function() {
|
|
// Load worked list
|
|
var tmpWorked = JSON.parse(localStorage.getItem("worked"));
|
|
if (tmpWorked) {
|
|
worked = tmpWorked;
|
|
}
|
|
}); |