nopaque/app/static/js/UploadForm.js
2021-12-09 12:50:14 +01:00

126 lines
3.8 KiB
JavaScript

class UploadForm {
static autoInit() {
const nopaqueSubmitForms = document.querySelectorAll('.nopaque-upload-form');
let nopaqueSubmitForm;
for (nopaqueSubmitForm of nopaqueSubmitForms) {
new UploadForm(nopaqueSubmitForm);
}
}
constructor(formElement) {
this.formElement = formElement;
this.request = new XMLHttpRequest();
this.formElement.addEventListener('submit', (event) => {
event.preventDefault();
this.submit();
});
}
submit() {
const selectElements = this.formElement.querySelectorAll('select');
let abortElement;
let helperTextElement;
let helperTextElements;
let inputFieldElement;
let modal;
let modalElement;
let progressElement;
let selectElement;
let tmp;
// Check if select elements are filled out properly
for (selectElement of selectElements) {
if (selectElement.value === '') {
inputFieldElement = selectElement.closest('.input-field');
inputFieldElement.querySelector('.select-dropdown').classList.add('invalid');
helperTextElements = inputFieldElement.querySelectorAll('.helper-text');
for (helperTextElement of helperTextElements) {
helperTextElement.remove();
}
inputFieldElement.insertAdjacentHTML(
'beforeend',
'<span class="helper-text error-color-text">Please select an option.</span>'
);
return;
}
}
// Setup modal
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4><i class="material-icons left">file_upload</i>Uploading files...</h4>
<div class="progress">
<div class="determinate" style="width: 0%"></div>
</div>
</div>
<div class="modal-footer">
<a href="#!" class="btn red waves-effect waves-light abort">Cancel</a>
</div>
</div>
`.trim();
modalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
modal = M.Modal.init(
modalElement,
{
dismissible: false,
onCloseEnd: () => {
modal.destroy();
modalElement.remove();
}
}
);
modal.open();
// Setup abort handling
abortElement = modalElement.querySelector('.abort');
abortElement.addEventListener('click', event => {this.request.abort();});
this.request.addEventListener('abort', event => {
this.request.abort();
modal.close();
});
// Setup load handling (after the request completed)
this.request.addEventListener('load', event => {
const response = JSON.parse(this.request.responseText);
let inputError;
let inputErrors;
let inputFieldElement;
let inputName;
if (this.request.status === 201) {
window.location.href = response.redirect_url;
}
if (this.request.status === 400) {
for ([inputName, inputErrors] of Object.entries(response)) {
inputFieldElement = this.formElement.querySelector(`input[name="${inputName}"], select[name="${inputName}"]`).closest('.input-field');
for (inputError of inputErrors) {
inputFieldElement.insertAdjacentHTML(
'beforeend',
`<span class="helper-text red-text">${inputError}</span>`
);
}
}
}
if (this.request.status === 500) {
location.reload();
}
modal.close();
});
// Setup progress handling
progressElement = modalElement.querySelector('.progress > .determinate');
this.request.upload.addEventListener('progress', event => {
const progress = Math.floor(100 * event.loaded / event.total);
progressElement.style.width = `${progress}%`;
});
this.request.open('POST', window.location.href);
this.request.send(new FormData(this.formElement));
}
}