From f347d0a34e70eba8ce1561bcf76cf3456e143a70 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Fri, 24 Oct 2025 18:22:15 +1300 Subject: [PATCH] fix(architecture): interactive diagram SVG click handler timing issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed non-responsive service node clicks on architecture.html interactive diagram. Root cause: SVG loaded via tag had contentDocument timing issues - event listeners attached before SVG fully accessible. Solution: - Added retry mechanism for contentDocument access (100ms intervals) - Implemented multiple loading strategies (immediate, load event, timeout) - Enabled event capturing phase (addEventListener 3rd param: true) - Enhanced logging for debugging click event flow - Auto-display overview panel on initialization - CSP-compliant cursor styling via JavaScript Deployed to production: https://agenticgovernance.digital/architecture.html 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- public/js/components/interactive-diagram.js | 41 +++++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/public/js/components/interactive-diagram.js b/public/js/components/interactive-diagram.js index f9cf24cf..400de610 100644 --- a/public/js/components/interactive-diagram.js +++ b/public/js/components/interactive-diagram.js @@ -133,11 +133,13 @@ class InteractiveDiagram { return; } - // Wait for object to load + // Wait for object to load with retry mechanism const initializeSVG = () => { const svgDoc = objectElement.contentDocument; if (!svgDoc) { - console.warn('[InteractiveDiagram] Could not access SVG contentDocument'); + console.warn('[InteractiveDiagram] Could not access SVG contentDocument, retrying...'); + // Retry after a short delay + setTimeout(initializeSVG, 100); return; } @@ -168,13 +170,22 @@ class InteractiveDiagram { const nodes = svg.querySelectorAll('.service-node'); console.log(`[InteractiveDiagram] Found ${nodes.length} service nodes`); + if (nodes.length === 0) { + console.warn('[InteractiveDiagram] No service nodes found in SVG'); + return; + } + nodes.forEach(node => { const serviceId = node.getAttribute('data-service'); + console.log(`[InteractiveDiagram] Attaching listeners to service: ${serviceId}`); + // Use event capturing to ensure events are caught node.addEventListener('click', (e) => { e.preventDefault(); + e.stopPropagation(); + console.log(`[InteractiveDiagram] Clicked service: ${serviceId}`); this.showServiceDetails(serviceId); - }); + }, true); node.addEventListener('mouseenter', () => { this.highlightService(serviceId); @@ -183,17 +194,33 @@ class InteractiveDiagram { node.addEventListener('mouseleave', () => { this.unhighlightService(serviceId); }); + + // Add pointer cursor via JavaScript (CSP-compliant) + node.style.cursor = 'pointer'; }); this.addKeyboardNavigation(nodes); + + // Show initial state (overview) + this.showServiceDetails('overview'); + console.log('[InteractiveDiagram] Setup complete, showing overview'); }; - // If object already loaded, initialize immediately - if (objectElement.contentDocument) { + // Try multiple approaches to ensure SVG loads + if (objectElement.contentDocument && objectElement.contentDocument.readyState === 'complete') { + // Object already loaded and ready + console.log('[InteractiveDiagram] Object already loaded, initializing immediately'); initializeSVG(); } else { - // Otherwise wait for load event - objectElement.addEventListener('load', initializeSVG); + // Wait for load event + console.log('[InteractiveDiagram] Waiting for object to load...'); + objectElement.addEventListener('load', () => { + console.log('[InteractiveDiagram] Object loaded event fired'); + initializeSVG(); + }); + + // Also try after a short delay as fallback + setTimeout(initializeSVG, 500); } }