From afc383c3d924b16ecd8fcf799be0117a802b231b Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Fri, 3 Oct 2025 13:53:23 +0100 Subject: [PATCH] Persist filters to local storage. Closes #22 --- webassets/js/code.js | 50 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/webassets/js/code.js b/webassets/js/code.js index d2b5231..ee9e426 100644 --- a/webassets/js/code.js +++ b/webassets/js/code.js @@ -185,6 +185,9 @@ function loadOptions() { $("#filters-container-2").append(generateFilterCard("Modes", "mode_type", options["mode_types"])); $("#filters-container-2").append(generateFilterCard("Sources", "source", options["sources"])); + // Load filter settings from settings storage + loadSettings(); + // Load spots and set up the timer loadSpots(); setInterval(loadSpots, REFRESH_INTERVAL_SEC * 1000) @@ -213,7 +216,7 @@ function generateFilterCard(displayName, filterQuery, options) { $card_body.append(`
${displayName}
`); $p = $("

"); options.forEach(o => { - $p.append(` `); + $p.append(` `); }); $card_body.append($p); $card.append($card_body); @@ -232,7 +235,7 @@ function generateBandsFilterCard(displayName, filterQuery, band_options) { // CSS doesn't like IDs with decimal points in, so we need to replace that in the same way as when we originally // queried the options endpoint and set our CSS. var cssFormattedBandName = o['name'] ? o['name'].replace('.', 'p') : "unknown"; - $p.append(` `); + $p.append(` `); }); $card_body.append($p); $card.append($card_body); @@ -240,6 +243,12 @@ function generateBandsFilterCard(displayName, filterQuery, band_options) { return $col; } +// Method called when any filter is changed to reload the spots and persist the filter settings. +function filtersUpdated() { + loadSpots(); + saveSettings(); +} + // Update the refresh timing display function updateRefreshDisplay() { if (lastUpdateTime != null) { @@ -275,14 +284,27 @@ function escapeHtml(str) { return str.replace(/[&<>"'`]/g, escapeCharacter); } -// 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); +// Save settings to local storage +function saveSettings() { + // Find all storeable UI elements, store a key of "element id:property name" mapped to the value of that + // property. For a checkbox, that's the "checked" property. + return $(".storeable-checkbox").each(function() { + localStorage.setItem($(this)[0].id + ":checked", $(this)[0].checked); + }); +} - // Event listeners +// Load settings from local storage and set up the filter selectors +function loadSettings() { + // Find all local storage entries and push their data to the corresponding UI element + Object.keys(localStorage).forEach(function(key) { + // Split the key back into an element ID and a property + var split = key.split(":"); + $("#" + split[0]).prop(split[1], JSON.parse(localStorage.getItem(key))); + }); +} + +// Set up UI element event listeners, after the document is ready +function setUpEventListeners() { $("#status-button").click(function() { // If we are going to display status, load the data for the status panel if (!$("#status-area").is(":visible")) { @@ -301,4 +323,14 @@ $(document).ready(function() { $("#filters-button").button("toggle"); $("#filters-area").hide(); }); +} + +// 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); + // Set up event listeners + setUpEventListeners(); }); \ No newline at end of file