diff --git a/fileManager.js b/fileManager.js index 5b82b18..24ee6e7 100644 --- a/fileManager.js +++ b/fileManager.js @@ -123,50 +123,57 @@ export function loadFileList(folderParam) { }); } +// Debounce helper (if not defined already) +function debounce(func, wait) { + let timeout; + return function(...args) { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; +} + export function renderFileTable(folder) { const fileListContainer = document.getElementById("fileList"); const folderPath = (folder === "root") ? "uploads/" : "uploads/" + folder.split("/").map(encodeURIComponent).join("/") + "/"; - - // Attempt to get the search input element. - const searchInputElement = document.getElementById("searchInput"); - const searchHadFocus = searchInputElement && (document.activeElement === searchInputElement); - const searchTerm = searchInputElement ? searchInputElement.value : ""; - + + // Use the global search term if available. + const searchTerm = window.currentSearchTerm || ""; + const filteredFiles = fileData.filter(file => file.name.toLowerCase().includes(searchTerm.toLowerCase()) ); - - // Read persistent items per page from localStorage, default to 10. + + // 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 = ` -
-
-
-
- - search - +
+
+
+
+ + search + +
+ +
+
+
+
+ + Page ${currentPage} of ${totalPages || 1} +
-
-
-
- - Page ${currentPage} of ${totalPages || 1} - -
-
-
`; - + let tableHTML = ` @@ -181,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); @@ -194,16 +201,15 @@ export function renderFileTable(folder) { const safeUploaded = escapeHTML(file.uploaded); const safeSize = escapeHTML(file.size); const safeUploader = escapeHTML(file.uploader || "Unknown"); - - // Check if file is an image. + const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.name); - + const previewButton = isImage ? `` + image + ` : ""; - + tableBody += ` `; } tableBody += `
@@ -229,43 +235,55 @@ export function renderFileTable(folder) { tableBody += `
No files found.
`; - + const bottomControlsHTML = `
items per page
`; - + fileListContainer.innerHTML = topControlsHTML + tableHTML + tableBody + bottomControlsHTML; - - // Only add event listeners if searchInputElement exists. - if (searchInputElement) { - searchInputElement.addEventListener("input", function () { + + // Re-attach event listener for the new search input element. + const newSearchInput = document.getElementById("searchInput"); + if (newSearchInput) { + newSearchInput.addEventListener("input", debounce(function () { + window.currentSearchTerm = newSearchInput.value; window.currentPage = 1; renderFileTable(folder); - }); + // After re-rendering, restore focus and caret position. + setTimeout(() => { + const freshInput = document.getElementById("searchInput"); + if (freshInput) { + freshInput.focus(); + freshInput.setSelectionRange(freshInput.value.length, freshInput.value.length); + } + }, 0); + }, 300)); } - + + // Add event listeners for header sorting. document.querySelectorAll("table.table thead th[data-column]").forEach(cell => { cell.addEventListener("click", function () { const column = this.getAttribute("data-column"); sortFiles(column, folder); }); }); - + + // Add event listeners for checkboxes. document.querySelectorAll('#fileList .file-checkbox').forEach(checkbox => { checkbox.addEventListener('change', function (e) { updateRowHighlight(e.target); updateFileActionButtons(); }); }); - + updateFileActionButtons(); } @@ -712,15 +730,15 @@ export function editFile(fileName, folder) { theme: theme, viewportMargin: Infinity }); - + // Ensure height adjustment window.currentEditor = editor; - + // Adjust height AFTER modal appears setTimeout(() => { adjustEditorSize(); // Set initial height }, 50); - + // Attach modal resize observer observeModalResize(modal); @@ -732,7 +750,7 @@ export function editFile(fileName, folder) { document.getElementById("closeEditorX").addEventListener("click", function () { modal.remove(); }); - + document.getElementById("decreaseFont").addEventListener("click", function () { currentFontSize = Math.max(8, currentFontSize - 2); editor.getWrapperElement().style.fontSize = currentFontSize + "px"; diff --git a/upload.js b/upload.js index c8f53b8..9d46534 100644 --- a/upload.js +++ b/upload.js @@ -45,6 +45,29 @@ function getFilesFromDataTransferItems(items) { return Promise.all(promises).then(results => results.flat()); } +// Helper: Set default drop area content. +// Moved to module scope so it is available globally in this module. +function setDropAreaDefault() { + const dropArea = document.getElementById("uploadDropArea"); + if (dropArea) { + dropArea.innerHTML = ` +
+ Drop files/folders here or click 'Choose files' +
+
+ +
+
+
+ No files selected +
+
+ `; + } +} + function adjustFolderHelpExpansion() { const uploadCard = document.getElementById("uploadCard"); const folderHelpDetails = document.querySelector(".folder-help-details"); @@ -247,8 +270,8 @@ function processFiles(filesInput) { } const listWrapper = document.createElement("div"); listWrapper.classList.add("upload-progress-wrapper"); - // Set a maximum height (adjust as needed) and enable vertical scrolling. - listWrapper.style.maxHeight = "300px"; // for example, 300px + // Set a maximum height and enable vertical scrolling. + listWrapper.style.maxHeight = "300px"; listWrapper.style.overflowY = "auto"; listWrapper.appendChild(list); progressContainer.appendChild(listWrapper); @@ -433,30 +456,11 @@ function initUpload() { fileInput.setAttribute("directory", ""); } - // Helper: Set default drop area content. - function setDropAreaDefault() { - if (dropArea) { - dropArea.innerHTML = ` -
- Drop files/folders here or click 'Choose files' -
-
- -
-
-
- No files selected -
-
- `; - } - } + // Set default drop area content. + setDropAreaDefault(); if (dropArea) { dropArea.classList.add("upload-drop-area"); - setDropAreaDefault(); dropArea.addEventListener("dragover", function (e) { e.preventDefault(); // Use a darker color if dark mode is active.