diff --git a/app/static/js/nopaque/main.js b/app/static/js/nopaque/main.js index 118af400..a998656b 100644 --- a/app/static/js/nopaque/main.js +++ b/app/static/js/nopaque/main.js @@ -5,72 +5,151 @@ var nopaque = {}; nopaque.Forms = {}; -nopaque.Forms.init = function() { - var abortRequestElement, parentElement, progressElement, progressModal, - progressModalElement, request, submitElement; +nopaque.Forms.autoInit = () => { + const nopaqueSubmitForms = document.querySelectorAll('.nopaque-submit-form'); + let nopaqueSubmitForm; - for (let form of document.querySelectorAll(".nopaque-submit-form")) { - submitElement = form.querySelector('button[type="submit"]'); - submitElement.addEventListener("click", function() { - for (let selectElement of form.querySelectorAll('select')) { - if (selectElement.value === "") { - parentElement = selectElement.closest(".input-field"); - parentElement.querySelector(".select-dropdown").classList.add("invalid"); - for (let helperTextElement of parentElement.querySelectorAll(".helper-text")) { + for (nopaqueSubmitForm of nopaqueSubmitForms) { + nopaqueSubmitForm.addEventListener('submit', (event) => { + event.preventDefault(); + + const request = new XMLHttpRequest(); + const selectElements = nopaqueSubmitForm.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(); } - parentElement.insertAdjacentHTML("beforeend", `Please select an option.`); + inputFieldElement.insertAdjacentHTML( + 'beforeend', + 'Please select an option.' + ); + return; } } - }); - request = new XMLHttpRequest(); - if (form.dataset.hasOwnProperty("progressModal")) { - progressModalElement = document.getElementById(form.dataset.progressModal); - progressModal = M.Modal.getInstance(progressModalElement); - progressModal.options.dismissible = false; - abortRequestElement = progressModalElement.querySelector(".abort-request"); - abortRequestElement.addEventListener("click", function() {request.abort();}); - progressElement = progressModalElement.querySelector(".determinate"); - } - form.addEventListener("submit", function(event) { - event.preventDefault(); - var formData; - - formData = new FormData(form); - // Initialize progress modal - if (progressModalElement) { - progressElement.style.width = "0%"; - progressModal.open(); - } - request.open("POST", window.location.href); - request.send(formData); - }); - request.addEventListener("load", function(event) { - var fieldElement; - - if (request.status === 201) { - window.location.href = JSON.parse(this.responseText).redirect_url; - } - if (request.status === 400) { - for (let [field, errors] of Object.entries(JSON.parse(this.responseText))) { - fieldElement = form.querySelector(`input[name$="${field}"]`).closest(".input-field"); - for (let error of errors) { - fieldElement.insertAdjacentHTML("beforeend", `${error}`); + // Setup modal + tmp = document.createElement('div'); + tmp.innerHTML = ` + + `.trim(); + modalElement = document.querySelector('#modals').appendChild(tmp.firstChild); + modal = M.Modal.init( + modalElement, + { + dismissible: false, + onCloseEnd: () => { + modal.destroy(); + modalElement.remove(); } } - if (progressModalElement) { - progressModal.close(); - } - } - if (request.status === 500) { - location.reload(); - } - }); - if (progressModalElement) { - request.upload.addEventListener("progress", function(event) { - progressElement.style.width = Math.floor(100 * event.loaded / event.total).toString() + "%"; + ); + modal.open(); + + // Setup abort handling + abortElement = modalElement.querySelector('.abort'); + abortElement.addEventListener('click', event => {request.abort();}); + request.addEventListener('abort', event => { + request.abort(); + modal.close(); }); + + // Setup load handling (after the request completed) + request.addEventListener('load', event => { + const response = JSON.parse(request.responseText); + let inputError; + let inputErrors; + let inputFieldElement; + let inputName; + + if (request.status === 201) { + window.location.href = response.redirect_url; + } + if (request.status === 400) { + for ([inputName, inputErrors] of Object.entries(response)) { + inputFieldElement = nopaqueSubmitForm.querySelector(`input[name="${inputName}"], select[name="${inputName}"]`).closest('.input-field'); + for (inputError of inputErrors) { + inputFieldElement.insertAdjacentHTML( + 'beforeend', + `${inputError}` + ); + } + } + } + if (request.status === 500) { + location.reload(); + } + modal.close(); + }); + + // Setup progress handling + progressElement = modalElement.querySelector('.progress > .determinate'); + request.upload.addEventListener('progress', event => { + const progress = Math.floor(100 * event.loaded / event.total); + progressElement.style.width = `${progress}%`; + }); + + request.open('POST', window.location.href); + request.send(new FormData(nopaqueSubmitForm)); + }); + } +} + + +nopaque.RessourceList = {}; +nopaque.RessourceList.autoInit = () => { + const nopaqueRessourceListElements = document.querySelectorAll('.nopaque-ressource-list[data-ressource-type]:not(.no-autoinit)'); + let nopaqueRessourceListElement; + + for (nopaqueRessourceListElement of nopaqueRessourceListElements) { + switch (nopaqueRessourceListElement.dataset.ressourceType) { + case 'Corpus': + new CorpusList(nopaqueRessourceListElement); + break; + case 'CorpusFile': + new CorpusFileList(nopaqueRessourceListElement); + break; + case 'Job': + new JobList(nopaqueRessourceListElement); + break; + case 'JobInput': + new JobInputList(nopaqueRessourceListElement); + break; + case 'JobResult': + new JobResultList(nopaqueRessourceListElement); + break; + case 'QueryResult': + new QueryResultList(nopaqueRessourceListElement); + break; + case 'User': + new UserList(nopaqueRessourceListElement); + break; + default: + break; } } } diff --git a/app/templates/_scripts.html.j2 b/app/templates/_scripts.html.j2 index e030a920..ca9b2591 100644 --- a/app/templates/_scripts.html.j2 +++ b/app/templates/_scripts.html.j2 @@ -40,33 +40,7 @@ app.addEventListener('users.patch', patch => jobStatusNotifier.usersPatchHandler(patch)); app.getUserById(currentUserId).then(user => {}, error => {throw JSON.stringify(error)}); {% endif %} - nopaque.Forms.init(); - for (let nopaqueRessourceListElement of document.querySelectorAll('.nopaque-ressource-list[data-ressource-type]:not(.no-autoinit)')) { - switch (nopaqueRessourceListElement.dataset.ressourceType) { - case 'Corpus': - new CorpusList(nopaqueRessourceListElement); - break; - case 'CorpusFile': - new CorpusFileList(nopaqueRessourceListElement); - break; - case 'Job': - new JobList(nopaqueRessourceListElement); - break; - case 'JobInput': - new JobInputList(nopaqueRessourceListElement); - break; - case 'JobResult': - new JobResultList(nopaqueRessourceListElement); - break; - case 'QueryResult': - new QueryResultList(nopaqueRessourceListElement); - break; - case 'User': - new UserList(nopaqueRessourceListElement); - break; - default: - break; - } - } + nopaque.Forms.autoInit(); + nopaque.RessourceList.autoInit(); for (let flashedMessage of {{ get_flashed_messages(with_categories=True)|tojson }}) {app.flash(flashedMessage[1], flashedMessage[0]);} diff --git a/app/templates/services/nlp.html.j2 b/app/templates/services/nlp.html.j2 index e24d867c..6132b322 100644 --- a/app/templates/services/nlp.html.j2 +++ b/app/templates/services/nlp.html.j2 @@ -127,7 +127,7 @@ {% block scripts %} {{ super() }}