Files
dv3d/dicom-viewer/public/load-dir-test.html
T

197 lines
7.5 KiB
HTML

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Load Directory Test</title>
<style>
body { font-family: system-ui, Arial; padding: 18px; background: #f6f6f8; color: #111 }
.controls { margin: 12px 0 }
.file-row { display:flex; gap:8px; align-items:center; padding:6px 8px; border-bottom:1px solid #eee }
.path { font-family: monospace; color:#444; flex:1 }
button { padding:6px 10px }
#fileList { border:1px solid #ddd; background:#fff; border-radius:6px; max-height:60vh; overflow:auto }
</style>
</head>
<body>
<h2>Directory Loader (recursive)</h2>
<p>Select a folder (uses `webkitdirectory`) — files will be read recursively.
This page will call <code>window.loadDicomStackFromFiles(files)</code> if available in the viewer.</p>
<div class="controls">
<input id="dirInput" type="file" webkitdirectory directory multiple />
<label style="margin-left:12px"><input id="onlyDcm" type="checkbox" checked /> Show only <code>.dcm</code></label>
<button id="loadSelected">Load Selected</button>
<button id="loadAll">Load All</button>
<button id="openViewerAndSend">Open Viewer & Send</button>
<button id="clear">Clear</button>
</div>
<div id="fileList"></div>
<script>
(function(){
const input = document.getElementById('dirInput');
const fileListDiv = document.getElementById('fileList');
const onlyDcmChk = document.getElementById('onlyDcm');
function asArray(fileList){ return Array.prototype.slice.call(fileList || []); }
function renderFiles(files){
fileListDiv.innerHTML = '';
if (!files || files.length === 0) {
fileListDiv.innerHTML = '<div style="padding:12px;color:#666">No files selected</div>';
return;
}
const frag = document.createDocumentFragment();
files.forEach((f, idx) => {
const row = document.createElement('div');
row.className = 'file-row';
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.checked = true;
cb.dataset.idx = idx;
const pathEl = document.createElement('div');
pathEl.className = 'path';
// webkitRelativePath shows the folder structure when directory input used
pathEl.textContent = f.webkitRelativePath || f.name;
const sizeEl = document.createElement('div');
sizeEl.style.width = '90px';
sizeEl.style.textAlign = 'right';
sizeEl.style.color = '#666';
sizeEl.textContent = (f.size/1024).toFixed(1)+' kB';
row.appendChild(cb);
row.appendChild(pathEl);
row.appendChild(sizeEl);
frag.appendChild(row);
});
fileListDiv.appendChild(frag);
}
function filterFiles(files){
const onlyDcm = onlyDcmChk.checked;
if (!onlyDcm) return files;
return files.filter(f => f.name.toLowerCase().endsWith('.dcm'));
}
input.addEventListener('change', ()=>{
const all = asArray(input.files);
const filtered = filterFiles(all);
// Save filtered list on the element for retrieval
input._currentFiles = filtered;
renderFiles(filtered);
});
document.getElementById('loadSelected').addEventListener('click', ()=>{
const current = input._currentFiles || [];
if (!current.length) return alert('No files selected. Choose a folder first.');
// collect checked indices
const checked = Array.from(fileListDiv.querySelectorAll('input[type=checkbox]'))
.filter(cb=>cb.checked)
.map(cb=>parseInt(cb.dataset.idx,10))
.filter(n=>!Number.isNaN(n));
const chosen = checked.map(i=>current[i]).filter(Boolean);
if (!chosen.length) return alert('No files checked.');
sendToViewer(chosen);
});
document.getElementById('loadAll').addEventListener('click', ()=>{
const current = input._currentFiles || [];
if (!current.length) return alert('No files selected. Choose a folder first.');
sendToViewer(current);
});
document.getElementById('openViewerAndSend').addEventListener('click', async ()=>{
const current = input._currentFiles || [];
if (!current.length) return alert('No files selected. Choose a folder first.');
// Open the viewer root in a new tab/window
const viewerWin = window.open('/', '_blank');
if (!viewerWin) return alert('Failed to open viewer window (popup blocked).');
// Wait for the viewer window to expose loadDicomStackFromFiles
const timeoutMs = 15000;
const start = Date.now();
const poll = () => new Promise((resolve, reject) => {
const iv = setInterval(() => {
try {
if (viewerWin && (viewerWin.loadDicomStackFromFiles || viewerWin.loadDicomStackFromWadouriList)) {
clearInterval(iv);
resolve(true);
}
if (Date.now() - start > timeoutMs) {
clearInterval(iv);
reject(new Error('Timed out waiting for viewer API'));
}
} catch (e) {
// cross-origin or not ready
}
}, 250);
});
try {
await poll();
// call the function on the opened viewer window
if (viewerWin.loadDicomStackFromFiles) {
viewerWin.loadDicomStackFromFiles(current);
alert('Sent '+current.length+' file(s) to the newly opened viewer.');
} else if (viewerWin.loadDicomStackFromWadouriList) {
// fallback for remote URLs
const wadouriList = current.map(f => 'wadouri:' + URL.createObjectURL(f));
viewerWin.loadDicomStackFromWadouriList(wadouriList);
alert('Sent '+current.length+' wadouri image(s) to the newly opened viewer.');
} else {
alert('Viewer opened but API not available.');
}
} catch (e) {
console.error('openViewerAndSend failed', e);
alert('Timed out waiting for viewer to be ready. Check the viewer tab.');
}
});
document.getElementById('clear').addEventListener('click', ()=>{
input.value = null;
input._currentFiles = [];
renderFiles([]);
});
function sendToViewer(files){
// Prefer calling the viewer global if present
if (window.loadDicomStackFromFiles && typeof window.loadDicomStackFromFiles === 'function') {
try {
// The viewer accepts FileList or File[] per typing; pass array
window.loadDicomStackFromFiles(files);
alert('Sent '+files.length+' file(s) to viewer (window.loadDicomStackFromFiles).');
return;
} catch (e) {
console.error('loadDicomStackFromFiles failed', e);
alert('Viewer call failed (see console).');
return;
}
}
// Fallback: try posting to parent (if embedded)
if (window.parent && window.parent !== window) {
try {
window.parent.postMessage({ type: 'loadFiles', filesCount: files.length }, '*');
alert('Posted message to parent with '+files.length+' files.');
return;
} catch (e) {
// ignore
}
}
alert('Viewer integration function `window.loadDicomStackFromFiles` not found on this page.');
}
// Initial empty render
renderFiles([]);
})();
</script>
</body>
</html>