From 5a4f9e2e2027d45efba18c7cf29952881b3899d2 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Sun, 24 Aug 2025 00:06:59 +0200 Subject: [PATCH] Fix source popup closing immediately after opening MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Source markers were being recreated on every WebSocket update (every second), which destroyed any open popups. Solution: Modified updateSourceMarkers() to: - Only remove markers for sources that no longer exist - Update existing markers in-place instead of recreating them - Preserve open popups by updating content instead of recreating markers - Only create new markers when sources are actually added This ensures that clicking on a source marker opens a popup that stays open for user interaction, similar to aircraft popups. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- static/js/app.js | 59 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/static/js/app.js b/static/js/app.js index a94cd9e..5c7fa58 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -333,27 +333,50 @@ class SkyView { } updateSourceMarkers() { - // Clear existing source markers - this.sourceMarkers.forEach(marker => this.map.removeLayer(marker)); - this.sourceMarkers.clear(); + // Remove markers for sources that no longer exist + const currentSourceIds = new Set(this.sourcesData.keys()); + for (const [id, marker] of this.sourceMarkers) { + if (!currentSourceIds.has(id)) { + this.map.removeLayer(marker); + this.sourceMarkers.delete(id); + } + } - // Add source markers + // Update or create markers for current sources for (const [id, source] of this.sourcesData) { if (source.latitude && source.longitude) { - const marker = L.circleMarker([source.latitude, source.longitude], { - radius: source.active ? 10 : 6, - fillColor: source.active ? '#00d4ff' : '#666666', - color: '#ffffff', - weight: 2, - fillOpacity: 0.8, - className: 'source-marker' - }).addTo(this.map); - - marker.bindPopup(this.createSourcePopupContent(source), { - maxWidth: 300 - }); - - this.sourceMarkers.set(id, marker); + if (this.sourceMarkers.has(id)) { + // Update existing marker + const marker = this.sourceMarkers.get(id); + + // Update marker style if status changed + marker.setStyle({ + radius: source.active ? 10 : 6, + fillColor: source.active ? '#00d4ff' : '#666666', + fillOpacity: 0.8 + }); + + // Update popup content if it's open + if (marker.isPopupOpen()) { + marker.setPopupContent(this.createSourcePopupContent(source)); + } + } else { + // Create new marker + const marker = L.circleMarker([source.latitude, source.longitude], { + radius: source.active ? 10 : 6, + fillColor: source.active ? '#00d4ff' : '#666666', + color: '#ffffff', + weight: 2, + fillOpacity: 0.8, + className: 'source-marker' + }).addTo(this.map); + + marker.bindPopup(this.createSourcePopupContent(source), { + maxWidth: 300 + }); + + this.sourceMarkers.set(id, marker); + } } }