mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
97 lines
3.9 KiB
JavaScript
97 lines
3.9 KiB
JavaScript
/**
|
|
* upload-progress.js
|
|
*
|
|
* Intercepts admin form submissions (add.php / edit.php) and submits via
|
|
* XMLHttpRequest to display a progress bar for large file uploads.
|
|
* Falls back to native form POST when JavaScript is unavailable.
|
|
*
|
|
* Requires an element with id="upload-progress-bar" inside the form.
|
|
* The progress bar is normally hidden (display:none), shown only during upload.
|
|
*/
|
|
(() => {
|
|
'use strict';
|
|
|
|
const FORMS = document.querySelectorAll('form[data-upload-progress]');
|
|
if (!FORMS.length) return;
|
|
|
|
for (const form of FORMS) {
|
|
const progressWrap = form.querySelector('#upload-progress-wrap');
|
|
const progressBar = form.querySelector('#upload-progress-bar');
|
|
const progressText = form.querySelector('#upload-progress-text');
|
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
|
|
if (!progressBar || !progressWrap) continue;
|
|
|
|
form.addEventListener('submit', function (e) {
|
|
// Only intercept if files are actually attached (FilePond inputs have files)
|
|
const fileInputs = form.querySelectorAll('input[type="file"]');
|
|
let hasFiles = false;
|
|
for (const fi of fileInputs) {
|
|
if (fi.files && fi.files.length > 0) {
|
|
hasFiles = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasFiles) return; // let native submit handle it
|
|
|
|
e.preventDefault();
|
|
|
|
// Show progress bar
|
|
progressWrap.style.display = 'block';
|
|
progressBar.value = 0;
|
|
progressText.textContent = '0%';
|
|
if (submitBtn) submitBtn.disabled = true;
|
|
|
|
// Build FormData
|
|
const fd = new FormData(form);
|
|
// Ensure any FilePond-managed files are included — FilePond with
|
|
// storeAsFile:true copies files into the <input>.files, so FormData
|
|
// picks them up automatically from the DOM inputs.
|
|
// But we must also respect queue_order hidden inputs.
|
|
// FormData(form) already handles this since it reads all form fields.
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
|
|
xhr.upload.addEventListener('progress', function (evt) {
|
|
if (evt.lengthComputable) {
|
|
const pct = Math.round((evt.loaded / evt.total) * 100);
|
|
progressBar.value = pct;
|
|
progressText.textContent = pct + '%';
|
|
}
|
|
});
|
|
|
|
xhr.addEventListener('load', function () {
|
|
// Server returns a redirect (302) on success, or re-renders the form on error.
|
|
// We can't follow 302 with XHR directly — the response body is the target page.
|
|
// Check if we got a redirect by examining the response URL.
|
|
const finalUrl = xhr.responseURL || '';
|
|
const isRedirect = xhr.status >= 200 && xhr.status < 300 && finalUrl !== '' && !finalUrl.endsWith(form.action);
|
|
|
|
if (isRedirect) {
|
|
// Success — navigate to the redirect target
|
|
window.location.href = finalUrl;
|
|
} else {
|
|
// Error — the server returned the form HTML with flash messages.
|
|
// Replace the current page content.
|
|
document.open();
|
|
document.write(xhr.responseText);
|
|
document.close();
|
|
}
|
|
});
|
|
|
|
xhr.addEventListener('error', function () {
|
|
progressText.textContent = 'Erreur réseau';
|
|
if (submitBtn) submitBtn.disabled = false;
|
|
});
|
|
|
|
xhr.addEventListener('abort', function () {
|
|
progressWrap.style.display = 'none';
|
|
if (submitBtn) submitBtn.disabled = false;
|
|
});
|
|
|
|
xhr.open('POST', form.action, true);
|
|
xhr.send(fd);
|
|
});
|
|
}
|
|
})();
|