fix(architecture): interactive diagram SVG click handler timing issues

Fixed non-responsive service node clicks on architecture.html interactive diagram.

Root cause: SVG loaded via <object> 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 <noreply@anthropic.com>
This commit is contained in:
TheFlow 2025-10-24 18:22:15 +13:00
parent 0b853c537d
commit f347d0a34e

View file

@ -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);
}
}