197 lines
7.5 KiB
HTML
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>
|