// ES6 Compliant Syntax
// GitHub Copilot, Claude Sonnet 4 (Preview), October 16, 2025
// File: showcase-demos/side-by-side/ui-elements.js
class UIElements {
static init(viewerId) {
this.createSidePanel(viewerId);
this.setupEventHandlers();
}
// Function to create a side panel that sits on the left side of the viewer
static createSidePanel(viewerId) {
const viewerElement = document.getElementById(viewerId);
if (!viewerElement) {
console.error(`Viewer element with id '${viewerId}' not found.`);
return;
}
// Create the side panel container
const sidePanel = document.createElement('div');
sidePanel.id = 'side-panel';
sidePanel.className = 'side-panel';
// Create side panel content
const content = document.createElement('div');
content.className = 'side-panel-content';
// Add the text extraction content
const sampleContent = document.createElement('div');
sampleContent.innerHTML = `
<div class="panel-section">
<h4>Side by Side Demo Files</h4>
<!-- File Version A (Left) -->
<div id="file-version-a">
<h3>File Version A (Left)</h3>
<input type="text" readonly placeholder="demo-annotated.pdf" class="file-input">
<button class="select-file-btn" id="btn-file-version-a">Select File</button>
</div>
<!-- File Version B (Right) -->
<div id="file-version-b">
<h3>File Version B (Right)</h3>
<input type="text" readonly placeholder="WebViewerDemoDoc.pdf" class="file-input">
<button class="select-file-btn" id="btn-file-version-b">Select File</button>
</div>
<!-- Sync Toggle -->
<div id="sync-toggle">
<input type="range" min="0" max="1" value="0" class="sync-slider" id="sync-slider">
<br>
<label for="sync-slider">Sync Scroll & Zoom</label>
</div>
</div>
`;
content.appendChild(sampleContent);
sidePanel.appendChild(content);
// Create a wrapper to contain both the side panel and viewer
const wrapper = document.createElement('div');
wrapper.id = 'viewer-wrapper';
wrapper.className = 'viewer-wrapper';
// Insert the wrapper before the viewer element
viewerElement.parentNode.insertBefore(wrapper, viewerElement);
// Move the viewer element into the wrapper and add the side panel
wrapper.appendChild(sidePanel);
wrapper.appendChild(viewerElement);
// Add the viewer-with-panel class to the viewer element
viewerElement.classList.add('viewer-with-panel');
}
// Function to add content to the side panel
addPanelContent(content) {
const panelContent = document.querySelector('.side-panel-content');
if (panelContent) {
const contentDiv = document.createElement('div');
contentDiv.className = 'panel-section';
contentDiv.innerHTML = content;
panelContent.appendChild(contentDiv);
}
}
static updateSyncToggleUIOnly(syncScroll) {
window.isUpdatingSync = true;
const syncSlider = document.getElementById('sync-slider');
if (syncSlider) {
// Guard against circular calls
syncSlider.value = syncScroll ? '1' : '0';
console.log('Sync slider UI updated to:', syncSlider.value);
// Function to update slider background color
const updateSliderBackground = (value) => {
if (value === '1') {
// Toggled to the right - light blue background
syncSlider.style.backgroundColor = '#87CEEB';
} else {
// Toggled to the left - gray background
syncSlider.style.backgroundColor = '#dadee2';
}
};
// Set initial background color
updateSliderBackground(syncSlider.value);
toggleSyncScrollZoom(syncScroll);
console.log('Sync slider background color updated to:', syncSlider.style.backgroundColor);
console.log('Sync toggle UI only updated to:', syncScroll);
console.log('syncSlider.value:', syncSlider.value);
}
}
// Setup event handlers for UI elements
static setupEventHandlers() {
// Sync toggle slider event listener
const syncSlider = document.getElementById('sync-slider');
if (syncSlider) {
// Function to update slider background color
const updateSliderBackground = (value) => {
if (value === '1') {
// Toggled to the right - light blue background
syncSlider.style.backgroundColor = '#87CEEB';
} else {
// Toggled to the left - gray background
syncSlider.style.backgroundColor = '#dadee2';
}
};
// Set initial background color
updateSliderBackground(syncSlider.value);
syncSlider.addEventListener('change', (event) => {
const isSync = event.target.value === '1';
// Update background color
updateSliderBackground(event.target.value);
// Guard against circular calls
if (window.isUpdatingSync) {
window.isUpdatingSync = false;
}
// Call the toggleSyncScrollZoom function in index.js if it exists
if (window.toggleSyncScrollZoom && typeof window.toggleSyncScrollZoom === 'function') {
window.toggleSyncScrollZoom(isSync);
}
});
// Also listen for input event for real-time updates while dragging
syncSlider.addEventListener('input', (event) => {
updateSliderBackground(event.target.value);
});
}
// File selection button event listeners
const selectFileButtons = document.querySelectorAll('.select-file-btn');
selectFileButtons.forEach((button, index) => {
button.addEventListener('click', () => {
if (button.id === 'btn-file-version-a') {
UIElements.filePicker('A');
}
else if (button.id === 'btn-file-version-b') {
UIElements.filePicker('B');
}
else if (button.id === 'sync-slider') {
window.toggleSyncScrollZoom((index === 1 ? true : false));
}
});
});
}
// Method to handle file upload for either side
static filePicker(selectSide) {
console.log(`Upload file for side: ${selectSide}`);
const instance = window.WebViewer.getInstance();
const viewerId = selectSide === 'A' ? 0 : 1;
// Create and trigger file input dialog directly
const input = document.createElement('input');
input.type = 'file';
input.accept = '.pdf,.docx,.doc,.pptx,.ppt,.xlsx,.xls,.txt,.rtf,.html,.htm,.xml,.tiff,.tif,.jpg,.jpeg,.png,.bmp,.gif,.svg,.webp,.heic,.heif';
input.onchange = async (event) => {
const file = event.target.files[0];
if (file) {
try {
const doc = await instance.Core.createDocument(file);
if (viewerId === 0) {
if (window.file1) {
window.file1.unloadResources();
}
window.file1 = doc;
instance.Core.getDocumentViewers()[0].loadDocument(doc);
window.title1 = file.name || 'File A';
console.log('Loaded file A:', window.title1);
} else {
if (window.file2) {
window.file2.unloadResources();
}
window.file2 = doc;
instance.Core.getDocumentViewers()[1].loadDocument(doc);
window.title2 = file.name || 'File B';
console.log('Loaded file B:', window.title2);
}
window.canStartComparing = true;
// Update UI to show selected file name
const fileInputs = document.querySelectorAll('.file-input');
if (fileInputs[viewerId]) {
fileInputs[viewerId].placeholder = file.name;
}
} catch (error) {
console.error('Error loading file:', error);
if (viewerId === 0) {
console.log('Error loading file A:', error.message);
} else {
console.log('Error loading file B:', error.message);
}
}
}
};
input.onerror = (error) => {
console.error('File input error:', error);
if (viewerId === 0) {
console.log('Error selecting file: ' + error.message);
} else {
console.log('Error selecting file: ' + error.message);
}
};
// Trigger the file dialog
input.click();
}
}