/* global debugLog */ // HTMX swap/script-execution configuration and section toggle helpers // Extracted from templates/v3/base.html so browsers cache it as a static asset. // Configure HTMX to evaluate scripts in swapped content and fix insertBefore errors (function() { function setupScriptExecution() { if (document.body) { // Fix HTMX insertBefore errors by validating targets before swap document.body.addEventListener('htmx:beforeSwap', function(event) { try { const target = event.detail.target; if (!target) { console.warn('[HTMX] Target is null, skipping swap'); event.detail.shouldSwap = false; return false; } // Check if target is a valid DOM element if (!(target instanceof Element)) { console.warn('[HTMX] Target is not a valid Element, skipping swap'); event.detail.shouldSwap = false; return false; } // Check if target has a parent node (required for insertBefore) if (!target.parentNode) { console.warn('[HTMX] Target has no parent node, skipping swap'); event.detail.shouldSwap = false; return false; } // Ensure target is in the DOM if (!document.body.contains(target) && !document.head.contains(target)) { console.warn('[HTMX] Target is not in DOM, skipping swap'); event.detail.shouldSwap = false; return false; } // Additional check: ensure parent is also in DOM if (target.parentNode && !document.body.contains(target.parentNode) && !document.head.contains(target.parentNode)) { console.warn('[HTMX] Target parent is not in DOM, skipping swap'); event.detail.shouldSwap = false; return false; } // All checks passed, allow swap return true; } catch (e) { // If validation fails, cancel swap console.warn('[HTMX] Error validating target:', e); event.detail.shouldSwap = false; return false; } }); // Handle HTMX errors gracefully with detailed logging document.body.addEventListener('htmx:responseError', function(event) { const detail = event.detail; const xhr = detail.xhr; const target = detail.target; // Enhanced error logging console.error('HTMX response error:', { status: xhr?.status, statusText: xhr?.statusText, url: xhr?.responseURL, target: target?.id || target?.tagName, responseText: xhr?.responseText }); // For form submissions, log field names only — values // may contain API keys, passwords, or other secrets // that must never reach the console. if (target && target.tagName === 'FORM') { const formData = new FormData(target); const fieldNames = []; for (const [key] of formData.entries()) { fieldNames.push(key); } console.error('Form fields (values redacted):', fieldNames); // Try to parse error response for validation details if (xhr?.responseText) { try { const errorData = JSON.parse(xhr.responseText); console.error('Error details:', { message: errorData.message, details: errorData.details, validation_errors: errorData.validation_errors, context: errorData.context }); } catch { console.error('Error response (non-JSON):', xhr.responseText.substring(0, 500)); } } } }); document.body.addEventListener('htmx:swapError', function(event) { // Log but don't break the app console.warn('HTMX swap error:', event.detail); }); // Execute