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;
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;