// Load spots and populate the table. function loadSpots() { $.getJSON('/api/v1/spots' + buildQueryString(), function(jsonData) { // Store last updated time lastUpdateTime = moment.utc(); updateRefreshDisplay(); // Store data spots = jsonData; // Update table updateTable(); }); } // Build a query string for the API, based on the filters that the user has selected. function buildQueryString() { var str = "?"; ["dx_continent", "de_continent", "mode_type", "source", "band"].forEach(fn => { if (!allFilterOptionsSelected(fn)) { str = str + getQueryStringFor(fn) + "&"; } }); str = str + "limit=" + $("#spots-to-fetch option:selected").val(); return str; } // Update the spots table function updateTable() { // Use local time instead of UTC? var useLocalTime = $("#timeZone")[0].value == "local"; // Get user grid if valid, this will be null if it's not. var userPos = latLonForGridCentre($("#userGrid").val()); // Table data toggles var showTime = $("#tableShowTime")[0].checked; var showDX = $("#tableShowDX")[0].checked; var showFreq = $("#tableShowFreq")[0].checked; var showMode = $("#tableShowMode")[0].checked; var showComment = $("#tableShowComment")[0].checked; var showBearing = $("#tableShowBearing")[0].checked && userPos != null; var showSource = $("#tableShowSource")[0].checked; var showRef = $("#tableShowRef")[0].checked; var showDE = $("#tableShowDE")[0].checked; // Populate table with headers let table = $('
| ${useLocalTime ? "Local" : "UTC"} | `); } if (showDX) { table.find('thead tr').append(`DX | `); } if (showFreq) { table.find('thead tr').append(`Frequency | `); } if (showMode) { table.find('thead tr').append(`Mode | `); } if (showComment) { table.find('thead tr').append(`Comment | `); } if (showBearing) { table.find('thead tr').append(`Bearing | `); } if (showSource) { table.find('thead tr').append(`Source | `); } if (showRef) { table.find('thead tr').append(`Ref. | `); } if (showDE) { table.find('thead tr').append(`DE | `); } if (spots.length == 0) { table.find('tbody').append('|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| No spots match your filters. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ${time_formatted} | `); } if (showDX) { $tr.append(`${s["dx_call"]} | `); } if (showFreq) { $tr.append(`■${freq_string} | `); } if (showMode) { $tr.append(`${mode_string} | `); } if (showComment) { $tr.append(`${commentText} | `); } if (showBearing) { $tr.append(``); } if (showSource) { $tr.append(``); } if (showRef) { $tr.append(`${sig_refs} | `); } if (showDE) { $tr.append(``); } table.find('tbody').append($tr); // Second row for mobile view only, containing source, ref & comment $tr2 = $("||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ");
if (showSource) {
$td2.append(` ${sigSourceText} `);
}
if (showRef) {
$td2.append(`${sig_refs} `);
}
if (showBearing) {
$td2.append(` Bearing: ${bearingText} `);
}
if (showComment) {
$td2.append(` ${commentText}`); } $tr2.append($td2); table.find('tbody').append($tr2); }); // Update DOM $('#table-container').html(table); } // Load server options. Once a successful callback is made from this, we then query spots and set up the timer to query // spots repeatedly. function loadOptions() { $.getJSON('/api/v1/options', function(jsonData) { // Store options options = jsonData; // Add CSS for band toggle buttons addBandToggleColourCSS(options["bands"]); // Populate the filters panel generateBandsMultiToggleFilterCard(options["bands"]); generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]); generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]); generateMultiToggleFilterCard("#mode-options", "mode_type", options["mode_types"]); generateMultiToggleFilterCard("#source-options", "source", options["spot_sources"]); // Load settings from settings storage now all the controls are available loadSettings(); // Extra setting - the toggle for the "bearing" column is disabled if the user has not entered a valid grid, and // normally this logic is handled on user input to the grid field, but we might have just loaded a value direct // into the field, so apply the same logic here. $("#tableShowBearing").prop('disabled', !isUserGridValid()); if (!isUserGridValid()) { $("#tableShowBearing").prop('checked', false); } // Show the Add Spot button if spotting is allowed if (options["spot_allowed"]) { $("#add-spot-button").show(); } // Load spots and set up the timer loadSpots(); setInterval(loadSpots, REFRESH_INTERVAL_SEC * 1000); }); } // Work out if the user's entered grid is a valid Maidenhead grid function isUserGridValid() { userGrid = $("#userGrid").val().toUpperCase(); return latLonForGridCentre(userGrid) != null; } // Method called when the user's grid input is changed. function userGridUpdated() { var userGridValid = isUserGridValid(); if (userGridValid) { updateTable(); } // Enable/disable bearing column depending on grid validity $("#tableShowBearing").prop('disabled', !userGridValid); if (!userGridValid) { $("#tableShowBearing").prop('checked', false); } // Save settings even if not a valid grid, this allows the user to clear their grid and have it save. saveSettings(); } // Method called to add a spot to the server function addSpot() { try { var dx = $("#add-spot-dx-call").val().toUpperCase(); var freqStr = $("#add-spot-freq").val(); var mode = $("#add-spot-mode").val().toUpperCase(); var comment = $("#add-spot-comment").val(); var de = $("#add-spot-de-call").val().toUpperCase(); var spot = {} if (dx != "") { spot["dx_call"] = dx; } else { showAddSpotError("A DX callsign is required in order to spot."); return; } if (freqStr != "") { spot["freq"] = parseFloat(freqStr) * 1000; } else { showAddSpotError("A frequency is required in order to spot."); return; } if (mode != "") { spot["mode"] = mode; } if (comment != "") { spot["comment"] = comment; } if (de != "") { spot["de_call"] = de; } spot["time"] = moment.utc().valueOf() / 1000.0; $.ajax("/api/v1/spot", { data : JSON.stringify(spot), contentType : 'application/json', type : 'POST', timeout: 10000, success: async function (result) { $("#post-spot-result-good").html(""); setTimeout(() => $("#post-spot-result-good").hide(), 2000); loadSpots(); }, error: function (result) { showAddSpotError(result.responseText); } }); } catch (error) { showAddSpotError(error); } return false; } // Show an "add spot" error. function showAddSpotError(text) { $("#post-spot-result-bad").html(" " + text + " ");
}
// React to toggling/closing panels
function toggleFiltersPanel() {
// If we are going to show the filters panel, hide the display and add spot panels
if (!$("#filters-area").is(":visible") && $("#display-area").is(":visible")) {
$("#display-area").hide();
$("#display-button").button("toggle");
}
if (!$("#filters-area").is(":visible") && $("#add-spot-area").is(":visible")) {
$("#add-spot-area").hide();
$("#add-spot-button").button("toggle");
}
$("#filters-area").toggle();
}
function closeFiltersPanel() {
$("#filters-button").button("toggle");
$("#filters-area").hide();
}
function toggleDisplayPanel() {
// If we are going to show the display panel, hide the filters and add spot panels
if (!$("#display-area").is(":visible") && $("#filters-area").is(":visible")) {
$("#filters-area").hide();
$("#filters-button").button("toggle");
}
if (!$("#display-area").is(":visible") && $("#add-spot-area").is(":visible")) {
$("#add-spot-area").hide();
$("#add-spot-button").button("toggle");
}
$("#display-area").toggle();
}
function closeDisplayPanel() {
$("#display-button").button("toggle");
$("#display-area").hide();
}
function toggleAddSpotPanel() {
// If we are going to show the add spot panel, hide the filters and display panels
if (!$("#add-spot-area").is(":visible") && $("#filters-area").is(":visible")) {
$("#filters-area").hide();
$("#filters-button").button("toggle");
}
if (!$("#add-spot-area").is(":visible") && $("#display-area").is(":visible")) {
$("#display-area").hide();
$("#display-button").button("toggle");
}
$("#add-spot-area").toggle();
}
function closeAddSpotPanel() {
$("#add-spot-button").button("toggle");
$("#add-spot-area").hide();
}
// Display the intro box, unless the user has already dismissed it once.
function displayIntroBox() {
if (localStorage.getItem("intro-box-dismissed") == null) {
$("#intro-box").show();
}
$("#intro-box-dismiss").click(function() {
localStorage.setItem("intro-box-dismissed", true);
});
}
// Startup
$(document).ready(function() {
// Call loadOptions(), this will then trigger loading spots and setting up timers.
loadOptions();
// Update the refresh timing display every second
setInterval(updateRefreshDisplay, 1000);
// Display intro box
displayIntroBox();
}); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||