From 7ba00676888cb1c518efb668b01a51ce387a1185 Mon Sep 17 00:00:00 2001 From: ge64qev Date: Mon, 6 May 2024 11:18:59 +0200 Subject: [PATCH 1/5] Made it possible to add files via the selector "File by File". --- src/main/resources/static/js/fileInput.js | 22 +++++++++++++++++----- src/main/resources/static/js/merge.js | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index 001c8f24f..d575dbaa9 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -47,13 +47,12 @@ function setupFileInput(chooser) { const dt = e.dataTransfer; const files = dt.files; + //Do not Update allFiles array here to prevent duplication, the change event listener will take care of that + const dataTransfer = new DataTransfer(); for (let i = 0; i < files.length; i++) { - allFiles.push(files[i]); + dataTransfer.items.add(files[i]); } - const dataTransfer = new DataTransfer(); - allFiles.forEach((file) => dataTransfer.items.add(file)); - const fileInput = document.getElementById(elementId); fileInput.files = dataTransfer.files; @@ -81,8 +80,21 @@ function setupFileInput(chooser) { document.body.addEventListener("drop", dropListener); $("#" + elementId).on("change", function (e) { - allFiles = Array.from(e.target.files); + //Get newly Added Files + const newFiles = Array.from(e.target.files); + + //Add Files to existing Files + allFiles = allFiles.concat(newFiles); + + //Update the file inout`s files property + const dataTransfer = new DataTransfer(); + allFiles.forEach((file) => dataTransfer.items.add(file)); + e.target.files = dataTransfer.files; + handleFileInputChange(this); + + //Call the displayFiles function with the allFiles array + displayFiles(allFiles) }); function handleFileInputChange(inputElement) { diff --git a/src/main/resources/static/js/merge.js b/src/main/resources/static/js/merge.js index 555757277..9c63c7b71 100644 --- a/src/main/resources/static/js/merge.js +++ b/src/main/resources/static/js/merge.js @@ -9,7 +9,7 @@ document.getElementById("fileInput-input").addEventListener("change", function ( }); /** - * @param {FileList} files + * @param {File[]} files */ function displayFiles(files) { const list = document.getElementById("selectedFiles"); From c1fea7c92fd1e968538dc4eceef4acd6a8b3d1f3 Mon Sep 17 00:00:00 2001 From: ge64qev Date: Fri, 10 May 2024 10:53:27 +0200 Subject: [PATCH 2/5] A duplicate Warning is displayed if the same file is added twice to the merging process --- src/main/resources/static/css/fileSelect.css | 4 ++++ src/main/resources/static/js/merge.js | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/resources/static/css/fileSelect.css b/src/main/resources/static/css/fileSelect.css index e8f129795..b133e6434 100644 --- a/src/main/resources/static/css/fileSelect.css +++ b/src/main/resources/static/css/fileSelect.css @@ -8,3 +8,7 @@ overflow-y: auto; white-space: pre-wrap; } +.duplicate-warning { + color: red; + font-weight: bold; +} \ No newline at end of file diff --git a/src/main/resources/static/js/merge.js b/src/main/resources/static/js/merge.js index 9c63c7b71..7037405d9 100644 --- a/src/main/resources/static/js/merge.js +++ b/src/main/resources/static/js/merge.js @@ -13,6 +13,7 @@ document.getElementById("fileInput-input").addEventListener("change", function ( */ function displayFiles(files) { const list = document.getElementById("selectedFiles"); + const processedFiles = []; while (list.firstChild) { list.removeChild(list.firstChild); @@ -21,9 +22,23 @@ function displayFiles(files) { for (let i = 0; i < files.length; i++) { const item = document.createElement("li"); item.className = "list-group-item"; + const fileNameDiv = document.createElement("div"); + fileNameDiv.className = "filename"; + fileNameDiv.textContent = files[i].name; + + // Check for duplicates + if (processedFiles.includes(files[i].name)) { + const warning = document.createElement("span"); + warning.className = "duplicate-warning"; + warning.textContent = "(Duplicate)"; + fileNameDiv.appendChild(warning); + } else { + processedFiles.push(files[i].name); + } + item.innerHTML = `
-
${files[i].name}
+ ${fileNameDiv.outerHTML}
@@ -33,7 +48,6 @@ function displayFiles(files) { `; list.appendChild(item); } - attachMoveButtons(); } From 0e262dc2bd53a63f7592a53350a1a8e8a0364cee Mon Sep 17 00:00:00 2001 From: ge64qev Date: Mon, 13 May 2024 22:27:25 +0200 Subject: [PATCH 3/5] Added a unique id for all files to be a able to delete duplicate files. --- src/main/resources/static/js/fileInput.js | 40 ++++++++++++----- src/main/resources/static/js/merge.js | 55 ++++++++++++++--------- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index d575dbaa9..cf1b98968 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -79,22 +79,43 @@ function setupFileInput(chooser) { document.body.addEventListener("dragleave", dragleaveListener); document.body.addEventListener("drop", dropListener); + // When adding files $("#" + elementId).on("change", function (e) { - //Get newly Added Files - const newFiles = Array.from(e.target.files); + // Get newly Added Files + const newFiles = Array.from(e.target.files).map(file => { + return { + file: file, + uniqueId: file.name + Date.now()// Assign a unique identifier to each file + }; + }); - //Add Files to existing Files - allFiles = allFiles.concat(newFiles); + // Add new files to existing files + allFiles = [...allFiles, ...newFiles]; - //Update the file inout`s files property + // Update the file input's files property const dataTransfer = new DataTransfer(); - allFiles.forEach((file) => dataTransfer.items.add(file)); + allFiles.forEach((fileObj) => dataTransfer.items.add(fileObj.file)); e.target.files = dataTransfer.files; handleFileInputChange(this); - //Call the displayFiles function with the allFiles array + // Call the displayFiles function with the allFiles array displayFiles(allFiles) + // Dispatch a custom event with the allFiles array + var filesUpdated = new CustomEvent("filesUpdated", { detail: allFiles }); + document.dispatchEvent(filesUpdated); + }); + +// Listen for event of file being removed and then filter it out of the allFiles array + document.addEventListener("fileRemoved", function (e) { + const fileId = e.detail; + console.log('File to be removed:', fileId); // Log the uniqueId of the file to be removed + console.log('All files before removal:', allFiles); // Log all files before removal + allFiles = allFiles.filter(fileObj => fileObj.uniqueId !== fileId); // Remove the file from the allFiles array using the unique identifier + console.log('All files after removal:', allFiles); // Log all files after removal + // Dispatch a custom event with the allFiles array + var filesUpdated = new CustomEvent("filesUpdated", { detail: allFiles }); + document.dispatchEvent(filesUpdated); }); function handleFileInputChange(inputElement) { @@ -116,9 +137,4 @@ function setupFileInput(chooser) { $(inputElement).siblings(".custom-file-label").addClass("selected").html(pdfPrompt); } } - //Listen for event of file being removed and the filter it out of the allFiles array - document.addEventListener("fileRemoved", function (e) { - const fileName = e.detail; - allFiles = allFiles.filter(file => file.name !== fileName); - }); } diff --git a/src/main/resources/static/js/merge.js b/src/main/resources/static/js/merge.js index 7037405d9..a60ba7f6c 100644 --- a/src/main/resources/static/js/merge.js +++ b/src/main/resources/static/js/merge.js @@ -2,40 +2,53 @@ let currentSort = { field: null, descending: false, }; +let filesWithUniqueId = []; +let processedFiles = []; document.getElementById("fileInput-input").addEventListener("change", function () { - var files = this.files; + var files = Array.from(this.files).map(file => { + return { + file: file, + uniqueId: file.name + Date.now() + }; + }); + filesWithUniqueId = files; displayFiles(files); }); +document.addEventListener("filesUpdated", function (e) { + filesWithUniqueId = e.detail; + displayFiles(filesWithUniqueId); +}); + -/** - * @param {File[]} files - */ function displayFiles(files) { const list = document.getElementById("selectedFiles"); - const processedFiles = []; while (list.firstChild) { list.removeChild(list.firstChild); } + // Clear the processedFiles array + processedFiles = []; + for (let i = 0; i < files.length; i++) { const item = document.createElement("li"); item.className = "list-group-item"; + item.dataset.id = files[i].uniqueId; // Assign the uniqueId to the list item const fileNameDiv = document.createElement("div"); fileNameDiv.className = "filename"; - fileNameDiv.textContent = files[i].name; + fileNameDiv.textContent = files[i].file.name; // Check for duplicates - if (processedFiles.includes(files[i].name)) { + const duplicateFiles = files.filter(file => file.file.name === files[i].file.name); + if (duplicateFiles.length > 1) { const warning = document.createElement("span"); warning.className = "duplicate-warning"; warning.textContent = "(Duplicate)"; fileNameDiv.appendChild(warning); - } else { - processedFiles.push(files[i].name); } + item.innerHTML = `
${fileNameDiv.outerHTML} @@ -80,16 +93,18 @@ function attachMoveButtons() { var removeButtons = document.querySelectorAll(".remove-file"); for (var i = 0; i < removeButtons.length; i++) { + // When the delete button is clicked removeButtons[i].addEventListener("click", function (event) { event.preventDefault(); var parent = this.closest(".list-group-item"); - //Get name of removed file - var fileName = parent.querySelector(".filename").innerText; + var fileId = parent.dataset.id; // Get the unique identifier of the file to be deleted parent.remove(); + // Remove the file from the filesWithUniqueId array + filesWithUniqueId = filesWithUniqueId.filter(fileObj => fileObj.uniqueId !== fileId); updateFiles(); - //Dispatch a custom event with the name of the removed file - var event = new CustomEvent("fileRemoved", { detail: fileName }); - document.dispatchEvent(event); + // Dispatch a custom event with the unique identifier of the file to be deleted + var fileRemoved = new CustomEvent("fileRemoved", { detail: fileId }); + document.dispatchEvent(fileRemoved); }); } } @@ -129,18 +144,18 @@ function sortFiles(comparator) { document.getElementById("fileInput-input").files = dataTransfer.files; } + function updateFiles() { var dataTransfer = new DataTransfer(); var liElements = document.querySelectorAll("#selectedFiles li"); - const files = document.getElementById("fileInput-input").files; for (var i = 0; i < liElements.length; i++) { - var fileNameFromList = liElements[i].querySelector(".filename").innerText; + var fileIdFromList = liElements[i].dataset.id; // Get the unique identifier from the list item var fileFromFiles; - for (var j = 0; j < files.length; j++) { - var file = files[j]; - if (file.name === fileNameFromList) { - dataTransfer.items.add(file); + for (var j = 0; j < filesWithUniqueId.length; j++) { + var fileObj = filesWithUniqueId[j]; + if (fileObj.uniqueId === fileIdFromList) { + dataTransfer.items.add(fileObj.file); break; } } From 36192ba560d68c8855d3d984df3ba9e965f5bf92 Mon Sep 17 00:00:00 2001 From: ge64qev Date: Tue, 14 May 2024 08:49:27 +0200 Subject: [PATCH 4/5] Change the SortFiles Method, so it works with the filesWithUniqueID Array --- src/main/resources/static/js/merge.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/static/js/merge.js b/src/main/resources/static/js/merge.js index a60ba7f6c..1b3599d61 100644 --- a/src/main/resources/static/js/merge.js +++ b/src/main/resources/static/js/merge.js @@ -132,15 +132,15 @@ document.getElementById("sortByDateBtn").addEventListener("click", function () { }); function sortFiles(comparator) { - // Convert FileList to array and sort - const sortedFilesArray = Array.from(document.getElementById("fileInput-input").files).sort(comparator); + // Sort the filesWithUniqueId array + const sortedFilesArray = filesWithUniqueId.sort((a, b) => comparator(a.file, b.file)); // Refresh displayed list displayFiles(sortedFilesArray); // Update the files property const dataTransfer = new DataTransfer(); - sortedFilesArray.forEach((file) => dataTransfer.items.add(file)); + sortedFilesArray.forEach((fileObj) => dataTransfer.items.add(fileObj.file)); document.getElementById("fileInput-input").files = dataTransfer.files; } From ce3e98e240f8c86478f8541ae2b82e5207d4c0f4 Mon Sep 17 00:00:00 2001 From: ge64qev Date: Tue, 14 May 2024 09:13:39 +0200 Subject: [PATCH 5/5] Deleted Console logs and adjusted some comments. --- src/main/resources/static/js/fileInput.js | 3 --- src/main/resources/static/js/merge.js | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index cf1b98968..f3ae75047 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -109,10 +109,7 @@ function setupFileInput(chooser) { // Listen for event of file being removed and then filter it out of the allFiles array document.addEventListener("fileRemoved", function (e) { const fileId = e.detail; - console.log('File to be removed:', fileId); // Log the uniqueId of the file to be removed - console.log('All files before removal:', allFiles); // Log all files before removal allFiles = allFiles.filter(fileObj => fileObj.uniqueId !== fileId); // Remove the file from the allFiles array using the unique identifier - console.log('All files after removal:', allFiles); // Log all files after removal // Dispatch a custom event with the allFiles array var filesUpdated = new CustomEvent("filesUpdated", { detail: allFiles }); document.dispatchEvent(filesUpdated); diff --git a/src/main/resources/static/js/merge.js b/src/main/resources/static/js/merge.js index 1b3599d61..a434e0453 100644 --- a/src/main/resources/static/js/merge.js +++ b/src/main/resources/static/js/merge.js @@ -2,6 +2,7 @@ let currentSort = { field: null, descending: false, }; +//New Array to keep track of unique id let filesWithUniqueId = []; let processedFiles = []; @@ -15,6 +16,7 @@ document.getElementById("fileInput-input").addEventListener("change", function ( filesWithUniqueId = files; displayFiles(files); }); +//Get Files Updated Event from FileInput document.addEventListener("filesUpdated", function (e) { filesWithUniqueId = e.detail; displayFiles(filesWithUniqueId); @@ -39,7 +41,7 @@ function displayFiles(files) { fileNameDiv.className = "filename"; fileNameDiv.textContent = files[i].file.name; - // Check for duplicates + // Check for duplicates and add a warning if necessary const duplicateFiles = files.filter(file => file.file.name === files[i].file.name); if (duplicateFiles.length > 1) { const warning = document.createElement("span"); @@ -151,7 +153,6 @@ function updateFiles() { for (var i = 0; i < liElements.length; i++) { var fileIdFromList = liElements[i].dataset.id; // Get the unique identifier from the list item - var fileFromFiles; for (var j = 0; j < filesWithUniqueId.length; j++) { var fileObj = filesWithUniqueId[j]; if (fileObj.uniqueId === fileIdFromList) {