/** * Reliable node/edge inspector: wire Cytoscape mouseover + tap to inspector-focus-store. * Complements dash-cytoscape props (clearOnUnhover=false) for fewer missed hovers. */ (function () { function isLiveCy(cy) { return cy && typeof cy.destroyed === "function" && !cy.destroyed(); } function cyOf(el) { if (!el) return null; if (isLiveCy(el._cytoscape)) return el._cytoscape; // cytoscape.js registers the live instance on its container as _cyreg.cy if (el._cyreg && isLiveCy(el._cyreg.cy)) return el._cyreg.cy; return null; } function findCy(host) { if (!host) return null; let cy = cyOf(host); if (cy) return cy; for (const el of host.querySelectorAll("div")) { cy = cyOf(el); if (cy) return cy; } return null; } function setInspector(data) { if ( window.dash_clientside && typeof window.dash_clientside.set_props === "function" ) { window.dash_clientside.set_props("inspector-focus-store", { data: data }); } } function wireGraph(host) { const cy = findCy(host); if (!cy) return false; if (host.__infoBridgeCy === cy) return true; host.__infoBridgeCy = cy; cy.on("mouseover", "node, edge", (evt) => { if (evt.target === cy) return; setInspector(evt.target.data()); }); cy.on("tap", "node, edge", (evt) => { if (evt.target === cy) return; setInspector(evt.target.data()); }); return true; } function boot() { const host = document.getElementById("graph"); if (!host) return; if (!wireGraph(host)) { host.__infoBridgeCy = null; } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", boot); } else { boot(); } setInterval(boot, 800); })();