diff --git a/atlas/templates/atlas/case_display_block.html b/atlas/templates/atlas/case_display_block.html index 884a4781..4449701f 100755 --- a/atlas/templates/atlas/case_display_block.html +++ b/atlas/templates/atlas/case_display_block.html @@ -1016,7 +1016,8 @@ let dicomViewerLoaded = false; dicomDetails.addEventListener("toggle", function() { if (!dicomViewerLoaded && dicomDetails.open) { - window.mountDicomViewers(); + // Use safe mount helper to avoid arbitrary timeouts + try { mountDicomViewersSafely(); } catch (e) { if (window.mountDicomViewers) try { window.mountDicomViewers(); } catch (er) { console.warn(er); } } dicomViewerLoaded = true; } }); @@ -1162,25 +1163,23 @@ } else { viewer_element_3d = null; } - // We have a slight delay to allow the viewer to load - setTimeout(function () { - // Then we load the annotation and viewport - window.mountDicomViewers(); - if (load_3d) { - console.log("loading 3d") - - //setTimeout(function () { - // console.log("loading 3d annotation") - // importAnnotations_root(annotationjson3d) - // importViewerState_root(viewerState); - //}, 1000); - } else { - console.log("not loading 3d") + // Initialize viewer deterministically after injecting HTML + (async function(){ + try { + await mountDicomViewersSafely(); + if (load_3d) { + console.log("loading 3d"); + // deferred 3D import can be handled here if needed + } else { + console.log("not loading 3d"); + } + } catch(e){ + console.warn('Viewer init error:', e); } - }, 200); + })(); document.getElementById("reload-finding").addEventListener("click", function () { - window.mountDicomViewers(); + mountDicomViewersSafely(); }); // Initialize the DICOM viewer with the images and annotations @@ -1201,6 +1200,36 @@ const dsFullscreenModal = new bootstrap.Modal(document.getElementById("displaysetFullscreenModal")); // Loader functions: can be called directly on reload + // Helper: wait for mount function and mount the viewers safely + function waitForMountFn(timeout = 5000) { + if (window.mountDicomViewers) return Promise.resolve(window.mountDicomViewers); + return new Promise((resolve, reject) => { + const start = Date.now(); + function poll() { + if (window.mountDicomViewers) return resolve(window.mountDicomViewers); + if (Date.now() - start > timeout) return reject(new Error('mountDicomViewers not available')); + requestAnimationFrame(poll); + } + poll(); + }); + } + + async function mountDicomViewersSafely(timeout = 5000) { + try { + // wait for layout to stabilise + await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); + const mountFn = await waitForMountFn(timeout); + try { mountFn(); } catch (e) { console.warn('mountDicomViewers failed', e); } + // allow any async render to settle then force a resize event + requestAnimationFrame(() => { + try { window.dispatchEvent(new Event('resize')); } catch (e) {} + if (typeof window.resizeDicomViewers === 'function') try { window.resizeDicomViewers(); } catch (e) {} + }); + } catch (err) { + console.warn('Viewer initialization deferred/fallback:', err); + } + } + async function loadDisplaysetModal(url, dsId) { if (!url && dsId) url = `/atlas/${dsId}/display_sets/modal`; if (!url) return; @@ -1217,7 +1246,8 @@ } } catch (e) { console.warn(e); } try { setUrlParam('displayset', dsId); } catch (e) {} - setTimeout(function () { try { window.mountDicomViewers(); } catch (e) { console.warn('mountDicomViewers not available', e); } }, 500); + // Initialize viewer deterministically after injecting HTML + mountDicomViewersSafely(); dsModal.show(); } catch (error) { console.error('Error loading display set details:', error); @@ -1249,7 +1279,8 @@ document.getElementById('displaysetFullscreenRight').innerHTML = tmp.innerHTML; try { if (dsId) { setUrlParam('displayset', dsId); setUrlParam('displayset_full', '1'); } } catch (e) {} dsFullscreenModal.show(); - setTimeout(function () { try { window.mountDicomViewers(); } catch (e) { console.warn('mountDicomViewers not available for fullscreen', e); } }, 500); + // Ensure viewer is mounted and resized after moving into fullscreen + mountDicomViewersSafely(); } catch (error) { console.error('Error loading fullscreen display set:', error); document.getElementById('displaysetFullscreenLeft').innerHTML = '

Failed to load viewer

'; @@ -1266,11 +1297,12 @@ const resp = await fetch(url); const html = await resp.text(); modalBody.innerHTML = html; - setTimeout(function () { try { window.mountDicomViewers(); } catch (e) { console.warn('mountDicomViewers not available', e); } }, 200); + // Ensure viewers mount after content injection + mountDicomViewersSafely(); try { setUrlParam('finding', findingId); } catch (e) {} const modal = new bootstrap.Modal(document.getElementById('findingModal')); modal.show(); - document.getElementById('reload-finding')?.addEventListener('click', function () { window.mountDicomViewers(); }); + document.getElementById('reload-finding')?.addEventListener('click', function () { mountDicomViewersSafely(); }); } catch (e) { console.error('Error loading finding details:', e); modalBody.innerHTML = '

Failed to load finding details.

'; diff --git a/atlas/templates/atlas/case_displaysets.html b/atlas/templates/atlas/case_displaysets.html index c12aa629..11fb2655 100755 --- a/atlas/templates/atlas/case_displaysets.html +++ b/atlas/templates/atlas/case_displaysets.html @@ -38,20 +38,48 @@ {% block js %}