93 lines
1.8 KiB
HTML
93 lines
1.8 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>HTML Viewer</title>
|
|
|
|
<style>
|
|
html, body {
|
|
margin: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #222;
|
|
}
|
|
|
|
body {
|
|
display: flex;
|
|
align-items: stretch;
|
|
justify-content: stretch;
|
|
}
|
|
|
|
#viewer-frame {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
border: 0;
|
|
background: #fff;
|
|
}
|
|
</style>
|
|
|
|
<script type="module">
|
|
import { Subscription_Endpoint } from './subscription.mjs';
|
|
|
|
function get_source_name() {
|
|
const params = new URLSearchParams(location.search);
|
|
return params.get('source') || 'default-html';
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
const viewer_frame = document.getElementById('viewer-frame');
|
|
|
|
const ep = new Subscription_Endpoint();
|
|
await ep.connect('/subscription');
|
|
|
|
const source = get_source_name();
|
|
ep.subscribe(source);
|
|
|
|
let current_url = null;
|
|
let pending_scroll = null;
|
|
|
|
ep.addEventListener('message', (ev) => {
|
|
// Capture current scroll position (best-effort)
|
|
try {
|
|
const win = viewer_frame.contentWindow;
|
|
if (win) {
|
|
pending_scroll = {
|
|
x: win.scrollX,
|
|
y: win.scrollY
|
|
};
|
|
}
|
|
} catch {
|
|
pending_scroll = null;
|
|
}
|
|
|
|
if (current_url) {
|
|
URL.revokeObjectURL(current_url);
|
|
}
|
|
|
|
current_url = URL.createObjectURL(ev.detail);
|
|
viewer_frame.src = current_url;
|
|
});
|
|
|
|
// Restore scroll after the new document loads
|
|
viewer_frame.addEventListener('load', () => {
|
|
if (!pending_scroll) return;
|
|
|
|
try {
|
|
viewer_frame.contentWindow.scrollTo(
|
|
pending_scroll.x,
|
|
pending_scroll.y
|
|
);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
|
|
pending_scroll = null;
|
|
});
|
|
});
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<iframe id="viewer-frame"></iframe>
|
|
</body>
|
|
</html>
|