From a83a13b34be42e910ce76f56b75c6836b1ae366b Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 15 Mar 2025 16:40:09 -0400 Subject: [PATCH] video & pdf preview added --- fileManager.js | 114 +++++++++++++++++++++++++++++++++---------------- styles.css | 12 ++++++ 2 files changed, 89 insertions(+), 37 deletions(-) diff --git a/fileManager.js b/fileManager.js index 24ee6e7..71c73e9 100644 --- a/fileManager.js +++ b/fileManager.js @@ -126,7 +126,7 @@ export function loadFileList(folderParam) { // Debounce helper (if not defined already) function debounce(func, wait) { let timeout; - return function(...args) { + return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; @@ -137,21 +137,21 @@ export function renderFileTable(folder) { const folderPath = (folder === "root") ? "uploads/" : "uploads/" + folder.split("/").map(encodeURIComponent).join("/") + "/"; - + // Use the global search term if available. const searchTerm = window.currentSearchTerm || ""; - + const filteredFiles = fileData.filter(file => file.name.toLowerCase().includes(searchTerm.toLowerCase()) ); - + // Get persistent items per page from localStorage. const itemsPerPageSetting = parseInt(localStorage.getItem('itemsPerPage') || '10', 10); const currentPage = window.currentPage || 1; const totalFiles = filteredFiles.length; const totalPages = Math.ceil(totalFiles / itemsPerPageSetting); const safeSearchTerm = escapeHTML(searchTerm); - + const topControlsHTML = `
@@ -173,7 +173,7 @@ export function renderFileTable(folder) {
`; - + let tableHTML = ` @@ -188,11 +188,11 @@ export function renderFileTable(folder) { `; - + const startIndex = (currentPage - 1) * itemsPerPageSetting; const endIndex = Math.min(startIndex + itemsPerPageSetting, totalFiles); let tableBody = ``; - + if (totalFiles > 0) { filteredFiles.slice(startIndex, endIndex).forEach(file => { const isEditable = canEditFile(file.name); @@ -201,15 +201,24 @@ export function renderFileTable(folder) { const safeUploaded = escapeHTML(file.uploaded); const safeSize = escapeHTML(file.size); const safeUploader = escapeHTML(file.uploader || "Unknown"); - - const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.name); - - const previewButton = isImage - ? `` - : ""; - + + const isViewable = /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico|tif|tiff|eps|heic|pdf|mp4|webm|ogg)$/i.test(file.name); + let previewButton = ""; + if (isViewable) { + let previewIcon = ""; + if (/\.(jpg|jpeg|png|gif|bmp|webp|svg|ico|tif|tiff|eps|heic)$/i.test(file.name)) { + previewIcon = `image`; + } else if (/\.(mp4|webm|ogg)$/i.test(file.name)) { + previewIcon = `videocam`; + } else if (/\.pdf$/i.test(file.name)) { + previewIcon = `picture_as_pdf`; + } + + previewButton = ``; + } + tableBody += ` `; } tableBody += `
@@ -235,21 +244,21 @@ export function renderFileTable(folder) { tableBody += `
No files found.
`; - + const bottomControlsHTML = `
items per page
`; - + fileListContainer.innerHTML = topControlsHTML + tableHTML + tableBody + bottomControlsHTML; - + // Re-attach event listener for the new search input element. const newSearchInput = document.getElementById("searchInput"); if (newSearchInput) { @@ -267,7 +276,7 @@ export function renderFileTable(folder) { }, 0); }, 300)); } - + // Add event listeners for header sorting. document.querySelectorAll("table.table thead th[data-column]").forEach(cell => { cell.addEventListener("click", function () { @@ -275,7 +284,7 @@ export function renderFileTable(folder) { sortFiles(column, folder); }); }); - + // Add event listeners for checkboxes. document.querySelectorAll('#fileList .file-checkbox').forEach(checkbox => { checkbox.addEventListener('change', function (e) { @@ -283,17 +292,17 @@ export function renderFileTable(folder) { updateFileActionButtons(); }); }); - + updateFileActionButtons(); } // Global function to show an image preview modal. -window.previewImage = function (imageUrl, fileName) { - let modal = document.getElementById("imagePreviewModal"); +window.previewFile = function (fileUrl, fileName) { + let modal = document.getElementById("filePreviewModal"); if (!modal) { modal = document.createElement("div"); - modal.id = "imagePreviewModal"; - // Full-screen overlay using flexbox, with no padding. + modal.id = "filePreviewModal"; + // Use the same styling as the original image modal. Object.assign(modal.style, { display: "none", position: "fixed", @@ -309,12 +318,12 @@ window.previewImage = function (imageUrl, fileName) { }); modal.innerHTML = ` `; document.body.appendChild(modal); - document.getElementById("closeImageModal").addEventListener("click", function () { + document.getElementById("closeFileModal").addEventListener("click", function () { modal.style.display = "none"; }); modal.addEventListener("click", function (e) { @@ -324,7 +333,38 @@ window.previewImage = function (imageUrl, fileName) { }); } modal.querySelector("h4").textContent = "Preview: " + fileName; - modal.querySelector("img").src = imageUrl; + const container = modal.querySelector(".file-preview-container"); + container.innerHTML = ""; // Clear previous content + + const extension = fileName.split('.').pop().toLowerCase(); + + if (/\.(jpg|jpeg|png|gif|bmp|webp|svg|ico|tif|tiff|eps|heic)$/i.test(fileName)) { + // Image preview + const img = document.createElement("img"); + img.src = fileUrl; + img.className = "image-modal-img"; + container.appendChild(img); + } else if (extension === "pdf") { + // PDF preview using with explicit sizing + const embed = document.createElement("embed"); + embed.src = fileUrl; + embed.type = "application/pdf"; + // Instead of using the image-modal-img class, set larger dimensions + embed.style.width = "80vw"; + embed.style.height = "80vh"; + embed.style.border = "none"; + container.appendChild(embed); + } else if (/\.(mp4|webm|ogg)$/i.test(fileName)) { + // Video preview using