rework navbar and also multi submits

This commit is contained in:
Anthony Stirling 2023-03-04 00:10:13 +00:00
parent 721645273c
commit 4a2da2b7e0
6 changed files with 402 additions and 222 deletions

View File

@ -2,6 +2,9 @@ package stirling.software.SPDF.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -11,6 +14,9 @@ public class PdfController {
private static final Logger logger = LoggerFactory.getLogger(PdfController.class); private static final Logger logger = LoggerFactory.getLogger(PdfController.class);
@Autowired
private Environment environment;
@GetMapping("/home") @GetMapping("/home")
public String root(Model model) { public String root(Model model) {
return "redirect:/"; return "redirect:/";
@ -19,7 +25,11 @@ public class PdfController {
@GetMapping("/") @GetMapping("/")
public String home(Model model) { public String home(Model model) {
model.addAttribute("currentPage", "home"); model.addAttribute("currentPage", "home");
String appVersion = environment.getProperty("version");
model.addAttribute("appVersion", appVersion);
return "home"; return "home";
} }
} }

View File

@ -15,3 +15,5 @@ server.error.whitelabel.enabled=false
server.error.include-stacktrace=always server.error.include-stacktrace=always
server.error.include-exception=true server.error.include-exception=true
server.error.include-message=always server.error.include-message=always
server.servlet.session.tracking-modes=cookie

View File

@ -27,17 +27,19 @@
<button type="submit" class="btn btn-primary" th:text="#{extractImages.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{extractImages.submit}"></button>
</form> </form>
<th:block th:insert="~{fragments/common :: filelist}"></th:block> <th:block th:insert="~{fragments/common :: filelist}"></th:block>
<div id="progressBarContainer" style="display: none;">
<div class="progress"> <br>
<div id="progressBar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div> <div id="progressBarContainer" style="display: none; position: relative;">
<div class="progress" style="height: 1rem;">
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
<span class="sr-only">Loading...</span>
</div>
</div> </div>
</div> </div>
<script> <script>
$('#multiPdfForm').submit(function(event) { $('form').submit(function(event) {
event.preventDefault(); // Prevent the default form handling behavior event.preventDefault(); // Prevent the default form handling behavior
submitMultiPdfForm(event); submitMultiPdfForm(event);
}); });

View File

@ -115,23 +115,41 @@
<input type="file" class="custom-file-input" th:name="${name}" th:id="${name}+'-input'" th:multiple="${multiple}"> <input type="file" class="custom-file-input" th:name="${name}" th:id="${name}+'-input'" th:multiple="${multiple}">
<label class="custom-file-label" th:for="${name}+'-input'" th:text="#{pdfPrompt}"></label> <label class="custom-file-label" th:for="${name}+'-input'" th:text="#{pdfPrompt}"></label>
</div> </div>
<div class="selected-files"></div>
</div> </div>
<script th:inline="javascript"> <script th:inline="javascript">
$([[${"#"+name+"-input"}]]).on("change", function() { $([[${"#"+name+"-input"}]]).on("change", function() {
const files = $(this).get(0).files; const files = $(this).get(0).files;
const fileNames = Array.from(files).map(f => f.name).join(", "); const fileNames = Array.from(files).map(f => f.name);
if (fileNames) { const selectedFilesContainer = $(this).siblings(".selected-files");
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames); selectedFilesContainer.empty();
fileNames.forEach(fileName => {
selectedFilesContainer.append("<div>" + fileName + "</div>");
});
if (fileNames.length === 1) {
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
} else if (fileNames.length > 1) {
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames.length + " files selected");
} else { } else {
$(this).siblings(".custom-file-label").addClass("selected").html([[#{pdfPrompt}]]); $(this).siblings(".custom-file-label").addClass("selected").html([[#{pdfPrompt}]]);
} }
}); });
</script> </script>
<style> <style>
.custom-file-label { .custom-file-label {
padding-right: 90px; padding-right: 90px;
} }
.selected-files {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
white-space: pre-wrap;
}
</style> </style>
</th:block> </th:block>

View File

@ -1,37 +1,166 @@
<div th:fragment="navbar"> <div th:fragment="navbar" class="mx-auto">
<style>
.toggle-container {
display: flex;
align-items: center;
margin-right: 10px;
}
.toggle {
position: relative;
display: inline-block;
width: 50px;
height: 28px;
}
.toggle input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
border-radius: 28px;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 20px;
width: 20px;
left: 4px;
bottom: 4px;
background-color: white;
border-radius: 50%;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
transform: translateX(22px);
}
.toggle-label {
margin-top: 2px;
margin-left: 2px;
text-align: center;
font-size: 14px;
color: #333;
display: flex;
align-items: center;
justify-content: center;
height: 20px;
width: 60px;
}
.navbar-nav {
width: 100% !important;
white-space: nowrap !important;
}
</style>
<script>
document
.addEventListener(
'DOMContentLoaded',
function() {
// Get the dropdown items
var dropdownItems = document
.querySelectorAll('.lang_dropdown-item');
// Loop through the dropdown items
for (var i = 0; i < dropdownItems.length; i++) {
dropdownItems[i].classList
.remove('active');
if (dropdownItems[i].dataset.languageCode === localStorage
.getItem('languageCode')) {
dropdownItems[i].classList
.add('active');
}
// Add a click event listener to each dropdown item
dropdownItems[i]
.addEventListener(
'click',
function(event) {
// Prevent the default link behavior
event
.preventDefault();
// Get the language code
var languageCode = this.dataset.languageCode;
// Save the language code to local storage
localStorage
.setItem(
'languageCode',
languageCode);
// Get the current URL
var currentUrl = window.location.href;
// Check if the URL already contains a "?lang" query parameter
if (currentUrl
.indexOf('?lang=') === -1) {
// Update the URL with the "?lang" query parameter
window.location.href = currentUrl
+ '?lang='
+ languageCode;
} else {
// Replace the "?lang" query parameter with the new value
window.location.href = currentUrl
.replace(
/\?lang=\w{2,}/,
'?lang='
+ languageCode);
}
});
}
});
</script>
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container "> <div class="container ">
<a class="navbar-brand" href="#" th:href="@{/}">Stirling PDF</a> <a class="navbar-brand" href="#" th:href="@{/}">Stirling PDF</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
data-target="#navbarNav" aria-controls="navbarNav"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav"> <ul class="navbar-nav mr-auto flex-nowrap">
<li class="nav-item"> <li class="nav-item"><a class="nav-link" href="#" th:href="@{merge-pdfs}" th:classappend="${currentPage}=='merge-pdfs' ? 'active' : ''" th:text="#{home.merge.title}"></a></li>
<a class="nav-link" href="#" th:href="@{merge-pdfs}" th:classappend="${currentPage}=='merge-pdfs' ? 'active' : ''" th:text="#{home.merge.title}"></a>
</li>
<li class="nav-item"> <li class="nav-item"><a class="nav-link" href="#" th:href="@{split-pdfs}" th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:text="#{home.split.title}"></a></li>
<a class="nav-link" href="#" th:href="@{split-pdfs}" th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:text="#{home.split.title}"></a>
</li>
<li class="nav-item"> <li class="nav-item"><a class="nav-link" href="#" th:href="@{pdf-organizer}" th:classappend="${currentPage}=='pdf-organizer' ? 'active' : ''" th:text="#{home.pdfOrganiser.title}"></a></li>
<a class="nav-link" href="#" th:href="@{pdf-organizer}" th:classappend="${currentPage}=='pdf-organizer' ? 'active' : ''" th:text="#{home.pdfOrganiser.title}"></a>
</li>
<li class="nav-item"> <li class="nav-item"><a class="nav-link" href="#" th:href="@{rotate-pdf}" th:classappend="${currentPage}=='rotate-pdf' ? 'active' : ''" th:text="#{home.rotate.title}"></a></li>
<a class="nav-link" href="#" th:href="@{rotate-pdf}" th:classappend="${currentPage}=='rotate-pdf' ? 'active' : ''" th:text="#{home.rotate.title}"></a>
</li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='xlsx-to-pdf' ? 'active' : ''"> <li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='xlsx-to-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.convert}"></a> aria-haspopup="true" aria-expanded="false" th:text="#{navbar.convert}"></a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#" th:href="@{pdf-to-img}" th:classappend="${currentPage}=='pdf-to-img' ? 'active' : ''" th:text="#{home.pdfToImage.title}"></a> <a class="dropdown-item" href="#" th:href="@{pdf-to-img}" th:classappend="${currentPage}=='pdf-to-img' ? 'active' : ''" th:text="#{home.pdfToImage.title}"></a>
<a class="dropdown-item" href="#" th:href="@{img-to-pdf}" th:classappend="${currentPage}=='img-to-pdf' ? 'active' : ''" th:text="#{home.imageToPdf.title}"></a> <a class="dropdown-item" href="#" th:href="@{img-to-pdf}" th:classappend="${currentPage}=='img-to-pdf' ? 'active' : ''" th:text="#{home.imageToPdf.title}"></a>
@ -39,6 +168,7 @@
</div> </div>
</li> </li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='change-permissions' OR ${currentPage}=='add-watermark' OR ${currentPage}=='remove-watermark' ? 'active' : ''"> <li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='change-permissions' OR ${currentPage}=='add-watermark' OR ${currentPage}=='remove-watermark' ? 'active' : ''">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.security}"></a> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.security}"></a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
@ -50,40 +180,38 @@
</div> </div>
</li> </li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='add-image' OR ${currentPage}=='compress-pdf' ? 'active' : ''">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.other}"></a> <li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='add-image' OR ${currentPage}=='compress-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" th:text="#{navbar.other}"></a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''" th:text="#{home.addImage.title}"></a> <a class="dropdown-item" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''" th:text="#{home.addImage.title}"></a> <a class="dropdown-item" href="#" th:href="@{compress-pdf}"
<a class="dropdown-item" href="#" th:href="@{compress-pdf}" th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:text="#{home.compressPdfs.title}"></a> th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:text="#{home.compressPdfs.title}"></a> <a class="dropdown-item" href="#" th:href="@{remove-pages}" th:classappend="${currentPage}=='remove-pages' ? 'active' : ''" th:text="#{home.removePages.title}"></a>
<a class="dropdown-item" href="#" th:href="@{remove-pages}" th:classappend="${currentPage}=='remove-pages' ? 'active' : ''" th:text="#{home.removePages.title}"></a> </div></li>
<div class="toggle-container">
<label class="toggle"> <input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()"> <span class="slider round"></span>
</label> <label class="toggle-label" for="toggle-dark-mode" th:text="#{navbar.darkmode}"></label>
</div> </div>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''"></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{compress-pdf}" th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''"></a>
</li>
<input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()">
<a class="nav-link" href="#" for="toggle-dark-mode" th:text="#{navbar.darkmode}"></a>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="languageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="bi bi-globe2"></i>
<li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="languageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="bi bi-globe2"></i>
</a> </a>
<div class="dropdown-menu" aria-labelledby="languageDropdown"> <div class="dropdown-menu" aria-labelledby="languageDropdown">
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_US">English (US)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_US">English (US)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English (UK)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English (UK)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">Deutsch</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a> </div></li>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">Deutsch</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a>
</div>
</li>
</ul> </ul>
@ -92,48 +220,59 @@
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button> <button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
</li> </li>
</ul> </ul>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Get the dropdown items
var dropdownItems = document.querySelectorAll('.lang_dropdown-item');
// Loop through the dropdown items
for (var i = 0; i < dropdownItems.length; i++) {
dropdownItems[i].classList.remove('active');
if (dropdownItems[i].dataset.languageCode === localStorage.getItem('languageCode')) {
dropdownItems[i].classList.add('active');
}
// Add a click event listener to each dropdown item
dropdownItems[i].addEventListener('click', function(event) {
// Prevent the default link behavior
event.preventDefault();
// Get the language code
var languageCode = this.dataset.languageCode;
// Save the language code to local storage
localStorage.setItem('languageCode', languageCode);
// Get the current URL
var currentUrl = window.location.href;
// Check if the URL already contains a "?lang" query parameter
if (currentUrl.indexOf('?lang=') === -1) {
// Update the URL with the "?lang" query parameter
window.location.href = currentUrl + '?lang=' + languageCode;
} else {
// Replace the "?lang" query parameter with the new value
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, '?lang=' + languageCode);
}
});
}
});
</script>
</div> </div>
</div> </div>
</nav> </nav>
<div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div> <div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div>
<div class="modal fade" id="settingsModal" tabindex="-1" role="dialog" aria-labelledby="settingsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p th:text="'App Version:' + ${appVersion}"></p>
<div class="form-group">
<label for="downloadOption">Choose download option (For non ZIP downloads):</label> <select class="form-control" id="downloadOption">
<option value="sameWindow">Open in same window (Single file downloads only)</option>
<option value="newWindow">Open in new window</option>
<option value="downloadFile">Download file</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Settings Button -->
<button type="button" class="btn btn-secondary float-right" data-toggle="modal" data-target="#settingsModal">
<span class="glyphicon glyphicon-cog"></span> Settings/About
</button>
<script>
// Get the download option from local storage, or set it to 'sameWindow' if it doesn't exist
var downloadOption = localStorage.getItem('downloadOption')
|| 'sameWindow';
// Set the selected option in the dropdown
document.getElementById('downloadOption').value = downloadOption;
// Save the selected option to local storage when the dropdown value changes
document.getElementById('downloadOption').addEventListener(
'change',
function() {
downloadOption = this.value;
localStorage.setItem('downloadOption',
downloadOption);
});
</script>
</div> </div>

View File

@ -28,65 +28,79 @@
<button type="submit" class="btn btn-primary" th:text="#{merge.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{merge.submit}"></button>
</div> </div>
</form> </form>
<style>
.list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.filename {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.arrows {
flex-shrink: 0;
display: flex;
justify-content: flex-end;
}
.move-up span,
.move-down span {
font-weight: bold;
font-size: 1.2em;
}
</style>
<script> <script>
document document.getElementById("fileInput").addEventListener("change", function() {
.getElementById(
"fileInput")
.addEventListener(
"change",
function() {
var files = this.files; var files = this.files;
var list = document var list = document.getElementById("selectedFiles");
.getElementById("selectedFiles");
list.innerHTML = ""; list.innerHTML = "";
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
var item = document var item = document.createElement("li");
.createElement("li"); item.className = "list-group-item";
item.className = "list-group-item d-flex justify-content-between align-items-center"; item.innerHTML = `
item.textContent = files[i].name; <div class="d-flex justify-content-between align-items-center w-100">
item.innerHTML += '<div><button class="btn btn-secondary move-up"><i class="fas fa-arrow-up"></i></button> <button class="btn btn-secondary move-down"><i class="fas fa-arrow-down"></i></button></div>'; <div class="filename">${files[i].name}</div>
list <div class="arrows d-flex">
.appendChild(item); <button class="btn btn-secondary move-up"><span>&uarr;</span></button>
<button class="btn btn-secondary move-down"><span>&darr;</span></button>
</div>
</div>
`;
list.appendChild(item);
} }
var moveUpButtons = document
.querySelectorAll(".move-up"); var moveUpButtons = document.querySelectorAll(".move-up");
for (var i = 0; i < moveUpButtons.length; i++) { for (var i = 0; i < moveUpButtons.length; i++) {
moveUpButtons[i] moveUpButtons[i].addEventListener("click", function(event) {
.addEventListener( event.preventDefault();
"click", var parent = this.closest(".list-group-item");
function(
event) {
event
.preventDefault();
var parent = this.parentNode.parentNode;
var grandParent = parent.parentNode; var grandParent = parent.parentNode;
if (parent.previousElementSibling) { if (parent.previousElementSibling) {
grandParent grandParent.insertBefore(parent, parent.previousElementSibling);
.insertBefore(
parent,
parent.previousElementSibling);
updateFiles(); updateFiles();
} }
}); });
} }
var moveDownButtons = document
.querySelectorAll(".move-down"); var moveDownButtons = document.querySelectorAll(".move-down");
for (var i = 0; i < moveDownButtons.length; i++) { for (var i = 0; i < moveDownButtons.length; i++) {
moveDownButtons[i] moveDownButtons[i].addEventListener("click", function(event) {
.addEventListener( event.preventDefault();
"click", var parent = this.closest(".list-group-item");
function(
event) {
event
.preventDefault();
var parent = this.parentNode.parentNode;
var grandParent = parent.parentNode; var grandParent = parent.parentNode;
if (parent.nextElementSibling) { if (parent.nextElementSibling) {
grandParent grandParent.insertBefore(parent.nextElementSibling, parent);
.insertBefore(
parent.nextElementSibling,
parent);
updateFiles(); updateFiles();
} }
}); });
@ -94,28 +108,23 @@
function updateFiles() { function updateFiles() {
var dataTransfer = new DataTransfer(); var dataTransfer = new DataTransfer();
var liElements = document var liElements = document.querySelectorAll("#selectedFiles li");
.querySelectorAll("#selectedFiles li");
for (var i = 0; i < liElements.length; i++) { for (var i = 0; i < liElements.length; i++) {
var fileNameFromList = liElements[i].innerText var fileNameFromList = liElements[i].querySelector(".filename").innerText;
.replace( var fileFromFiles;
"\nMove Up Move Down",
"");
var fileFromFiles
for (var j = 0; j < files.length; j++) { for (var j = 0; j < files.length; j++) {
var file = files[j]; var file = files[j];
if (file.name === fileNameFromList) { if (file.name === fileNameFromList) {
dataTransfer.items dataTransfer.items.add(file);
.add(file);
break; break;
} }
} }
} }
document document.getElementById("fileInput").files = dataTransfer.files;
.getElementById("fileInput").files = dataTransfer.files;
} }
}); });
</script> </script>
</div> </div>
</div> </div>