From 94e3d4908d87713ebe09621bf64d15a1164820b7 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Nov 2025 13:08:53 +0000 Subject: [PATCH 1/5] No flooding / remove timer b4 creating new one --- assets/js/dxwaterfall.js | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/assets/js/dxwaterfall.js b/assets/js/dxwaterfall.js index 21a0dae5c..40395da38 100644 --- a/assets/js/dxwaterfall.js +++ b/assets/js/dxwaterfall.js @@ -6273,6 +6273,10 @@ function setFrequency(frequencyInKHz, fromWaterfall) { // Wait for jQuery to be available before initializing (function waitForJQuery() { + // Global timer variable to prevent multiple auto-refresh timers + var autoRefreshTimer = null; + var isInitialized = false; + if (typeof jQuery !== 'undefined') { // jQuery is loaded, proceed with initialization $(document).ready(function() { @@ -6282,16 +6286,32 @@ function setFrequency(frequencyInKHz, fromWaterfall) { // Function to try initializing the canvas with retries function tryInitCanvas() { if (document.getElementById('dxWaterfall')) { + // Prevent multiple initializations + if (isInitialized) { + DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Already initialized, skipping duplicate initialization'); + return; + } + isInitialized = true; + // Canvas found, but DON'T auto-initialize // Wait for user to click the power button + // Clear any existing timer before creating new one + if (autoRefreshTimer) { + clearInterval(autoRefreshTimer); + autoRefreshTimer = null; + DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Cleared existing auto-refresh timer'); + } + // Set up DX spots fetching at regular intervals (only when initialized) - setInterval(function() { + autoRefreshTimer = setInterval(function() { if (dxWaterfall.canvas) { // Only fetch if waterfall has been initialized dxWaterfall.fetchDxSpots(true, false); // Background fetch - NOT user-initiated } }, DX_WATERFALL_CONSTANTS.DEBOUNCE.DX_SPOTS_FETCH_INTERVAL_MS); + DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Auto-refresh timer created with interval: ' + DX_WATERFALL_CONSTANTS.DEBOUNCE.DX_SPOTS_FETCH_INTERVAL_MS + 'ms'); + } else { // Canvas not found, try again in 100ms setTimeout(tryInitCanvas, 100); @@ -6307,6 +6327,15 @@ function setFrequency(frequencyInKHz, fromWaterfall) { dxWaterfall.updateDimensions(); }); + // Cleanup function to prevent memory leaks and multiple timers + $(window).on('beforeunload pagehide', function() { + if (autoRefreshTimer) { + clearInterval(autoRefreshTimer); + autoRefreshTimer = null; + DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Auto-refresh timer cleaned up on page unload'); + } + }); + // Handle click on the cycle icon in dxWaterfallSpotContent div to cycle through spots $('#dxWaterfallSpotContent').on('click', '.cycle-spot-icon', function(e) { e.stopPropagation(); // Prevent event bubbling From 24b462a7d5004705b2b1b055289c66031d878b7d Mon Sep 17 00:00:00 2001 From: Szymon Porwolik Date: Fri, 28 Nov 2025 16:04:20 +0100 Subject: [PATCH 2/5] Let's reset the variable on turning off --- assets/js/dxwaterfall.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/dxwaterfall.js b/assets/js/dxwaterfall.js index 40395da38..18ecb4828 100644 --- a/assets/js/dxwaterfall.js +++ b/assets/js/dxwaterfall.js @@ -6923,6 +6923,7 @@ function setFrequency(frequencyInKHz, fromWaterfall) { } waterfallActive = false; + isInitialized = false; // Reset so waterfall can be turned on again // Log user action DX_WATERFALL_UTILS.log.debug('[Power Control] User turned OFF waterfall'); From 4029ca9a9c09bcd8f01f918ee429f94898e16b9f Mon Sep 17 00:00:00 2001 From: Szymon Porwolik Date: Fri, 28 Nov 2025 16:24:42 +0100 Subject: [PATCH 3/5] Band shall base on frequency field, when CAT is not available --- assets/js/dxwaterfall.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/assets/js/dxwaterfall.js b/assets/js/dxwaterfall.js index 18ecb4828..303d118d3 100644 --- a/assets/js/dxwaterfall.js +++ b/assets/js/dxwaterfall.js @@ -3526,15 +3526,27 @@ var dxWaterfall = { }); }, - // Get current band from form or default to 20m + // Get current band calculated from frequency (single source of truth) getCurrentBand: function() { - // Safety check: return default if not initialized - if (!this.$bandSelect) { - return '20m'; + var freqHz = 0; + + // When CAT is operational, use CAT frequency + if (window.catState && window.catState.frequency && window.catState.frequency > 0) { + freqHz = window.catState.frequency; + } else if (this.$frequency) { + // When offline, read directly from hidden frequency field (single source of truth) + freqHz = parseFloat(this.$frequency.val()) || 0; } - // Try to get band from form - adjust selector based on your HTML structure - var band = this.$bandSelect.val() || '20m'; - return band; + + if (freqHz > 0) { + var freqKhz = freqHz / 1000; + var band = frequencyToBandKhz(freqKhz); + if (band && band !== '' && band.toLowerCase() !== 'select') { + return band; + } + } + // Fallback to 20m if frequency not available or out of band + return '20m'; }, // Get current mode from form or default to All From b510bd7fe177ee4201186c100c1930d499d34d0c Mon Sep 17 00:00:00 2001 From: Szymon Porwolik Date: Fri, 28 Nov 2025 20:09:54 +0100 Subject: [PATCH 4/5] Cat triggering dxwaterfall --- assets/js/cat.js | 4 ++-- assets/js/dxwaterfall.js | 44 +++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/assets/js/cat.js b/assets/js/cat.js index 95ec23bea..a78d0938a 100644 --- a/assets/js/cat.js +++ b/assets/js/cat.js @@ -819,8 +819,8 @@ $(document).ready(function() { } // Notify DX Waterfall of mode change for sideband display update - // Only refresh if mode actually changed (not on initial undefined → value transition) - if (modeChanged && typeof dxWaterfall !== 'undefined' && dxWaterfall.refresh) { + // Only refresh if mode actually changed AND waterfall is active (has canvas) + if (modeChanged && typeof dxWaterfall !== 'undefined' && dxWaterfall.canvas && dxWaterfall.refresh) { // Update virtual CAT state if (typeof window.catState !== 'undefined' && window.catState !== null) { window.catState.mode = newMode; diff --git a/assets/js/dxwaterfall.js b/assets/js/dxwaterfall.js index 303d118d3..e3e087973 100644 --- a/assets/js/dxwaterfall.js +++ b/assets/js/dxwaterfall.js @@ -32,7 +32,7 @@ var DX_WATERFALL_CONSTANTS = { VERSION: '0.9.6', // DX Waterfall version (keep in sync with @version in file header) // Debug and logging - DEBUG_MODE: false, // Set to true for verbose logging, false for production + DEBUG_MODE: true, // Set to true for verbose logging, false for production // Timing and debouncing DEBOUNCE: { @@ -4659,12 +4659,9 @@ var dxWaterfall = { // Update last refresh time this.lastRefreshTime = Date.now(); - // Ensure canvas is initialized + // Ensure canvas is initialized - don't auto-init, just return if (!this.canvas) { - this.init(); - if (!this.canvas) { - return; // Canvas not available, abort - } + return; // Canvas not available, user must click power button } // Check if canvas is visible in DOM @@ -6307,22 +6304,7 @@ function setFrequency(frequencyInKHz, fromWaterfall) { // Canvas found, but DON'T auto-initialize // Wait for user to click the power button - - // Clear any existing timer before creating new one - if (autoRefreshTimer) { - clearInterval(autoRefreshTimer); - autoRefreshTimer = null; - DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Cleared existing auto-refresh timer'); - } - - // Set up DX spots fetching at regular intervals (only when initialized) - autoRefreshTimer = setInterval(function() { - if (dxWaterfall.canvas) { // Only fetch if waterfall has been initialized - dxWaterfall.fetchDxSpots(true, false); // Background fetch - NOT user-initiated - } - }, DX_WATERFALL_CONSTANTS.DEBOUNCE.DX_SPOTS_FETCH_INTERVAL_MS); - - DX_WATERFALL_UTILS.log.debug('[DX Waterfall] Auto-refresh timer created with interval: ' + DX_WATERFALL_CONSTANTS.DEBOUNCE.DX_SPOTS_FETCH_INTERVAL_MS + 'ms'); + // Auto-refresh timer will be created when waterfall is turned on } else { // Canvas not found, try again in 100ms @@ -6895,13 +6877,23 @@ function setFrequency(frequencyInKHz, fromWaterfall) { // Show waiting message dxWaterfall.displayWaitingMessage(lang_dxwaterfall_please_wait); - // Set up periodic refresh interval + // Set up periodic refresh interval for visual updates waterfallRefreshInterval = setInterval(function() { if (dxWaterfall.canvas) { dxWaterfall.refresh(); } }, DX_WATERFALL_CONSTANTS.VISUAL.STATIC_NOISE_REFRESH_MS); + // Set up DX spots fetching at regular intervals + if (autoRefreshTimer) { + clearInterval(autoRefreshTimer); + } + autoRefreshTimer = setInterval(function() { + if (dxWaterfall.canvas) { + dxWaterfall.fetchDxSpots(true, false); // Background fetch + } + }, DX_WATERFALL_CONSTANTS.DEBOUNCE.DX_SPOTS_FETCH_INTERVAL_MS); + // Add 3 second delay before initializing (allows page to stabilize) initializationDelayTimer = setTimeout(function() { if (DXWaterfallStateMachine.getState() === DX_WATERFALL_CONSTANTS.STATES.INITIALIZING) { @@ -6953,6 +6945,12 @@ function setFrequency(frequencyInKHz, fromWaterfall) { waterfallRefreshInterval = null; } + // Stop the auto-refresh timer for DX spots + if (autoRefreshTimer) { + clearInterval(autoRefreshTimer); + autoRefreshTimer = null; + } + // Destroy the waterfall component (handles cleanup of memory, timers, event handlers, and DOM refs) if (typeof dxWaterfall !== 'undefined' && dxWaterfall.canvas) { dxWaterfall.destroy(); From 233eac2e128dad18341fb5a35ac9ed8e7b023257 Mon Sep 17 00:00:00 2001 From: Szymon Porwolik Date: Fri, 28 Nov 2025 20:36:48 +0100 Subject: [PATCH 5/5] Debug off --- assets/js/dxwaterfall.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/dxwaterfall.js b/assets/js/dxwaterfall.js index e3e087973..5dfc3f72f 100644 --- a/assets/js/dxwaterfall.js +++ b/assets/js/dxwaterfall.js @@ -32,7 +32,7 @@ var DX_WATERFALL_CONSTANTS = { VERSION: '0.9.6', // DX Waterfall version (keep in sync with @version in file header) // Debug and logging - DEBUG_MODE: true, // Set to true for verbose logging, false for production + DEBUG_MODE: false, // Set to true for verbose logging, false for production // Timing and debouncing DEBOUNCE: {