fix(interactive-diagram): resolve race condition with SVG contentDocument loading

This commit is contained in:
TheFlow 2025-10-26 12:23:55 +13:00
parent 242bd8575c
commit 427b50993b

View file

@ -138,7 +138,6 @@ class InteractiveDiagram {
const svgDoc = objectElement.contentDocument; const svgDoc = objectElement.contentDocument;
if (!svgDoc) { if (!svgDoc) {
console.warn('[InteractiveDiagram] Could not access SVG contentDocument, retrying...'); console.warn('[InteractiveDiagram] Could not access SVG contentDocument, retrying...');
// Retry after a short delay
setTimeout(initializeSVG, 100); setTimeout(initializeSVG, 100);
return; return;
} }
@ -159,7 +158,9 @@ class InteractiveDiagram {
// Verify it's actually an SVG element (case-insensitive check) // Verify it's actually an SVG element (case-insensitive check)
const tagName = svg.tagName ? svg.tagName.toLowerCase() : ''; const tagName = svg.tagName ? svg.tagName.toLowerCase() : '';
if (tagName !== 'svg') { 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; return;
} }
@ -177,13 +178,11 @@ class InteractiveDiagram {
nodes.forEach(node => { nodes.forEach(node => {
const serviceId = node.getAttribute('data-service'); 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) => { node.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
console.log(`[InteractiveDiagram] Clicked service: ${serviceId}`);
this.showServiceDetails(serviceId); this.showServiceDetails(serviceId);
}, true); }, true);
@ -191,10 +190,10 @@ class InteractiveDiagram {
node.addEventListener('touchstart', (e) => { node.addEventListener('touchstart', (e) => {
e.preventDefault(); e.preventDefault();
const serviceId = node.getAttribute('data-service'); const serviceId = node.getAttribute('data-service');
console.log(`[InteractiveDiagram] Touch service: ${serviceId}`);
this.showServiceDetails(serviceId); this.showServiceDetails(serviceId);
}, { passive: false }); }, { passive: false });
// Hover effects
node.addEventListener('mouseenter', () => { node.addEventListener('mouseenter', () => {
this.highlightService(serviceId); this.highlightService(serviceId);
}); });
@ -214,24 +213,59 @@ class InteractiveDiagram {
console.log('[InteractiveDiagram] Setup complete, showing overview'); console.log('[InteractiveDiagram] Setup complete, showing overview');
}; };
// Try multiple approaches to ensure SVG loads // FIXED: Better load detection with SVG verification
if (objectElement.contentDocument && objectElement.contentDocument.readyState === 'complete') { const checkAndInit = () => {
// Object already loaded and ready const svgDoc = objectElement.contentDocument;
console.log('[InteractiveDiagram] Object already loaded, initializing immediately');
initializeSVG(); // Check if contentDocument exists and is actually SVG
} else { if (svgDoc && svgDoc.documentElement) {
// Wait for load event 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...'); console.log('[InteractiveDiagram] Waiting for object to load...');
objectElement.addEventListener('load', () => { objectElement.addEventListener('load', () => {
console.log('[InteractiveDiagram] Object loaded event fired'); console.log('[InteractiveDiagram] Object load event fired');
initializeSVG(); // 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 // Also try periodic checks as fallback
setTimeout(initializeSVG, 500); 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) { highlightService(serviceId) {
if (!this.svg) return; if (!this.svg) return;