fix(js): resolve ESLint no-undef warnings across 6 JS files

Three distinct patterns:

1. Vendor library globals — htmx is injected by <script> before these
   extension files load; ESLint lints files in isolation and doesn't know.
   Fix: add /* global htmx */ to htmx-sse.js and htmx-json-enc.js.

2. Cross-file globals — showNotification is defined as window.showNotification
   in app.js/notification.js but called bare in app.js and error_handler.js.
   ESLint doesn't connect window.X = Y with a bare call to X.
   Fix: add /* global showNotification */ to app.js and error_handler.js.

3. Forward-reference window.* functions — in array-table.js, checkbox-group.js,
   and custom-feeds.js, functions like removeArrayTableRow are called early
   inside event-handler closures but assigned to window.* later in the file.
   At runtime this works (the handler fires after the assignment), but ESLint
   sees the bare name at the call site.
   Fix: change bare calls to window.removeArrayTableRow(this) etc. so the
   reference is explicit and ESLint-safe.

Also guard the updateSystemStats call in app.js reconnectSSE: the function
is called but defined nowhere in the codebase. Guard with typeof check so
it won't throw ReferenceError if the reconnect path is hit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-05-14 10:54:05 -04:00
parent ac32759056
commit 97d798b471
7 changed files with 12 additions and 8 deletions

View File

@@ -1,3 +1,4 @@
/* global showNotification */
// LED Matrix v3 JavaScript // LED Matrix v3 JavaScript
// Additional helpers for HTMX and Alpine.js integration // Additional helpers for HTMX and Alpine.js integration
@@ -57,7 +58,7 @@ window.reconnectSSE = function() {
window.statsSource = new EventSource('/api/v3/stream/stats'); window.statsSource = new EventSource('/api/v3/stream/stats');
window.statsSource.onmessage = function(event) { window.statsSource.onmessage = function(event) {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
updateSystemStats(data); if (typeof updateSystemStats === 'function') updateSystemStats(data);
}; };
} }

View File

@@ -1,3 +1,4 @@
/* global htmx */
htmx.defineExtension('json-enc', { htmx.defineExtension('json-enc', {
onEvent: function (name, evt) { onEvent: function (name, evt) {
if (name === "htmx:configRequest") { if (name === "htmx:configRequest") {

View File

@@ -1,3 +1,4 @@
/* global htmx */
/* /*
Server Sent Events Extension Server Sent Events Extension
============================ ============================

View File

@@ -1,6 +1,7 @@
/* global showNotification */
/** /**
* Frontend error handling utilities. * Frontend error handling utilities.
* *
* Provides user-friendly error formatting and display with enhanced UI. * Provides user-friendly error formatting and display with enhanced UI.
*/ */

View File

@@ -179,7 +179,7 @@
const removeButton = document.createElement('button'); const removeButton = document.createElement('button');
removeButton.type = 'button'; removeButton.type = 'button';
removeButton.className = 'text-red-600 hover:text-red-800 px-2 py-1'; removeButton.className = 'text-red-600 hover:text-red-800 px-2 py-1';
removeButton.onclick = function() { removeArrayTableRow(this); }; removeButton.onclick = function() { window.removeArrayTableRow(this); };
const removeIcon = document.createElement('i'); const removeIcon = document.createElement('i');
removeIcon.className = 'fas fa-trash'; removeIcon.className = 'fas fa-trash';
removeButton.appendChild(removeIcon); removeButton.appendChild(removeIcon);

View File

@@ -75,7 +75,7 @@
}); });
// Update hidden input // Update hidden input
updateCheckboxGroupData(fieldId); window.updateCheckboxGroupData(fieldId);
}, },
handlers: { handlers: {

View File

@@ -142,7 +142,7 @@
fileInput.dataset.index = String(index); fileInput.dataset.index = String(index);
fileInput.addEventListener('change', function(e) { fileInput.addEventListener('change', function(e) {
const idx = parseInt(e.target.dataset.index || '0', 10); const idx = parseInt(e.target.dataset.index || '0', 10);
handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey); window.handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey);
}); });
const uploadButton = document.createElement('button'); const uploadButton = document.createElement('button');
@@ -207,7 +207,7 @@
removeButton.type = 'button'; removeButton.type = 'button';
removeButton.className = 'text-red-600 hover:text-red-800 px-2 py-1'; removeButton.className = 'text-red-600 hover:text-red-800 px-2 py-1';
removeButton.addEventListener('click', function() { removeButton.addEventListener('click', function() {
removeCustomFeedRow(this); window.removeCustomFeedRow(this);
}); });
const removeIcon = document.createElement('i'); const removeIcon = document.createElement('i');
removeIcon.className = 'fas fa-trash'; removeIcon.className = 'fas fa-trash';
@@ -290,7 +290,7 @@
fileInput.dataset.index = String(newIndex); fileInput.dataset.index = String(newIndex);
fileInput.addEventListener('change', function(e) { fileInput.addEventListener('change', function(e) {
const idx = parseInt(e.target.dataset.index || '0', 10); const idx = parseInt(e.target.dataset.index || '0', 10);
handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey); window.handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey);
}); });
const uploadButton = document.createElement('button'); const uploadButton = document.createElement('button');
@@ -449,7 +449,7 @@
fileInput.dataset.index = String(index); fileInput.dataset.index = String(index);
fileInput.addEventListener('change', function(e) { fileInput.addEventListener('change', function(e) {
const idx = parseInt(e.target.dataset.index || '0', 10); const idx = parseInt(e.target.dataset.index || '0', 10);
handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey); window.handleCustomFeedLogoUpload(e, fieldId, idx, pluginId, fullKey);
}); });
// Create upload button // Create upload button