diff --git a/public/js/components/interactive-diagram.js b/public/js/components/interactive-diagram.js index d3b69f34..a2efd827 100644 --- a/public/js/components/interactive-diagram.js +++ b/public/js/components/interactive-diagram.js @@ -138,7 +138,6 @@ class InteractiveDiagram { const svgDoc = objectElement.contentDocument; if (!svgDoc) { console.warn('[InteractiveDiagram] Could not access SVG contentDocument, retrying...'); - // Retry after a short delay setTimeout(initializeSVG, 100); return; } @@ -159,7 +158,9 @@ class InteractiveDiagram { // Verify it's actually an SVG element (case-insensitive check) const tagName = svg.tagName ? svg.tagName.toLowerCase() : ''; if (tagName !== 'svg') { - console.warn('[InteractiveDiagram] Element found but not SVG, tagName:', tagName); + console.warn('[InteractiveDiagram] Element found but not SVG, tagName:', tagName, '- retrying...'); + // This is the race condition - contentDocument is HTML, not SVG yet + setTimeout(initializeSVG, 100); return; } @@ -177,13 +178,11 @@ class InteractiveDiagram { 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 + // Click handler node.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); - console.log(`[InteractiveDiagram] Clicked service: ${serviceId}`); this.showServiceDetails(serviceId); }, true); @@ -191,10 +190,10 @@ class InteractiveDiagram { node.addEventListener('touchstart', (e) => { e.preventDefault(); const serviceId = node.getAttribute('data-service'); - console.log(`[InteractiveDiagram] Touch service: ${serviceId}`); this.showServiceDetails(serviceId); }, { passive: false }); + // Hover effects node.addEventListener('mouseenter', () => { this.highlightService(serviceId); }); @@ -214,24 +213,59 @@ class InteractiveDiagram { console.log('[InteractiveDiagram] Setup complete, showing overview'); }; - // 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 { - // Wait for load event + // FIXED: Better load detection with SVG verification + const checkAndInit = () => { + const svgDoc = objectElement.contentDocument; + + // Check if contentDocument exists and is actually SVG + if (svgDoc && svgDoc.documentElement) { + const rootTagName = svgDoc.documentElement.tagName ? svgDoc.documentElement.tagName.toLowerCase() : ''; + + if (rootTagName === 'svg') { + // It's an SVG - safe to initialize + console.log('[InteractiveDiagram] SVG detected in contentDocument, initializing'); + initializeSVG(); + return true; + } else { + console.log('[InteractiveDiagram] contentDocument exists but root is:', rootTagName, '- not ready yet'); + return false; + } + } + return false; + }; + + // Try immediate initialization if already loaded + if (!checkAndInit()) { + // Not ready yet - wait for load event console.log('[InteractiveDiagram] Waiting for object to load...'); + objectElement.addEventListener('load', () => { - console.log('[InteractiveDiagram] Object loaded event fired'); - initializeSVG(); + console.log('[InteractiveDiagram] Object load event fired'); + // Small delay to ensure contentDocument is fully parsed + setTimeout(() => { + if (!checkAndInit()) { + // Still not ready - start retry mechanism + initializeSVG(); + } + }, 50); }); - // Also try after a short delay as fallback - setTimeout(initializeSVG, 500); + // Also try periodic checks as fallback + let retryCount = 0; + const maxRetries = 20; + const retryInterval = setInterval(() => { + retryCount++; + if (checkAndInit() || retryCount >= maxRetries) { + clearInterval(retryInterval); + if (retryCount >= maxRetries) { + console.error('[InteractiveDiagram] Failed to load SVG after', maxRetries, 'retries'); + } + } + }, 100); } } + highlightService(serviceId) { if (!this.svg) return;