* Virtual Display Manager
* Drop-in helper to manage multiple full-page views within a single browser
tab.
*/
class VirtualDisplayManager {
constructor() {
this.displays = new Map(); // Stores our virtual displays
this.activeDisplayId = 'default'; // 'default' is the underlying original
DOM
this._initDOM(); }
// --- Private setup methods ---
_initDOM() {
// 1. Inject necessary CSS safely
const styleId = 'v-display-manager-styles';
if (!document.getElementById(styleId)) {
const style = document.createElement('style');
style.id = styleId;
style.textContent = `
#v-display-root {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
width: 100vw; height: 100vh;
z-index: 999999; /* Sit on top of the default DOM */
background: #ffffff; /* Default background */
display: none; /* Hidden by default */
}
#v-display-root.is-active {
display: block;
}
.v-display-view {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
display: none; /* Hide all views by default */
overflow-y: auto; /* Allow scrolling within the view */
background: #ffffff;
}
.v-display-view.is-active {
display: block; /* Only show the active one */
}
`;
document.head.appendChild(style);
}
// 2. Create the master container for all virtual displays
if (!document.getElementById('v-display-root')) {
this.rootContainer = document.createElement('div');
this.rootContainer.id = 'v-display-root';
document.body.appendChild(this.rootContainer);
} else {
this.rootContainer = document.getElementById('v-display-root');
} }
// --- Public API ---
/**
* Register a new virtual display.
* @param {string} id - Unique name for the display
* @param {HTMLElement|string} content - DOM Element or HTML string
*/
add(id, content) { if (id === 'default') {
console.warn('Cannot overwrite the "default" display.'); return;
}
// If it already exists, remove the old one first
if (this.displays.has(id)) { this.remove(id); }
const viewWrapper = document.createElement('div');
viewWrapper.className = 'v-display-view';
viewWrapper.dataset.displayId = id;
// Append content
if (typeof content === 'string') {
viewWrapper.innerHTML = content;
} else if (content instanceof HTMLElement) { viewWrapper.appendChild(c
ontent); } this.rootContainer.appendChild(viewWrapper);
this.displays.set(id, viewWrapper);
return viewWrapper; }
/**
* Delete a virtual display.
* @param {string} id
*/
remove(id) { if (!this.displays.has(id)) return;
const viewWrapper = this.displays.get(id);
if (viewWrapper && viewWrapper.parentNode) { viewWrapper.parentNode.removeC
hild(viewWrapper); }
this.displays.delete(id);
// If we just deleted the active display, fallback to default
if (this.activeDisplayId === id) { this.switchTo('default'); } }
/**
* Switch the visible display.
* @param {string} id - The ID to switch to, or 'default'
*/
switchTo(id) {
if (id !== 'default' && !this.displays.has(id)) { console.error(`Display
"${id}" not found.`); return; }
this.activeDisplayId = id;
if (id === 'default') {
// Hide the master container to reveal the original DOM
this.rootContainer.classList.remove('is-active');
// Deactivate all child views just in case
this.displays.forEach(view => view.classList.remove('is-active'));
} else { // Show the master container
this.rootContainer.classList.add('is-active');
// Loop through and only show the requested view
this.displays.forEach((view, key) => {
if (key === id) { view.classList.add('is-active'); } else {
view.classList.remove('is-active'); } }); } }
/**
* List all available displays.
* @returns {Array<string>} Array of display IDs
*/
list() { return ['default', ...Array.from(this.displays.keys())]; }
/**
* Get the currently active display ID.
*/
getCurrent() { return this.activeDisplayId; }
}
/ Export as a global singleton so all scripts share the same manager
window.DisplayManager = new VirtualDisplayManager();