JS and css cleanup
This commit is contained in:
parent
7bdb2615d4
commit
45b3e0aa6a
14 changed files with 669 additions and 644 deletions
10
src/main/resources/static/css/fileSelect.css
Normal file
10
src/main/resources/static/css/fileSelect.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
.custom-file-label {
|
||||
padding-right: 90px;
|
||||
}
|
||||
|
||||
.selected-files {
|
||||
margin-top: 10px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
76
src/main/resources/static/js/darkmode.js
Normal file
76
src/main/resources/static/js/darkmode.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
var toggleCount = 0;
|
||||
var lastToggleTime = Date.now();
|
||||
|
||||
function toggleDarkMode() {
|
||||
var currentTime = Date.now();
|
||||
if (currentTime - lastToggleTime < 1000) {
|
||||
toggleCount++;
|
||||
} else {
|
||||
toggleCount = 1;
|
||||
}
|
||||
lastToggleTime = currentTime;
|
||||
|
||||
var lightModeStyles = document.getElementById("light-mode-styles");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var rainbowModeStyles = document.getElementById("rainbow-mode-styles");
|
||||
var darkModeIcon = document.getElementById("dark-mode-icon");
|
||||
|
||||
if (toggleCount >= 18) {
|
||||
localStorage.setItem("dark-mode", "rainbow");
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = false;
|
||||
darkModeIcon.src = "rainbow.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "on") {
|
||||
localStorage.setItem("dark-mode", "off");
|
||||
lightModeStyles.disabled = false;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
} else {
|
||||
localStorage.setItem("dark-mode", "on");
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var lightModeStyles = document.getElementById("light-mode-styles");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var rainbowModeStyles = document.getElementById("rainbow-mode-styles");
|
||||
var darkModeIcon = document.getElementById("dark-mode-icon");
|
||||
|
||||
if (localStorage.getItem("dark-mode") == "on") {
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "off") {
|
||||
lightModeStyles.disabled = false;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "rainbow") {
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = false;
|
||||
darkModeIcon.src = "rainbow.svg";
|
||||
} else {
|
||||
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
} else {
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("dark-mode-toggle").addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
toggleDarkMode();
|
||||
});
|
||||
});
|
242
src/main/resources/static/js/downloader.js
Normal file
242
src/main/resources/static/js/downloader.js
Normal file
|
@ -0,0 +1,242 @@
|
|||
function showErrorBanner(message, stackTrace) {
|
||||
const errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "block"; // Display the banner
|
||||
document.querySelector("#errorContainer .alert-heading").textContent = "Error";
|
||||
document.querySelector("#errorContainer p").textContent = message;
|
||||
document.querySelector("#traceContent").textContent = stackTrace;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('form').submit(async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const url = this.action;
|
||||
const files = $('#fileInput-input')[0].files;
|
||||
const formData = new FormData(this);
|
||||
const override = $('#override').val() || '';
|
||||
|
||||
$('#submitBtn').text('Processing...');
|
||||
|
||||
try {
|
||||
if (override === 'multi' || files.length > 1 && override !== 'single') {
|
||||
// Show the progress bar
|
||||
$('#progressBarContainer').show();
|
||||
// Initialize the progress bar
|
||||
//let progressBar = $('#progressBar');
|
||||
//progressBar.css('width', '0%');
|
||||
//progressBar.attr('aria-valuenow', 0);
|
||||
//progressBar.attr('aria-valuemax', files.length);
|
||||
|
||||
await submitMultiPdfForm(url, files);
|
||||
} else {
|
||||
const downloadDetails = await handleSingleDownload(url, formData);
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
// Handle the download action according to the selected option
|
||||
//handleDownloadAction(downloadOption, downloadDetails.blob, downloadDetails.filename);
|
||||
|
||||
// Update the progress bar
|
||||
//updateProgressBar(progressBar, 1);
|
||||
|
||||
}
|
||||
|
||||
$('#submitBtn').text('Submit');
|
||||
} catch (error) {
|
||||
handleDownloadError(error);
|
||||
$('#submitBtn').text('Submit');
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleDownloadAction(downloadOption, blob, filename) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
switch (downloadOption) {
|
||||
case 'sameWindow':
|
||||
// Open the file in the same window
|
||||
window.location.href = url;
|
||||
break;
|
||||
case 'newWindow':
|
||||
// Open the file in a new window
|
||||
window.open(url, '_blank');
|
||||
break;
|
||||
default:
|
||||
// Download the file
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
link.click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSingleDownload(url, formData) {
|
||||
try {
|
||||
const response = await fetch(url, { method: 'POST', body: formData });
|
||||
const contentType = response.headers.get('content-type');
|
||||
|
||||
if (!response.ok) {
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
return handleJsonResponse(response);
|
||||
console.error('Throwing error banner, response was not okay');
|
||||
}
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const contentDisposition = response.headers.get('Content-Disposition');
|
||||
let filename = getFilenameFromContentDisposition(contentDisposition);
|
||||
|
||||
const blob = await response.blob();
|
||||
|
||||
if (contentType.includes('application/pdf') || contentType.includes('image/')) {
|
||||
return handleResponse(blob, filename, true);
|
||||
} else {
|
||||
return handleResponse(blob, filename);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in handleSingleDownload:', error);
|
||||
throw error; // Re-throw the error if you want it to be handled higher up.
|
||||
}
|
||||
}
|
||||
|
||||
function getFilenameFromContentDisposition(contentDisposition) {
|
||||
let filename;
|
||||
|
||||
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
|
||||
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
|
||||
} else {
|
||||
// If the Content-Disposition header is not present or does not contain the filename, use a default filename
|
||||
filename = 'download';
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function handleJsonResponse(response) {
|
||||
const json = await response.json();
|
||||
const errorMessage = JSON.stringify(json, null, 2);
|
||||
if (errorMessage.toLowerCase().includes('the password is incorrect') || errorMessage.toLowerCase().includes('Password is not provided')) {
|
||||
alert('[[#{error.pdfPassword}]]');
|
||||
} else {
|
||||
showErrorBanner(json.error + ':' + json.message, json.trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handleResponse(blob, filename, considerViewOptions = false) {
|
||||
if (!blob) return;
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
if (considerViewOptions) {
|
||||
if (downloadOption === 'sameWindow') {
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.location.href = url;
|
||||
return;
|
||||
} else if (downloadOption === 'newWindow') {
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.open(url, '_blank');
|
||||
return;
|
||||
}
|
||||
}
|
||||
downloadFile(blob, filename);
|
||||
return { filename, blob };
|
||||
}
|
||||
|
||||
function handleDownloadError(error) {
|
||||
const errorMessage = error.message;
|
||||
showErrorBanner(errorMessage);
|
||||
}
|
||||
|
||||
let urls = []; // An array to hold all the URLs
|
||||
|
||||
function downloadFile(blob, filename) {
|
||||
if (!(blob instanceof Blob)) {
|
||||
console.error('Invalid blob passed to downloadFile function');
|
||||
return;
|
||||
}
|
||||
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
a.click();
|
||||
urls.push(url); // Store the URL so it doesn't get garbage collected too soon
|
||||
|
||||
return { filename, blob };
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function submitMultiPdfForm(url, files) {
|
||||
const zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
|
||||
const zipFiles = files.length > zipThreshold;
|
||||
let jszip = null;
|
||||
//let progressBar = $('#progressBar');
|
||||
//progressBar.css('width', '0%');
|
||||
//progressBar.attr('aria-valuenow', 0);
|
||||
//progressBar.attr('aria-valuemax', Array.from(files).length);
|
||||
if (zipFiles) {
|
||||
jszip = new JSZip();
|
||||
}
|
||||
|
||||
// Get existing form data
|
||||
let formData = new FormData($('form')[0]);
|
||||
formData.delete('fileInput');
|
||||
|
||||
const CONCURRENCY_LIMIT = 8;
|
||||
const chunks = [];
|
||||
for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
|
||||
chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
|
||||
}
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const promises = chunk.map(async file => {
|
||||
let fileFormData = new FormData();
|
||||
fileFormData.append('fileInput', file);
|
||||
|
||||
// Add other form data
|
||||
for (let pair of formData.entries()) {
|
||||
fileFormData.append(pair[0], pair[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
const downloadDetails = await handleSingleDownload(url, fileFormData);
|
||||
console.log(downloadDetails);
|
||||
if (zipFiles) {
|
||||
jszip.file(downloadDetails.filename, downloadDetails.blob);
|
||||
} else {
|
||||
downloadFile(downloadDetails.blob, downloadDetails.filename);
|
||||
}
|
||||
//updateProgressBar(progressBar, Array.from(files).length);
|
||||
} catch (error) {
|
||||
handleDownloadError(error);
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
if (zipFiles) {
|
||||
try {
|
||||
const content = await jszip.generateAsync({ type: "blob" });
|
||||
downloadFile(content, "files.zip");
|
||||
} catch (error) {
|
||||
console.error('Error generating ZIP file: ' + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updateProgressBar(progressBar, files) {
|
||||
let progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
|
||||
progressBar.css('width', progress + '%');
|
||||
progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
|
||||
}
|
||||
window.addEventListener('unload', () => {
|
||||
for (const url of urls) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
});
|
50
src/main/resources/static/js/errorBanner.js
Normal file
50
src/main/resources/static/js/errorBanner.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
var traceVisible = false;
|
||||
|
||||
function toggletrace() {
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (!traceVisible) {
|
||||
traceDiv.style.maxHeight = "500px";
|
||||
traceVisible = true;
|
||||
} else {
|
||||
traceDiv.style.maxHeight = "0px";
|
||||
traceVisible = false;
|
||||
}
|
||||
adjustContainerHeight();
|
||||
}
|
||||
|
||||
function copytrace() {
|
||||
var flip = false
|
||||
if (!traceVisible) {
|
||||
toggletrace()
|
||||
flip = true
|
||||
}
|
||||
var traceContent = document.getElementById("traceContent");
|
||||
var range = document.createRange();
|
||||
range.selectNode(traceContent);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
if (flip) {
|
||||
toggletrace()
|
||||
}
|
||||
}
|
||||
|
||||
function dismissError() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "none";
|
||||
errorContainer.style.height = "0";
|
||||
}
|
||||
|
||||
function adjustContainerHeight() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (traceVisible) {
|
||||
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
|
||||
} else {
|
||||
errorContainer.style.height = "auto";
|
||||
}
|
||||
}
|
||||
function showHelp() {
|
||||
$('#helpModal').modal('show');
|
||||
}
|
37
src/main/resources/static/js/favourites.js
Normal file
37
src/main/resources/static/js/favourites.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
function updateFavoritesDropdown() {
|
||||
var dropdown = document.querySelector('#favoritesDropdown');
|
||||
dropdown.innerHTML = ''; // Clear the current favorites
|
||||
|
||||
|
||||
|
||||
var hasFavorites = false;
|
||||
|
||||
for (var i = 0; i < localStorage.length; i++) {
|
||||
var key = localStorage.key(i);
|
||||
if (localStorage.getItem(key) === 'favorite') {
|
||||
// Find the corresponding navbar entry
|
||||
var navbarEntry = document.querySelector(`a[href='${key}']`);
|
||||
if (navbarEntry) {
|
||||
// Create a new dropdown entry
|
||||
var dropdownItem = document.createElement('a');
|
||||
dropdownItem.className = 'dropdown-item';
|
||||
dropdownItem.href = navbarEntry.href;
|
||||
dropdownItem.innerHTML = navbarEntry.innerHTML;
|
||||
dropdown.appendChild(dropdownItem);
|
||||
hasFavorites = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show or hide the default item based on whether there are any favorites
|
||||
if (!hasFavorites) {
|
||||
var defaultItem = document.createElement('a');
|
||||
defaultItem.className = 'dropdown-item';
|
||||
defaultItem.textContent = noFavourites;
|
||||
dropdown.appendChild(defaultItem);
|
||||
}
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
updateFavoritesDropdown();
|
||||
});
|
45
src/main/resources/static/js/fileInput.js
Normal file
45
src/main/resources/static/js/fileInput.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const fileInput = document.getElementById(elementID);
|
||||
|
||||
// Prevent default behavior for drag events
|
||||
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
||||
fileInput.addEventListener(eventName, preventDefaults, false);
|
||||
});
|
||||
|
||||
function preventDefaults(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// Add drop event listener
|
||||
fileInput.addEventListener('drop', handleDrop, false);
|
||||
|
||||
function handleDrop(e) {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
fileInput.files = files;
|
||||
handleFileInputChange(fileInput)
|
||||
}
|
||||
});
|
||||
|
||||
$(elementID).on("change", function() {
|
||||
handleFileInputChange(this);
|
||||
});
|
||||
|
||||
function handleFileInputChange(inputElement) {
|
||||
const files = $(inputElement).get(0).files;
|
||||
const fileNames = Array.from(files).map(f => f.name);
|
||||
const selectedFilesContainer = $(inputElement).siblings(".selected-files");
|
||||
selectedFilesContainer.empty();
|
||||
fileNames.forEach(fileName => {
|
||||
selectedFilesContainer.append("<div>" + fileName + "</div>");
|
||||
});
|
||||
console.log("fileNames.length=" + fileNames.length)
|
||||
if (fileNames.length === 1) {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
|
||||
} else if (fileNames.length > 1) {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames.length + " " + filesSelected);
|
||||
} else {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html(pdfPrompt);
|
||||
}
|
||||
}
|
41
src/main/resources/static/js/githubVersion.js
Normal file
41
src/main/resources/static/js/githubVersion.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
function compareVersions(version1, version2) {
|
||||
const v1 = version1.split('.');
|
||||
const v2 = version2.split('.');
|
||||
|
||||
for (let i = 0; i < v1.length || i < v2.length; i++) {
|
||||
const n1 = parseInt(v1[i]) || 0;
|
||||
const n2 = parseInt(v2[i]) || 0;
|
||||
|
||||
if (n1 > n2) {
|
||||
return 1;
|
||||
} else if (n1 < n2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
async function getLatestReleaseVersion() {
|
||||
const url = "https://api.github.com/repos/Frooodle/Stirling-PDF/releases/latest";
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
return data.tag_name.substring(1);
|
||||
}
|
||||
|
||||
|
||||
async function checkForUpdate() {
|
||||
const latestVersion = await getLatestReleaseVersion();
|
||||
console.log("latestVersion=" + latestVersion)
|
||||
console.log("currentVersion=" + currentVersion)
|
||||
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion))
|
||||
if (latestVersion != null && latestVersion != "" && compareVersions(latestVersion, currentVersion) > 0) {
|
||||
document.getElementById("update-btn").style.display = "block";
|
||||
console.log("visible")
|
||||
} else {
|
||||
document.getElementById("update-btn").style.display = "none";
|
||||
console.log("hidden")
|
||||
}
|
||||
}
|
||||
|
||||
checkForUpdate();
|
46
src/main/resources/static/js/languageSelection.js
Normal file
46
src/main/resources/static/js/languageSelection.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const defaultLocale = document.documentElement.lang || 'en_GB';
|
||||
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
|
||||
const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
|
||||
|
||||
for (let i = 0; i < dropdownItems.length; i++) {
|
||||
const item = dropdownItems[i];
|
||||
item.classList.remove('active');
|
||||
if (item.dataset.languageCode === storedLocale) {
|
||||
item.classList.add('active');
|
||||
}
|
||||
item.addEventListener('click', handleDropdownItemClick);
|
||||
}
|
||||
});
|
||||
|
||||
function handleDropdownItemClick(event) {
|
||||
event.preventDefault();
|
||||
const languageCode = this.dataset.languageCode;
|
||||
localStorage.setItem('languageCode', languageCode);
|
||||
|
||||
const currentUrl = window.location.href;
|
||||
if (currentUrl.indexOf('?lang=') === -1) {
|
||||
window.location.href = currentUrl + '?lang=' + languageCode;
|
||||
} else {
|
||||
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, '?lang=' + languageCode);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".nav-item.dropdown").each(function() {
|
||||
var $dropdownMenu = $(this).find(".dropdown-menu");
|
||||
if ($dropdownMenu.children().length <= 2 && $dropdownMenu.children("hr.dropdown-divider").length === $dropdownMenu.children().length) {
|
||||
$(this).prev('.nav-item.nav-item-separator').remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
//Sort languages by alphabet
|
||||
var list = $('.dropdown-menu[aria-labelledby="languageDropdown"]').children("a");
|
||||
list.sort(function(a, b) {
|
||||
var A = $(a).text().toUpperCase();
|
||||
var B = $(b).text().toUpperCase();
|
||||
return (A < B) ? -1 : (A > B) ? 1 : 0;
|
||||
})
|
||||
.appendTo('.dropdown-menu[aria-labelledby="languageDropdown"]');
|
||||
});
|
63
src/main/resources/static/js/merge.js
Normal file
63
src/main/resources/static/js/merge.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
document.getElementById("fileInput-input").addEventListener("change", function() {
|
||||
var files = this.files;
|
||||
var list = document.getElementById("selectedFiles");
|
||||
list.innerHTML = "";
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var item = document.createElement("li");
|
||||
item.className = "list-group-item";
|
||||
item.innerHTML = `
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<div class="filename">${files[i].name}</div>
|
||||
<div class="arrows d-flex">
|
||||
<button class="btn btn-secondary move-up"><span>↑</span></button>
|
||||
<button class="btn btn-secondary move-down"><span>↓</span></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
list.appendChild(item);
|
||||
}
|
||||
|
||||
var moveUpButtons = document.querySelectorAll(".move-up");
|
||||
for (var i = 0; i < moveUpButtons.length; i++) {
|
||||
moveUpButtons[i].addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var parent = this.closest(".list-group-item");
|
||||
var grandParent = parent.parentNode;
|
||||
if (parent.previousElementSibling) {
|
||||
grandParent.insertBefore(parent, parent.previousElementSibling);
|
||||
updateFiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var moveDownButtons = document.querySelectorAll(".move-down");
|
||||
for (var i = 0; i < moveDownButtons.length; i++) {
|
||||
moveDownButtons[i].addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var parent = this.closest(".list-group-item");
|
||||
var grandParent = parent.parentNode;
|
||||
if (parent.nextElementSibling) {
|
||||
grandParent.insertBefore(parent.nextElementSibling, parent);
|
||||
updateFiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateFiles() {
|
||||
var dataTransfer = new DataTransfer();
|
||||
var liElements = document.querySelectorAll("#selectedFiles li");
|
||||
|
||||
for (var i = 0; i < liElements.length; i++) {
|
||||
var fileNameFromList = liElements[i].querySelector(".filename").innerText;
|
||||
var fileFromFiles;
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
if (file.name === fileNameFromList) {
|
||||
dataTransfer.items.add(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById("fileInput-input").files = dataTransfer.files;
|
||||
}
|
||||
});
|
42
src/main/resources/static/js/settings.js
Normal file
42
src/main/resources/static/js/settings.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
// 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);
|
||||
});
|
||||
|
||||
|
||||
// Get the zipThreshold value from local storage, or set it to 0 if it doesn't exist
|
||||
var zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
|
||||
|
||||
// Set the value of the slider and the display span
|
||||
document.getElementById('zipThreshold').value = zipThreshold;
|
||||
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
||||
|
||||
|
||||
|
||||
// Save the selected value to local storage when the slider value changes
|
||||
document.getElementById('zipThreshold').addEventListener('input', function() {
|
||||
zipThreshold = this.value;
|
||||
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
||||
localStorage.setItem('zipThreshold', zipThreshold);
|
||||
});
|
||||
|
||||
|
||||
var boredWaiting = localStorage.getItem('boredWaiting') || 'disabled';
|
||||
document.getElementById('boredWaiting').checked = boredWaiting === 'enabled';
|
||||
|
||||
document.getElementById('boredWaiting').addEventListener('change', function() {
|
||||
boredWaiting = this.checked ? 'enabled' : 'disabled';
|
||||
localStorage.setItem('boredWaiting', boredWaiting);
|
||||
});
|
|
@ -34,84 +34,7 @@
|
|||
<script src="js/tab-container.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
var toggleCount = 0;
|
||||
var lastToggleTime = Date.now();
|
||||
|
||||
function toggleDarkMode() {
|
||||
var currentTime = Date.now();
|
||||
if (currentTime - lastToggleTime < 1000) {
|
||||
toggleCount++;
|
||||
} else {
|
||||
toggleCount = 1;
|
||||
}
|
||||
lastToggleTime = currentTime;
|
||||
|
||||
var lightModeStyles = document.getElementById("light-mode-styles");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var rainbowModeStyles = document.getElementById("rainbow-mode-styles");
|
||||
var darkModeIcon = document.getElementById("dark-mode-icon");
|
||||
|
||||
if (toggleCount >= 18) {
|
||||
localStorage.setItem("dark-mode", "rainbow");
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = false;
|
||||
darkModeIcon.src = "rainbow.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "on") {
|
||||
localStorage.setItem("dark-mode", "off");
|
||||
lightModeStyles.disabled = false;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
} else {
|
||||
localStorage.setItem("dark-mode", "on");
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var lightModeStyles = document.getElementById("light-mode-styles");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var rainbowModeStyles = document.getElementById("rainbow-mode-styles");
|
||||
var darkModeIcon = document.getElementById("dark-mode-icon");
|
||||
|
||||
if (localStorage.getItem("dark-mode") == "on") {
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "off") {
|
||||
lightModeStyles.disabled = false;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
} else if (localStorage.getItem("dark-mode") == "rainbow") {
|
||||
lightModeStyles.disabled = true;
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = false;
|
||||
darkModeIcon.src = "rainbow.svg";
|
||||
} else {
|
||||
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
darkModeStyles.disabled = false;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "moon.svg";
|
||||
} else {
|
||||
darkModeStyles.disabled = true;
|
||||
rainbowModeStyles.disabled = true;
|
||||
darkModeIcon.src = "sun.svg";
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("dark-mode-toggle").addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
toggleDarkMode();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="js/darkmode.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
|
@ -168,214 +91,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
</th:block>
|
||||
|
||||
<th:block th:fragment="fileSelector(name, multiple)" th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: 'true', notRequired=${notRequired} ?: false">
|
||||
<script>
|
||||
function showErrorBanner(message, stackTrace) {
|
||||
const errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "block"; // Display the banner
|
||||
document.querySelector("#errorContainer .alert-heading").textContent = "Error";
|
||||
document.querySelector("#errorContainer p").textContent = message;
|
||||
document.querySelector("#traceContent").textContent = stackTrace;
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('form').submit(async function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
const url = this.action;
|
||||
const files = $('#fileInput-input')[0].files;
|
||||
const formData = new FormData(this);
|
||||
const override = $('#override').val() || '';
|
||||
|
||||
$('#submitBtn').text('Processing...');
|
||||
|
||||
try {
|
||||
if (override === 'multi' || files.length > 1 && override !== 'single') {
|
||||
await submitMultiPdfForm(url, files);
|
||||
} else {
|
||||
const downloadDetails = await handleSingleDownload(url, formData);
|
||||
|
||||
// Determine the download option from localStorage
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
// Handle the download action according to the selected option
|
||||
handleDownloadAction(downloadOption, downloadDetails.blob, downloadDetails.filename);
|
||||
}
|
||||
|
||||
$('#submitBtn').text('Submit');
|
||||
} catch (error) {
|
||||
handleDownloadError(error);
|
||||
$('#submitBtn').text('Submit');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleDownloadAction(downloadOption, blob, filename) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
switch (downloadOption) {
|
||||
case 'sameWindow':
|
||||
// Open the file in the same window
|
||||
window.location.href = url;
|
||||
break;
|
||||
case 'newWindow':
|
||||
// Open the file in a new window
|
||||
window.open(url, '_blank');
|
||||
break;
|
||||
default:
|
||||
// Download the file
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
link.click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSingleDownload(url, formData) {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
} else {
|
||||
const blob = await response.blob();
|
||||
const filename = getFilenameFromContentDisposition(response.headers.get('Content-Disposition'));
|
||||
return { blob, filename };
|
||||
}
|
||||
}
|
||||
function getFilenameFromContentDisposition(contentDisposition) {
|
||||
let filename;
|
||||
|
||||
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
|
||||
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, ''));
|
||||
} else {
|
||||
// If the Content-Disposition header is not present or does not contain the filename, use a default filename
|
||||
filename = 'download';
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
async function handlePdfOrImageResponse(response, filename) {
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
const blob = await response.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
if (downloadOption === 'sameWindow') {
|
||||
window.location.href = url;
|
||||
} else if (downloadOption === 'newWindow') {
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
downloadFile(url, filename);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleJsonResponse(response) {
|
||||
const json = await response.json();
|
||||
const errorMessage = JSON.stringify(json, null, 2);
|
||||
if(errorMessage.toLowerCase().includes('the password is incorrect') || errorMessage.toLowerCase().includes('Password is not provided')){
|
||||
alert('[[#{error.pdfPassword}]]');
|
||||
} else {
|
||||
showErrorBanner(json.error + ':' + json.message, json.trace);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleOtherResponse(response, filename) {
|
||||
const blob = await response.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
downloadFile(url, filename);
|
||||
}
|
||||
function handleDownloadError(error) {
|
||||
const errorMessage = error.message;
|
||||
showErrorBanner(errorMessage);
|
||||
}
|
||||
|
||||
let urls = []; // An array to hold all the URLs
|
||||
|
||||
function downloadFile(blob, filename) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
a.click();
|
||||
urls.push(url); // Store the URL so it doesn't get garbage collected too soon
|
||||
}
|
||||
|
||||
|
||||
async function submitMultiPdfForm(url, files) {
|
||||
const zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
|
||||
const zipFiles = files.length > zipThreshold;
|
||||
let jszip = null;
|
||||
let progressBar = $('#progressBar');
|
||||
progressBar.css('width', '0%');
|
||||
progressBar.attr('aria-valuenow', 0);
|
||||
progressBar.attr('aria-valuemax', Array.from(files).length);
|
||||
if (zipFiles) {
|
||||
jszip = new JSZip();
|
||||
}
|
||||
|
||||
// Get existing form data
|
||||
let formData = new FormData($('form')[0]);
|
||||
formData.delete('fileInput');
|
||||
|
||||
const CONCURRENCY_LIMIT = 8;
|
||||
const chunks = [];
|
||||
for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
|
||||
chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
|
||||
}
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const promises = chunk.map(async file => {
|
||||
let fileFormData = new FormData();
|
||||
fileFormData.append('fileInput', file);
|
||||
|
||||
// Add other form data
|
||||
for (let pair of formData.entries()) {
|
||||
fileFormData.append(pair[0], pair[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
const downloadDetails = await handleSingleDownload(url, fileFormData);
|
||||
if (zipFiles) {
|
||||
jszip.file(downloadDetails.filename, downloadDetails.blob);
|
||||
} else {
|
||||
downloadFile(downloadDetails.blob, downloadDetails.filename);
|
||||
}
|
||||
updateProgressBar(progressBar, Array.from(files).length);
|
||||
} catch (error) {
|
||||
handleDownloadError(error);
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
if (zipFiles) {
|
||||
try {
|
||||
const content = await jszip.generateAsync({ type: "blob" });
|
||||
downloadFile(content, "files.zip");
|
||||
} catch (error) {
|
||||
console.error('Error generating ZIP file: ' + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updateProgressBar(progressBar, files) {
|
||||
let progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
|
||||
progressBar.css('width', progress + '%');
|
||||
progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
|
||||
}
|
||||
window.addEventListener('unload', () => {
|
||||
for (const url of urls) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
<script src="js/downloader.js"></script>
|
||||
|
||||
<div class="custom-file-chooser">
|
||||
<div class="custom-file">
|
||||
|
@ -394,65 +110,12 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
<button type="button" class="btn btn-primary" id="show-game-btn" style="display:none;">Bored waiting?</button>
|
||||
|
||||
|
||||
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const fileInput = document.getElementById([[${name+"-input"}]]);
|
||||
|
||||
// Prevent default behavior for drag events
|
||||
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
||||
fileInput.addEventListener(eventName, preventDefaults, false);
|
||||
});
|
||||
|
||||
function preventDefaults(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// Add drop event listener
|
||||
fileInput.addEventListener('drop', handleDrop, false);
|
||||
|
||||
function handleDrop(e) {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
fileInput.files = files;
|
||||
handleFileInputChange(fileInput)
|
||||
}
|
||||
});
|
||||
|
||||
$([[${"#"+name+"-input"}]]).on("change", function() {
|
||||
handleFileInputChange(this);
|
||||
});
|
||||
|
||||
function handleFileInputChange(inputElement) {
|
||||
const files = $(inputElement).get(0).files;
|
||||
const fileNames = Array.from(files).map(f => f.name);
|
||||
const selectedFilesContainer = $(inputElement).siblings(".selected-files");
|
||||
selectedFilesContainer.empty();
|
||||
fileNames.forEach(fileName => {
|
||||
selectedFilesContainer.append("<div>" + fileName + "</div>");
|
||||
});
|
||||
console.log("fileNames.length=" + fileNames.length)
|
||||
if (fileNames.length === 1) {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
|
||||
} else if (fileNames.length > 1) {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames.length + " " + [[#{filesSelected}]]);
|
||||
} else {
|
||||
$(inputElement).siblings(".custom-file-label").addClass("selected").html([[#{pdfPrompt}]]);
|
||||
}
|
||||
}
|
||||
const elementID = /*[[${name+"-input"}]]*/ '';
|
||||
const filesSelected = /*[[#{filesSelected}]]*/ '';
|
||||
const pdfPrompt = /*[[#{pdfPrompt}]]*/ '';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.custom-file-label {
|
||||
padding-right: 90px;
|
||||
}
|
||||
.selected-files {
|
||||
margin-top: 10px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="js/fileInput.js"></script>
|
||||
<link rel="stylesheet" href="css/fileSelect.css">
|
||||
</th:block>
|
|
@ -54,56 +54,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var traceVisible = false;
|
||||
|
||||
function toggletrace() {
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (!traceVisible) {
|
||||
traceDiv.style.maxHeight = "500px";
|
||||
traceVisible = true;
|
||||
} else {
|
||||
traceDiv.style.maxHeight = "0px";
|
||||
traceVisible = false;
|
||||
}
|
||||
adjustContainerHeight();
|
||||
}
|
||||
|
||||
function copytrace() {
|
||||
var flip = false
|
||||
if(!traceVisible) {
|
||||
toggletrace()
|
||||
flip = true
|
||||
}
|
||||
var traceContent = document.getElementById("traceContent");
|
||||
var range = document.createRange();
|
||||
range.selectNode(traceContent);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
if(flip){
|
||||
toggletrace()
|
||||
}
|
||||
}
|
||||
|
||||
function dismissError() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "none";
|
||||
errorContainer.style.height ="0";
|
||||
}
|
||||
|
||||
function adjustContainerHeight() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (traceVisible) {
|
||||
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
|
||||
} else {
|
||||
errorContainer.style.height = "auto";
|
||||
}
|
||||
}
|
||||
function showHelp() {
|
||||
$('#helpModal').modal('show');
|
||||
}
|
||||
</script>
|
||||
<script src="js/errorBanner.js"></script>
|
||||
</th:block>
|
|
@ -1,78 +1,11 @@
|
|||
<div th:fragment="navbar" class="mx-auto">
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const defaultLocale = document.documentElement.lang || 'en_GB';
|
||||
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
|
||||
const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
|
||||
|
||||
for (let i = 0; i < dropdownItems.length; i++) {
|
||||
const item = dropdownItems[i];
|
||||
item.classList.remove('active');
|
||||
if (item.dataset.languageCode === storedLocale) {
|
||||
item.classList.add('active');
|
||||
}
|
||||
item.addEventListener('click', handleDropdownItemClick);
|
||||
}
|
||||
});
|
||||
|
||||
function handleDropdownItemClick(event) {
|
||||
event.preventDefault();
|
||||
const languageCode = this.dataset.languageCode;
|
||||
localStorage.setItem('languageCode', languageCode);
|
||||
|
||||
const currentUrl = window.location.href;
|
||||
if (currentUrl.indexOf('?lang=') === -1) {
|
||||
window.location.href = currentUrl + '?lang=' + languageCode;
|
||||
} else {
|
||||
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, '?lang=' + languageCode);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script src="js/languageSelection.js"></script>
|
||||
|
||||
<script th:inline="javascript">
|
||||
function compareVersions(version1, version2) {
|
||||
const v1 = version1.split('.');
|
||||
const v2 = version2.split('.');
|
||||
|
||||
for (let i = 0; i < v1.length || i < v2.length; i++) {
|
||||
const n1 = parseInt(v1[i]) || 0;
|
||||
const n2 = parseInt(v2[i]) || 0;
|
||||
|
||||
if (n1 > n2) {
|
||||
return 1;
|
||||
} else if (n1 < n2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
async function getLatestReleaseVersion() {
|
||||
const url = "https://api.github.com/repos/Frooodle/Stirling-PDF/releases/latest";
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
return data.tag_name.substring(1);
|
||||
}
|
||||
|
||||
const currentVersion = /*[[${@appVersion}]]*/ ''; // Replace with your current version number
|
||||
|
||||
async function checkForUpdate() {
|
||||
const latestVersion = await getLatestReleaseVersion();
|
||||
console.log("latestVersion=" + latestVersion)
|
||||
console.log("currentVersion=" + currentVersion)
|
||||
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion))
|
||||
if (latestVersion != null && latestVersion != "" && compareVersions(latestVersion, currentVersion) > 0) {
|
||||
document.getElementById("update-btn").style.display = "block";
|
||||
console.log("visible")
|
||||
} else {
|
||||
document.getElementById("update-btn").style.display = "none";
|
||||
console.log("hidden")
|
||||
}
|
||||
}
|
||||
|
||||
checkForUpdate();
|
||||
const currentVersion = /*[[${@appVersion}]]*/ '';
|
||||
const noFavourites = /*[[#{noFavourites}]]*/ '';
|
||||
</script>
|
||||
<script th:src="@{/js/githubVersion.js}"></script>
|
||||
|
||||
<link rel="stylesheet" href="css/navbar.css">
|
||||
|
||||
|
@ -263,48 +196,7 @@ function compareVersions(version1, version2) {
|
|||
</div>
|
||||
|
||||
</div>
|
||||
<script th:inline="javascript">
|
||||
|
||||
|
||||
function updateFavoritesDropdown() {
|
||||
var dropdown = document.querySelector('#favoritesDropdown');
|
||||
dropdown.innerHTML = ''; // Clear the current favorites
|
||||
|
||||
|
||||
|
||||
var hasFavorites = false;
|
||||
|
||||
for (var i = 0; i < localStorage.length; i++) {
|
||||
var key = localStorage.key(i);
|
||||
if (localStorage.getItem(key) === 'favorite') {
|
||||
// Find the corresponding navbar entry
|
||||
var navbarEntry = document.querySelector(`a[href='${key}']`);
|
||||
if (navbarEntry) {
|
||||
// Create a new dropdown entry
|
||||
var dropdownItem = document.createElement('a');
|
||||
dropdownItem.className = 'dropdown-item';
|
||||
dropdownItem.href = navbarEntry.href;
|
||||
dropdownItem.innerHTML = navbarEntry.innerHTML;
|
||||
dropdown.appendChild(dropdownItem);
|
||||
hasFavorites = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show or hide the default item based on whether there are any favorites
|
||||
if(!hasFavorites){
|
||||
var defaultItem = document.createElement('a');
|
||||
defaultItem.className = 'dropdown-item';
|
||||
defaultItem.textContent = [[#{noFavourites}]]
|
||||
dropdown.appendChild(defaultItem);
|
||||
}
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
updateFavoritesDropdown();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="js/favourites.js"></script>
|
||||
</nav>
|
||||
|
||||
<div th:insert="~{fragments/errorBannerPerPage.html :: errorBannerPerPage}"></div>
|
||||
|
@ -363,73 +255,7 @@ function compareVersions(version1, version2) {
|
|||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".nav-item.dropdown").each(function() {
|
||||
var $dropdownMenu = $(this).find(".dropdown-menu");
|
||||
if ($dropdownMenu.children().length <= 2 && $dropdownMenu.children("hr.dropdown-divider").length === $dropdownMenu.children().length) {
|
||||
$(this).prev('.nav-item.nav-item-separator').remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
//Sort languages by alphabet
|
||||
var list = $('.dropdown-menu[aria-labelledby="languageDropdown"]').children("a");
|
||||
list.sort(function(a, b) {
|
||||
var A = $(a).text().toUpperCase();
|
||||
var B = $(b).text().toUpperCase();
|
||||
return (A < B) ? -1 : (A > B) ? 1 : 0;
|
||||
})
|
||||
.appendTo('.dropdown-menu[aria-labelledby="languageDropdown"]');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
|
||||
// Get the zipThreshold value from local storage, or set it to 0 if it doesn't exist
|
||||
var zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
|
||||
|
||||
// Set the value of the slider and the display span
|
||||
document.getElementById('zipThreshold').value = zipThreshold;
|
||||
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
||||
|
||||
|
||||
|
||||
// Save the selected value to local storage when the slider value changes
|
||||
document.getElementById('zipThreshold').addEventListener('input', function () {
|
||||
zipThreshold = this.value;
|
||||
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
||||
localStorage.setItem('zipThreshold', zipThreshold);
|
||||
});
|
||||
|
||||
|
||||
var boredWaiting = localStorage.getItem('boredWaiting') || 'disabled';
|
||||
document.getElementById('boredWaiting').checked = boredWaiting === 'enabled';
|
||||
|
||||
document.getElementById('boredWaiting').addEventListener('change', function() {
|
||||
boredWaiting = this.checked ? 'enabled' : 'disabled';
|
||||
localStorage.setItem('boredWaiting', boredWaiting);
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="js/settings.js"></script>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,72 +27,7 @@
|
|||
</div>
|
||||
</form>
|
||||
<link rel="stylesheet" href="css/merge.css">
|
||||
<script>
|
||||
document.getElementById("fileInput-input").addEventListener("change", function() {
|
||||
var files = this.files;
|
||||
var list = document.getElementById("selectedFiles");
|
||||
list.innerHTML = "";
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var item = document.createElement("li");
|
||||
item.className = "list-group-item";
|
||||
item.innerHTML = `
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<div class="filename">${files[i].name}</div>
|
||||
<div class="arrows d-flex">
|
||||
<button class="btn btn-secondary move-up"><span>↑</span></button>
|
||||
<button class="btn btn-secondary move-down"><span>↓</span></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
list.appendChild(item);
|
||||
}
|
||||
|
||||
var moveUpButtons = document.querySelectorAll(".move-up");
|
||||
for (var i = 0; i < moveUpButtons.length; i++) {
|
||||
moveUpButtons[i].addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var parent = this.closest(".list-group-item");
|
||||
var grandParent = parent.parentNode;
|
||||
if (parent.previousElementSibling) {
|
||||
grandParent.insertBefore(parent, parent.previousElementSibling);
|
||||
updateFiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var moveDownButtons = document.querySelectorAll(".move-down");
|
||||
for (var i = 0; i < moveDownButtons.length; i++) {
|
||||
moveDownButtons[i].addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var parent = this.closest(".list-group-item");
|
||||
var grandParent = parent.parentNode;
|
||||
if (parent.nextElementSibling) {
|
||||
grandParent.insertBefore(parent.nextElementSibling, parent);
|
||||
updateFiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateFiles() {
|
||||
var dataTransfer = new DataTransfer();
|
||||
var liElements = document.querySelectorAll("#selectedFiles li");
|
||||
|
||||
for (var i = 0; i < liElements.length; i++) {
|
||||
var fileNameFromList = liElements[i].querySelector(".filename").innerText;
|
||||
var fileFromFiles;
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
if (file.name === fileNameFromList) {
|
||||
dataTransfer.items.add(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById("fileInput-input").files = dataTransfer.files;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<script src="js/merge.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue