From 1fc80b05b11aefcf0bbd0e1d812917c13b396f40 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 12 Apr 2026 21:28:50 +0100 Subject: [PATCH] fix(sensor): replace static NodeList while-loops causing page freeze and removeChild TypeError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four list-trimming loops used querySelectorAll (static NodeList) inside a while condition, so .length never decreased — causing infinite loops that froze the page, or repeated removeChild calls on already-removed nodes (TypeError: parameter 1 is not of type 'Node'). Also replaces blocking alert() with showInfo() for start errors and adds a .catch() handler to the start_sensor fetch so network failures surface cleanly instead of leaving the UI in a broken state. Co-Authored-By: Claude Sonnet 4.6 --- templates/index.html | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/templates/index.html b/templates/index.html index 49eb83a..d810531 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5341,8 +5341,11 @@ // Clear existing output output.innerHTML = ''; } else { - alert('Error: ' + data.message); + showInfo('Error: ' + (data.message || 'Failed to start sensor')); } + }) + .catch(err => { + showInfo('Error starting sensor: ' + err.message); }); } @@ -5580,8 +5583,8 @@ // Keep list manageable const cards = output.querySelectorAll('.signal-card'); - while (cards.length > 100) { - output.removeChild(output.lastChild); + for (let i = cards.length - 1; i >= 100; i--) { + cards[i].remove(); } } @@ -5864,14 +5867,8 @@ // Limit to max 50 unique meters (cards won't pile up since we update in place) const cards = output.querySelectorAll('.signal-card.meter-aggregated'); - while (cards.length > 50) { - // Remove oldest card (last one) - const oldestCard = output.querySelector('.signal-card.meter-aggregated:last-of-type'); - if (oldestCard) { - output.removeChild(oldestCard); - } else { - break; - } + for (let i = cards.length - 1; i >= 50; i--) { + cards[i].remove(); } } @@ -7055,8 +7052,8 @@ // Limit messages displayed (keep placeholder/empty-state) const cards = output.querySelectorAll('.signal-card'); - while (cards.length > 100) { - output.removeChild(cards[cards.length - 1]); + for (let i = cards.length - 1; i >= 100; i--) { + cards[i].remove(); } } @@ -7420,7 +7417,7 @@ // Limit displayed devices while (content.children.length > 50) { - content.removeChild(content.lastChild); + content.lastElementChild.remove(); } } @@ -10707,7 +10704,7 @@ // Keep log manageable while (logEl.children.length > 100) { - logEl.removeChild(logEl.lastChild); + logEl.lastElementChild.remove(); } // Update map if position data