// // Javascripts für VERO // // Roland Keck (2025) // document.addEventListener('DOMContentLoaded', function () { hide("author",2,9); hide("abstract",2,3); hide("identificator",2,5); hide("subject",2,10); // hide("divCreativeCommons",1,1); // hide("cc0commercial",1,1); // hide("cc0share", 1, 1); hide("publisherInEditedVolume",2,9); hideElement("divErstveroeffentlichungOpenAccess"); hideElement("divErstveroeffentlichungUrheberrecht"); hideElement("divZweitveroeffentlichungOpenAccess"); hideElement("Select4A4B"); hideElement("divZweitUrh4A"); hideElement("divErstUrh"); hideElement("divZweitUrh4B"); hideElement("divCommon"); hideElement("erstVeroeffentlichtSection"); hideElement("mitteilungSection"); } ) function hide(FieldName, start, end) { for (let i = start; i <= end; i++) { hideElement(FieldName + i); // document.getElementById(FieldName + i).style.display = 'none'; } } function hideElement(ele) { var present = document.getElementById(ele); if (present) { present.style.display = 'none'; } } function showElement(ele) { var present = document.getElementById(ele); if (present) { present.style.display = 'block'; } } function insert(FieldName,pos,max) { let a = pos -1 let ret = false switch(FieldName) { case 'author': if (a > 1) { // special case: first author is not an input!! ret = validateNameFormat(FieldName, a); if (ret === false) return; } break; case 'publisherInEditedVolume': ret = validateEmptyEntry(FieldName, a); if (ret === false) return; break; default: break; } document.getElementById(FieldName + pos).style.display = 'block'; if (pos < max) { document.getElementById("button-add-" + FieldName +'-' + pos).style.display = 'block';} document.getElementById("button-del-" + FieldName +'-' + pos).style.display = 'block'; document.getElementById("button-add-" + FieldName +'-' + (pos-1)).style.display = 'none'; } function del(FieldName,pos,min) { switch(FieldName) { case 'author': if (pos > 1) { // special case: first author is not an input!! deleteErrorMessage(FieldName, pos); } break; default: break; } document.getElementById(FieldName + pos).style.display = 'none'; if (pos > min) { document.getElementById("button-del-" + FieldName +'-' + pos).style.display = 'none';} document.getElementById("button-add-" + FieldName +'-' + (pos-1)).style.display = 'block'; return; } function checkcontent(FieldName) { // alert(FieldName) var value = document.getElementById(FieldName).value ; // alert (FieldName +": " +value); } function showInputBibliografic() { document.getElementById('title').style.display = 'block'; hide("author",2,5); document.getElementById('authors').style.display = 'block'; } function hideInputBibliografic() { document.getElementById('title').style.display = 'none'; document.getElementById('authors').style.display = 'none'; } function oldcheckBoxType(checkedField) { document.getElementById("checkBoxType").style.display = 'none'; /* var fields = document.getElementById("checkBoxType").getElementsByTagName('label'); for(var i = 0; i < fields.length; i++) { alert (fields[i]); fields[i].disabled = true; } */ // activate part of the input reference in "checkedField" const typeFields = []; // typeFields.push("Monografie", "Sammelbandbeitrag", "Zeitschriftenartikel", "Qualifizierungsarbeit", "DiscussionPaper","Konferenzbeitrag"); typeFields.push("Monografie", "Sammelbandbeitrag", "Zeitschriftenartikel", "Qualifikationsarbeit"); for (let i = 0; i < typeFields.length; i++) { document.getElementById('div' + typeFields[i]).style.display = 'none'; const form = document.getElementById('div' + typeFields[i]); resetFormFields('div' + typeFields[i]); } document.getElementById('div' + checkedField).style.display = 'block'; } function resetFormFields(divToClear) { const div = document.getElementById(divToClear); const inputs = div.querySelectorAll('input, textarea, select'); inputs.forEach(field => { if (field.type === 'checkbox' || field.type === 'radio') { field.checked = false; } else if (field.tagName === 'SELECT') { field.selectedIndex = 0; } else { field.value = ''; } }); } function showErrors() { // Prüfen, ob Pflichtfelder gefüllt sind emptyFields = validateRequiredFields() ; let errorArray = []; let warningArray = []; let message = ''; let errorclass = ''; for (let i = 0; i < emptyFields.length; i++) { switch (emptyFields[i]) { case "titleinput1" : message = "Titelangabe fehlt."; errorclass = "error"; break; case "abstractinput1" : message = "Bitte mindestens ein Abstract eingeben."; errorclass = "error"; break; case "publicationyearinput1": message = "Bitte Erscheinungsjahr in den bibliografischen Grunddaten eingeben"; errorclass = "error"; break; case "publicatedDocument" : message = "Kein PDF-Dokument hochgeladen."; errorclass = "error"; break; case "publicatedDocumentType" : message = "Bitte prüfen Sie, ob mindestens ein Dokument mit der Eigenschaft 'Publikation' hochgeladen wurde."; errorclass = "error"; break; case "publishedInEditedVolumeinput1": message = "Bei Sammelbandbeitrag: bitte Titel des Sammelbands ergänzen."; errorclass= "warning"; break; case "publishedInJournalinput1": message = "Bei Zeitschriftenartikel: bitte Titel der Zeitschrift ergänzen, in der der Artikel erschienen ist."; errorclass= "warning"; break; case "qualificationType_select1" : message = "Bei Qualifikationsarbeit: bitte Art der Qualifikationsarbeit angeben"; errorclass= "warning"; break; case "qualifiedInstitutioninput1": message = "Bei Qualifikationsarbeit: bitte Name der titelverleihenden Institution angeben"; errorclass= "warning"; break; case "qualifiedYearinput1" : message = "Bei Qualifikationsarbeit: bitte Jahr angeben"; errorclass= "warning"; break; case "pageQualification1" : message = "Bei Qualifikationsarbeit: bitte Seitenanzahl angeben"; errorclass= "warning"; break; default: continue; } if (errorclass =="error") { errorArray.push({ message: message, errorclass: errorclass }); } else { warningArray.push({ message: message, errorclass: errorclass }); } } if (errorArray.length == 0) { showSummary() ; return; } console.log(errorArray); var modal = document.getElementById('arrayModal'); // Direkter CSS-Zugriff ohne !important if (modal) { modal.style.display = 'block'; modal.style.visibility = 'visible'; modal.style.position = 'fixed'; modal.style.zIndex = '99999'; modal.style.left = '0px'; modal.style.top = '0px'; modal.style.width = '100%'; modal.style.height = '100%'; modal.style.backgroundColor = 'rgba(0,0,0,0.5)'; } // FormData erstellen var formData = new FormData(); formData.append('errorArray', JSON.stringify(errorArray)); formData.append('warningArray', JSON.stringify(warningArray)); $('#arrayModal').modal('show'); $('#modalBody').html('Loading...'); // AJAX-Aufruf setTimeout(function() { $.ajax({ url: 'showSummaryErrors.php', method: 'POST', data: formData, processData: false, contentType: false, success: function(html) { $('#modalBody').html(html); // IN Modal laden! }, error: function(xhr, status, error) { $('#modalBody').html('Fehler: ' + error); $('#arrayModal').modal('show'); } }); }, 100); //100 ms Verzögerung return; // alert ("Nicht alle Pflichtfelder ausgefüllt. Bitte korrigieren."); } function showSummary() { var modal = document.getElementById('arrayModal'); // Direkter CSS-Zugriff ohne !important if (modal) { modal.style.display = 'block'; modal.style.visibility = 'visible'; modal.style.position = 'fixed'; modal.style.zIndex = '99999'; modal.style.left = '0px'; modal.style.top = '0px'; modal.style.width = '100%'; modal.style.height = '100%'; modal.style.backgroundColor = 'rgba(0,0,0,0.5)'; } const relevantDivs = [ "BibliographicData", "IdentificatorData", "TypeData", "SubjectData", "contractData", "uploadData" ]; // Globale Arrays für die Daten let bibliographicDataArray = []; let identificatorDataArray = []; let typeDataArray = []; let subjectDataArray = []; let contractDataArray = []; let uploadDataArray = []; // BibliographicData auslesen bibliographicDataArray = readDataFromDiv('BibliographicData'); // IdentificatorData auslesen identificatorDataArray = readDataFromDiv('IdentificatorData'); // TypeData auslesen typeDataArray = readDataFromDiv('TypeData'); //SubjectData auselesen subjectDataArray = readDataFromDiv('SubjectData'); //contractData auslesen contractDataArray = readDataFromDiv('contractData'); //uploadData auslesen uploadDataArray = readDataFromUploadDiv('fileList'); //Console ausgeben //console.log('BibliographicData Array:', bibliographicDataArray); //console.log('IdentificatorData Array:', identificatorDataArray); //console.log('TypeData Array:', typeDataArray); //console.log('SubjectData Array:', subjectDataArray); //console.log('ContractData Array:', contractDataArray); //console.log('UploadData Array:', uploadDataArray); // FormData erstellen var formData = new FormData(); formData.append('bibliographicArray', JSON.stringify(bibliographicDataArray)); formData.append('identificatorArray', JSON.stringify(identificatorDataArray)); formData.append('typeArray', JSON.stringify(typeDataArray)); formData.append('subjectArray', JSON.stringify(subjectDataArray)); formData.append('contractArray', JSON.stringify(contractDataArray)); formData.append('uploadArray', JSON.stringify(uploadDataArray)); $('#arrayModal').modal('show'); $('#modalBody').html('Loading...'); // AJAX-Aufruf setTimeout(function() { $.ajax({ url: 'checkModal.php', method: 'POST', data: formData, processData: false, contentType: false, success: function(html) { $('#modalBody').html(html); // IN Modal laden! }, error: function(xhr, status, error) { $('#modalBody').html('Fehler: ' + error); $('#arrayModal').modal('show'); } }); }, 100); //100 ms Verzögerung return; } function closeModal() { $('#arrayModal').hide(); // Backdrop explizit entfernen $('.modal-backdrop').remove(); $('body').removeClass('modal-open'); $('body').css('overflow', 'auto'); // Scroll wieder aktivieren } // ✅ correctData mit komplettem Reset function correctData() { closeModal(); // Optional: Button-Funktion nach Schließen testen setTimeout(() => { console.log('Modal geschlossen - Button sollte funktionieren'); }, 100); } function finishPublication() { closeModal(); } // Funktion: Daten aus einem spezifischen Div auslesen function readDataFromUploadDiv(divId) { let dataArray = []; const fieldArray = ["uploadItem", "uploadHiddenType", "uploadHiddenItem"]; // Div finden const div = document.getElementById(divId); if (!div) { console.warn('Div mit ID "' + divId + '" nicht gefunden!'); return dataArray; } var numberOfChildren = div.children.length // Spezielle Felder im Div durchlaufen for(let i = 0; i < numberOfChildren ; i++) { const uploadItem = document.getElementById("uploadItem" +i).textContent; // const uploadHiddenType = document.getElementById("uploadHiddenType" +i).textContent; const uploadHiddenItem = document.getElementById("uploadHiddenItem" +i).textContent; const uploadHiddenType = document.getElementById("uploadHiddenType" +i).textContent; // Nur Felder mit Werten berücksichtigen if (uploadItem && uploadItem.trim() !== '') { dataArray.push({ fieldId: "uploadItem" +i, fieldValue: uploadItem.trim() }); } if(uploadHiddenType && uploadHiddenType.trim() != '') { dataArray.push({ fieldId: "uploadType" +i , fieldValue: uploadHiddenType.trim() }); } if(uploadHiddenItem && uploadHiddenItem.trim() != '') { dataArray.push({ fieldId: "uploadHiddenItem" +i , fieldValue: uploadHiddenItem.trim() }); } } return dataArray; } // Funktion: Daten aus einem spezifischen Div auslesen function readDataFromDiv(divId) { let dataArray = []; // Div finden const $div = $('#' +divId); if ($div.length === 0) { console.warn('Div mit ID "' + divId + '" nicht gefunden!'); return dataArray; } // Alle Eingabefelder im Div durchlaufen $div.find('input, select, textarea').each(function() { const $field = $(this); const fieldId = $field.attr('id'); const fieldType = $field.prop('tagName').toLowerCase(); const inputType = $field.attr('type') || 'text'; let fieldValue = $field.val(); let isSelected = false; // Sicherstellen, dass fieldValue ein String ist if (fieldValue === null || fieldValue === undefined) { fieldValue = '' } else { fieldValue = String(fieldValue); } // Spezielle Behandlung für verschiedene Feldtypen if (inputType === 'checkbox') { // Checkbox: Nur hinzufügen wenn gechecked isSelected = $field.is(':checked'); fieldValue = isSelected ? ($field.val() || 'checked') : ''; } else if (inputType === 'radio') { // Radio: Nur hinzufügen wenn selected isSelected = $field.is(':checked'); fieldValue = isSelected ? $field.val() : ''; } else if (fieldType === 'select') { // Select: Prüfen ob etwas ausgewählt wurde (nicht der leere default-Wert) isSelected = (fieldValue !== '' && fieldValue !== null); } else { // Input/Textarea: Standard-Behandlung isSelected = (fieldValue.trim() !== ''); } // Nur Felder mit Namen und Werten berücksichtigen if (fieldId && isSelected && fieldValue && fieldValue.trim() !== '') { // Daten zum Array hinzufügen dataArray.push({ fieldId: fieldId, fieldValue: fieldValue.trim(), fieldType: $field.prop('tagName').toLowerCase(), fieldId: $field.prop('id').toLowerCase(), inputType: $field.attr('type') || 'text', isSelected: isSelected }); } }); return dataArray; } function oldcheckMultiPublish() { const publishTypeSelection = document.querySelector('input[name="publishType"]:checked'); const licenseTypeSelection = document.querySelector('input[name="licenseType"]:checked'); if (! publishTypeSelection || !licenseTypeSelection) { return } hideElement("divErstveroeffentlichungOpenAccess"); hideElement("divErstveroeffentlichungUrheberrecht"); hideElement("divZweitveroeffentlichungOpenAccess"); hideElement("Select4A4B"); hideElement("divZweitUrh4A"); hideElement("divErstUrh"); hideElement("divZweitUrh4B"); hideElement("divCommon"); hideElement("erstVeroeffentlichtSection"); hideElement("mitteilungSection"); if (publishTypeSelection.value == 'Erstveröffentlichung' && licenseTypeSelection.value == 'CC-Lizenz') { showElement("divErstveroeffentlichungOpenAccess"); showElement("divCommon"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Erstveröffentlichung' && licenseTypeSelection.value == 'Deutschem Urheberrecht') { showElement("divErstUrh"); showElement("divCommon"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Zweitveröffentlichung' && licenseTypeSelection.value == 'CC-Lizenz') { showElement("divZweitveroeffentlichungOpenAccess"); showElement("divCommon"); showElement("erstVeroeffentlichtSection"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Zweitveröffentlichung' && licenseTypeSelection.value == 'Deutschem Urheberrecht') { showElement("Select4A4B"); // showElement("divZweitveroeffentlichungUrheberrecht4B"); } } function showNextStep(Version) { hideElement("divZweitUrh4A"); hideElement("divZweitUrh4B"); showElement("erstVeroeffentlichtSection"); showElement("mitteilungSection"); if (Version == "Version4B") { showElement("divZweitUrh4B"); showElement("divCommon"); } else { showElement("divZweitUrh4A"); showElement("divCommon"); } } function checkLicense(checkedField) { // alert (checkedField) document.getElementById('divCreativeCommons1').style.display = 'block'; //document.getElementById('cc0share1').style.display = 'block'; //document.getElementById('cc0commercial1').style.display = 'block'; document.getElementById('licenseType').style.display = 'none'; } function clearTypeData() { document.getElementById("checkBoxType").style.display = 'block'; const typeFields = []; //typeFields.push("Monografie", "Sammelbandbeitrag", "Zeitschriftenartikel", "Qualifizierungsarbeit", "DiscussionPaper","Konferenzbeitrag"); typeFields.push("Monografie", "Sammelbandbeitrag", "Zeitschriftenartikel", "Qualifikationsarbeit", "Konferenzbeitrag"); for (let i = 0; i < typeFields.length; i++) { document.getElementById('div' + typeFields[i]).style.display = 'none'; // document.getElementById('div' + typeFields[i]).innerHTML = ""; } } function saveBibliographicData() { // TODO store bibliografic data on server /* titleinput1 authorinput1 - authorinput9 role_select1 - role_select9 publicationyearinput1 abstract_language_select1 - abstract_language_select3 abstractinput1 - abstractinput3 */ return; } function saveSubjectData() { return; } function saveIdentificators() { /* identificator_select1 - identificator_select5 identificator1 - identificator5 */ return } function saveTypeData() { /* Zeitschriftenartikel: publishedInJournal1, publishedInVolume1, pagefromArticle1, pagetoArticle1, reviewArticle1 Sammelbandbeitrag: publishedInEditedVolume1, publisherInEditedVolume1, pagefromEditedVolume1, pagetoEditedVolume1, review_editedvolume_select1 DiscussionPaper: pages1 Monografie: publisher1, pagesMonograph1 Konferenzbeitrag: publishedInEditedVolume1, conferenceName1, conferenceDetail1 Qualifizierungsarbeit: qualifiedInstitution1, qualifiedFachbereich1, qualifiedPerson1, qualifiedNote1, pagesQualification1 */ return } function saveMultiPublish() { return } function showHelp(field) { switch(field) { case 'helpFirstTitles': var r = '' alert (r); break; case 'helpFirstTitle': var r = "
Hinweis zur Erfassung von AutorInnen
Bitte AutorInnen in der Form 'Nachname, Vorname' eingeben"; break; default: } document.getElementById(field).innerHTML = r; document.getElementById(field).style.visibility = "block"; } function delHelp(field) { var hf= 'help' + field; var f = 'input' + field; document.getElementById(f).blur(); document.getElementById(hf).style.visibility = "hidden"; } // Javascripts für den Honeypot // // JavaScript für erweiterte Bot-Erkennung /*document.getElementById('js_enabled').value = '1'; let interactions = 0; let mouseMoved = false; // Zähle Formular-Interaktionen document.querySelectorAll('input, textarea').forEach(function(field) { field.addEventListener('focus', function() { interactions++; document.getElementById('form_interactions').value = interactions; }); }); // Maus-Bewegung tracken document.addEventListener('mousemove', function() { if (!mouseMoved) { mouseMoved = true; document.getElementById('mouse_moved').value = '1'; } }); */ // Formular-Validierung (findet in den einzelnen PHP-Dateien direkt statt) /* document.getElementById('contactForm').addEventListener('submit', function(e) { var name = document.getElementById('name').value.trim(); var email = document.getElementById('email').value.trim(); var message = document.getElementById('message').value.trim(); if (!name || !email || !message) { e.preventDefault(); alert('Bitte füllen Sie alle Felder aus.'); } }); */ // Bootstrap 5 Validierung /* (function() { 'use strict'; window.addEventListener('load', function() { var forms = document.getElementsByClassName('needs-validation'); var validation = Array.prototype.filter.call(forms, function(form) { form.addEventListener('onmouseout', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); }, false); })(); // Formular Submit Handler document.getElementById('validationForm').addEventListener('onmouseout', function(e) { e.preventDefault(); // Bootstrap Validierung hinzufügen this.classList.add('was-validated'); // Prüfen ob alle Felder gültig sind if (this.checkValidity()) { alert('Formular erfolgreich validiert!'); // Hier würden Sie normalerweise die Daten senden } }); */ // Manuelle Validierung für Custom Field function validateField(inputField, fieldNumber) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); if (value.length === 0) { // Leer - keine Anzeige field.classList.remove('is-valid', 'is-invalid'); error.style.display = 'none'; success.style.display = 'none'; } else if (value.length < 3) { // Ungültig field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } else { // Gültig field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } } function validateAlpha(inputField, fieldNumber) { const alphanumeric = /^[\p{sc=Latn}\p{Nd}0-9 .,-:\/]*$/u; var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); // Validate alphanumeric if (value.match(alphanumeric)) { // Valid field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } } function validateDigits(inputField, fieldNumber) { const digits = /^[\p{sc=Latn}\p{Nd}0-9]*$/u; var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); // Validate digits if (value.match(digits)) { // Valid field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } } function validatePages(inputField, fieldNumber) { const pages = /^(Seite|S\.)?[0-9\-\.\s]+$/ var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); // Validate digits if (value.match(pages)) { // Valid field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } } function validatePagesPageAtEnd(inputField, fieldNumber) { const pages = /^[0-9\-\.\s]+(S\.|Seiten)?$/ var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); // Validate digits if (value.match(pages)) { // Valid field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } } function validateAlphaExtended(inputField, fieldNumber) { const alphanumeric = /^[\p{sc=Latn}\p{Nd}0-9 .,-:\/]*$/u; var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); // Validate alphanumeric if (value.match(alphanumeric)) { // Valid field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } } function validateEmptyEntry(inputField, fieldNumber) { return(validateEmptyTitle(inputField, fieldNumber)); } function validateEmptyTitle(inputField, fieldNumber) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); if (value.length == 0) { // Ungültig field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; return false } else { // Gültig field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; return true } } function validateText(inputField, fieldNumber, minLength=4, maxLength=2000) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); if (event.type === 'blur') { if (value.length == 0) { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; setTimeout(() => { field.focus(); }, 10); return } } if (value.length <= minLength ) { // noch nicht genügend eingetippt - keine Anzeige field.classList.remove('is-valid', 'is-invalid'); error.style.display = 'none'; success.style.display = 'none'; } else { // Gültig field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } } function validateYear(inputField, fieldNumber) { var yearInput = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = yearInput.value.trim(); var result = true; // Leer - keine Anzeige yearInput.classList.remove('is-valid', 'is-invalid'); error.style.display = 'none'; success.style.display = 'none'; yearInput.addEventListener('input', function() { const value = this.value; // Erst Regex prüfen if (!/^\d{4}$/.test(value)) { this.value = value.replace(/\D/g, '').slice(0, 4); result = false ; } // Wenn 4 Stellen, Jahr validieren if (value.length === 4) { const year = parseInt(value, 10); const currentYear = new Date().getFullYear(); if (year > currentYear) { result = false; } else { result = true; } } if (result === false) { yearInput.classList.remove('is-valid'); yearInput.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; setTimeout(() => { yearInput.focus(); }, 10); return; } else { // Gültig yearInput.classList.remove('is-invalid'); yearInput.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } }); yearInput.addEventListener('focusout', function(event) { const value = this.value.trim(); // Validierung if (!isValidYear(value)) { event.preventDefault(); // Verhindert das Verlassen des Feldes this.focus(); // Focus zurück ins Feld yearInput.classList.remove('is-valid'); yearInput.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; setTimeout(() => { yearInput.focus(); }, 10); return; } }); } function isValidYear(input) { if (!/^\d{4}$/.test(input)) { return false; } const year = parseInt(input, 10); const currentYear = new Date().getFullYear(); return year <= currentYear && year >= 1900; // mit sinnvollem Mindestjahr } function validateAbstract(inputField, fieldNumber) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); if (value.length === 0) { // Leer - keine Anzeige field.classList.remove('is-valid', 'is-invalid'); error.style.display = 'none'; success.style.display = 'none'; } else if (value.length >= 2800) { // Ungültig field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } else { // Gültig field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } } function validatePID(inputField, fieldNumber) { var selected = document.getElementById(inputField +"_select" +fieldNumber).value; var field = document.getElementById(inputField +"Input"+ fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); const pid = document.getElementById(inputField +"Input"+ fieldNumber).value; console.log("Selected: " +selected); console.log("Value: " +pid); result = validateIdentifier(pid, selected); if (result.valid === true) { field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; error.innerHTML = ''; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; error.innerHTML = result.error; success.style.display = 'none'; setTimeout(() => { field.focus(); }, 10); return } } function deleteErrorMessage(inputField, fieldNumber) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); if (error) { if(field) { field.classList.remove('is-invalid'); field.classList.add('is-valid'); field.innerHTML = ''; } error.style.display = 'none'; error.innerHTML = ''; } } function validateNameFormat(inputField, fieldNumber) { var field = document.getElementById(inputField + 'input' + fieldNumber); var error = document.getElementById(inputField + fieldNumber + 'Error'); var success = document.getElementById(inputField + fieldNumber + 'Success'); var value = field.value.trim(); var ret = true // check if input is null or undefined if (!value || typeof value !== 'string') { ret = false } // Regex to check "name, forename" format. Erlaubt alle UTF-8 Zeichen plus Apostroph und Punkt für Abkürzungen const namePattern = /^[\p{L}\s'.-]+,\s*[\p{L}\s'.-]+$/u; if (!namePattern.test(value)) { ret = false } if (ret === true) { field.classList.remove('is-invalid'); field.classList.add('is-valid'); error.style.display = 'none'; success.style.display = 'block'; } else { field.classList.remove('is-valid'); field.classList.add('is-invalid'); error.style.display = 'block'; success.style.display = 'none'; } return ret } // Formular zurücksetzen function clearForm() { const form = document.getElementById('validationForm'); form.reset(); form.classList.remove('was-validated'); // Custom Field auch zurücksetzen const customField = document.getElementById('customField'); customField.classList.remove('is-valid', 'is-invalid'); document.getElementById('customError').style.display = 'none'; document.getElementById('customSuccess').style.display = 'none'; } function sendFinalMails(bibliographicArray, identificatorArray, typeArray, subjectArray, contractArray) { const relevantDivs = ["BibliographicData", "IdentificatorData", "TypeData", "SubjectData", "contractData", "uploadData"]; // Globale Arrays für die Daten let bibliographicDataArray = []; let identificatorDataArray = []; let typeDataArray = []; let subjectDataArray = []; let contractDataArray = []; let uploadDataArray = []; bibliographicDataArray = readDataFromDiv('BibliographicData'); identificatorDataArray = readDataFromDiv('IdentificatorData'); typeDataArray = readDataFromDiv('TypeData'); subjectDataArray = readDataFromDiv('SubjectData'); contractDataArray = readDataFromDiv('contractData'); uploadDataArray = readDataFromUploadDiv('fileList'); // Console ausgeben console.log('BibliographicData Array:', bibliographicDataArray); console.log('IdentificatorData Array:', identificatorDataArray); console.log('TypeData Array:', typeDataArray); console.log('SubjectData Array:', subjectDataArray); console.log('ContractData Array:', contractDataArray); console.log('UploadData Array:', uploadDataArray); // Einfaches JavaScript-Objekt für jQuery $.post() var postData = { bibliographicArray: JSON.stringify(bibliographicDataArray), identificatorArray: JSON.stringify(identificatorDataArray), typeArray: JSON.stringify(typeDataArray), subjectArray: JSON.stringify(subjectDataArray), contractArray: JSON.stringify(contractDataArray), uploadArray: JSON.stringify(uploadDataArray) }; // AJAX-Aufruf $.post('sendFinalMails.php', postData, function(data, status) { if (status == "success") { hideElement("BibliographicData"); hideElement("IdentificatorData"); hideElement("TypeData"); hideElement("SubjectData"); hideElement("contractData"); hideElement("uploadData"); hideElement("divSummaryButton"); hideElement("summaryButton"); const VERODataDiv = document.getElementById("VEROData"); //if (VERODataDiv && VERODataDiv.style.display !== 'none') { // VERODataDiv.style.display = 'none'; //} //alert(data); const MailDataDiv = document.getElementById("finalMailContent"); MailDataDiv.innerHTML = data; const MailDiv = document.getElementById("MAILData"); if (MailDiv && MailDiv.style.display !== 'block') { // alert("MAILdata auf block gestellt"); MailDiv.style.display = 'block'; } console.log(MailDiv); } else { alert("Mail konnte nicht verschickt werden: " + data); } }).fail(function(xhr, status, error) { alert("AJAX-Fehler: " + error); }); } // Accordion Validierung - verhindert das Schließen bei fehlenden required Feldern document.addEventListener('DOMContentLoaded', function() { // Event Listener für alle Accordion Buttons const accordionButtons = document.querySelectorAll('[data-bs-toggle="collapse"]'); accordionButtons.forEach(button => { button.addEventListener('click', function(e) { const targetId = this.getAttribute('data-bs-target'); const targetAccordion = document.querySelector(targetId); // Prüfen ob das Accordion aktuell geöffnet ist und geschlossen werden soll if (targetAccordion && targetAccordion.classList.contains('show')) { // Validierung durchführen if (!validateAccordionContent(targetAccordion)) { e.preventDefault(); e.stopPropagation(); return false; } } }); }); // Bootstrap Accordion Event abfangen (zusätzliche Sicherheit) const accordionElement = document.getElementById('TypeData'); if (accordionElement) { accordionElement.addEventListener('hide.bs.collapse', function(e) { if (!validateAccordionContent(e.target)) { e.preventDefault(); return false; } }); } }); function validateAccordionContent(accordionContent) { // Prüfen ob wir im Dokumenttyp-Auswahl-Modus sind const checkBoxTypeDiv = document.getElementById("checkBoxType"); if (checkBoxTypeDiv && checkBoxTypeDiv.style.display !== 'none') { // Im Auswahl-Modus - nur prüfen ob ein Dokumenttyp gewählt wurde const selectedType = document.querySelector('input[name="checkType"]:checked'); if (!selectedType) { showValidationError('Bitte wählen Sie einen Dokumenttyp aus.'); return false; } // Dokumenttyp gewählt - Validierung bestanden return true; } // Im Detail-Modus - normale Feldvalidierung const selectedType = document.querySelector('input[name="checkType"]:checked'); if (!selectedType) { // Das sollte nicht passieren, aber sicherheitshalber backToDocumentTypeSelection(); return false; } // Nur die Felder des gewählten Dokumenttyps validieren const activeDiv = getActiveDivForDocumentType(selectedType.value); if (!activeDiv) { return true; // Kein spezifischer Div gefunden, Validierung übersprungen } // Required Felder nur im aktiven Div suchen const requiredFields = activeDiv.querySelectorAll('input[required], textarea[required], select[required]'); let allValid = true; let firstInvalidField = null; requiredFields.forEach(field => { // Zusätzliche Sichtbarkeits-Prüfung für nested Elemente if (isFieldInActiveArea(field, activeDiv)) { if (!field.value.trim()) { allValid = false; if (!firstInvalidField) { firstInvalidField = field; } // Feld als ungültig markieren markFieldAsInvalid(field); } } }); if (!allValid) { // Fehlermeldung anzeigen showValidationError('Bitte füllen Sie alle Pflichtfelder für den gewählten Dokumenttyp aus.'); // Zum ersten ungültigen Feld scrollen if (firstInvalidField) { firstInvalidField.focus(); firstInvalidField.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } return allValid; } // Hilfsfunktion: Aktiven Div für gewählten Dokumenttyp ermitteln function getActiveDivForDocumentType(documentType) { switch(documentType) { case 'Zeitschriftenartikel': return document.getElementById('divZeitschriftenartikel'); case 'Sammelbandbeitrag': return document.getElementById('divSammelbandbeitrag'); case 'Monografie': return document.getElementById('divMonografie'); case 'Qualifikationsarbeit': return document.getElementById('divQualifikationsarbeit'); case 'Konferenzbeitrag': // Falls Sie diesen auch haben return document.getElementById('divKonferenzbeitrag'); default: return null; } } // Hilfsfunktion: Prüfen ob Feld im aktiven Bereich ist function isFieldInActiveArea(field, activeDiv) { // Prüfen ob das Feld ein Nachfahre des aktiven Divs ist return activeDiv.contains(field) && isFieldActuallyVisible(field); } function isFieldActuallyVisible(field) { // Prüfen ob das Feld und seine direkten Container sichtbar sind let element = field; while (element && element !== document.body) { const style = window.getComputedStyle(element); if (style.display === 'none' || style.visibility === 'hidden') { return false; } element = element.parentElement; } return true; } function markFieldAsInvalid(field) { // Bootstrap Validation Klassen hinzufügen field.classList.add('is-invalid'); // Bestehende Error-Divs anzeigen (falls vorhanden) const fieldId = field.id; if (fieldId) { const errorDiv = document.getElementById(fieldId.replace('input', '') + 'Error'); if (errorDiv) { errorDiv.style.display = 'block'; } } // Event Listener für Änderungen am Feld field.addEventListener('input', function() { if (this.value.trim()) { this.classList.remove('is-invalid'); this.classList.add('is-valid'); // Error div ausblenden const fieldId = this.id; if (fieldId) { const errorDiv = document.getElementById(fieldId.replace('input', '') + 'Error'); if (errorDiv) { errorDiv.style.display = 'none'; } } } }, { once: true }); } function showValidationError(message = 'Bitte füllen Sie alle Pflichtfelder aus, bevor Sie fortfahren.') { // Toast oder Alert für Fehlermeldung if (typeof bootstrap !== 'undefined' && bootstrap.Toast) { // Bootstrap Toast verwenden const toastHtml = ` `; // Toast Container erstellen falls nicht vorhanden let toastContainer = document.getElementById('toast-container'); if (!toastContainer) { toastContainer = document.createElement('div'); toastContainer.id = 'toast-container'; toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3'; toastContainer.style.zIndex = '1055'; document.body.appendChild(toastContainer); } // Toast hinzufügen und anzeigen toastContainer.innerHTML = toastHtml; const toastElement = toastContainer.querySelector('.toast'); const toast = new bootstrap.Toast(toastElement); toast.show(); } else { // Fallback: einfaches Alert alert(message); } } // Hilfsfunktion: Alle Felder in einem Accordion validieren function validateAllFieldsInAccordion(accordionId) { const accordion = document.getElementById(accordionId); if (accordion) { const collapseElement = accordion.querySelector('.accordion-collapse'); return validateAccordionContent(collapseElement); } return true; } // Hilfsfunktion: Validierung für spezifische Dokumenttypen function validateDocumentTypeFields() { const selectedType = document.querySelector('input[name="checkType"]:checked'); if (!selectedType) { return false; } const typeValue = selectedType.value; let targetDiv = null; switch(typeValue) { case 'Zeitschriftenartikel': targetDiv = document.getElementById('divZeitschriftenartikel'); break; case 'Sammelbandbeitrag': targetDiv = document.getElementById('divSammelbandbeitrag'); break; case 'Monografie': targetDiv = document.getElementById('divMonografie'); break; case 'Qualifikationsarbeit': targetDiv = document.getElementById('divQualifikationsarbeit'); break; } if (targetDiv) { return validateAccordionContent(targetDiv); } return true; } // Angepasste checkBoxType Funktion function checkBoxType(selectedType) { // Alle Dokumenttyp-Divs ausblenden const allTypeDivs = [ 'divMonografie', 'divSammelbandbeitrag', 'divZeitschriftenartikel', 'divKonferenzbeitrag', 'divQualifikationsarbeit' ]; allTypeDivs.forEach(divId => { const div = document.getElementById(divId); if (div) { div.style.display = 'none'; } }); // Validierungsklassen von allen Feldern entfernen allTypeDivs.forEach(divId => { const div = document.getElementById(divId); if (div) { const fields = div.querySelectorAll('.is-invalid, .is-valid'); fields.forEach(field => { field.classList.remove('is-invalid', 'is-valid'); }); // Error Divs ausblenden const errorDivs = div.querySelectorAll('[id$="Error"]'); errorDivs.forEach(errorDiv => { errorDiv.style.display = 'none'; }); } }); // Entsprechenden Div für gewählten Typ einblenden let targetDivId = null; switch(selectedType) { case 'Zeitschriftenartikel': targetDivId = 'divZeitschriftenartikel'; break; case 'Sammelbandbeitrag': targetDivId = 'divSammelbandbeitrag'; break; case 'Monografie': targetDivId = 'divMonografie'; break; case 'Qualifikationsarbeit': targetDivId = 'divQualifikationsarbeit'; break; case 'Konferenzbeitrag': targetDivId = 'divKonferenzbeitrag'; break; } if (targetDivId) { const targetDiv = document.getElementById(targetDivId); if (targetDiv) { targetDiv.style.display = 'block'; } } // Dokumenttyp-Auswahl ausblenden const checkBoxTypeDiv = document.getElementById("checkBoxType"); if (checkBoxTypeDiv) { checkBoxTypeDiv.style.display = 'none'; } // Zurück-Button hinzufügen/anzeigen showBackToSelectionButton(); } // Funktion für Zurück-Button function showBackToSelectionButton() { // Prüfen ob Button bereits existiert let backButton = document.getElementById('backToDocumentTypeSelection'); if (!backButton) { // Button erstellen backButton = document.createElement('div'); backButton.id = 'backToDocumentTypeSelection'; backButton.className = 'mb-3'; backButton.innerHTML = ` `; // Button nach dem typeBox einfügen const typeBox = document.getElementById('typeBox'); if (typeBox && typeBox.parentNode) { typeBox.parentNode.insertBefore(backButton, typeBox.nextSibling); } } // Button anzeigen backButton.style.display = 'block'; } // Zurück zur Dokumenttyp-Auswahl function backToDocumentTypeSelection() { // Alle Dokumenttyp-Divs ausblenden const allTypeDivs = [ 'divMonografie', 'divSammelbandbeitrag', 'divZeitschriftenartikel', 'divKonferenzbeitrag', 'divQualifikationsarbeit' ]; allTypeDivs.forEach(divId => { const div = document.getElementById(divId); if (div) { div.style.display = 'none'; } }); // Dokumenttyp-Auswahl wieder einblenden const checkBoxTypeDiv = document.getElementById("checkBoxType"); if (checkBoxTypeDiv) { checkBoxTypeDiv.style.display = 'block'; } // Zurück-Button ausblenden const backButton = document.getElementById('backToDocumentTypeSelection'); if (backButton) { backButton.style.display = 'none'; } // Radio-Button Auswahl zurücksetzen (optional) const radioButtons = document.querySelectorAll('input[name="checkType"]'); radioButtons.forEach(radio => { radio.checked = false; }); // Alle Validierungsklassen entfernen allTypeDivs.forEach(divId => { const div = document.getElementById(divId); if (div) { const fields = div.querySelectorAll('.is-invalid, .is-valid'); fields.forEach(field => { field.classList.remove('is-invalid', 'is-valid'); field.value = ''; // Felder leeren (optional) }); // Error Divs ausblenden const errorDivs = div.querySelectorAll('[id$="Error"]'); errorDivs.forEach(errorDiv => { errorDiv.style.display = 'none'; }); } }); } // Initialisierung beim Laden der Seite function initializeDocumentTypeSelection() { // Sicherstellen, dass alle Detail-Divs ausgeblendet sind const allTypeDivs = [ 'divMonografie', 'divSammelbandbeitrag', 'divZeitschriftenartikel', 'divKonferenzbeitrag', 'divQualifikationsarbeit' ]; allTypeDivs.forEach(divId => { const div = document.getElementById(divId); if (div) { div.style.display = 'none'; } }); // Sicherstellen, dass checkBoxType sichtbar ist const checkBoxTypeDiv = document.getElementById("checkBoxType"); if (checkBoxTypeDiv) { checkBoxTypeDiv.style.display = 'block'; } // Zurück-Button ausblenden const backButton = document.getElementById('backToDocumentTypeSelection'); if (backButton) { backButton.style.display = 'none'; } } // Beim Laden der Seite initialisieren document.addEventListener('DOMContentLoaded', function() { initializeDocumentTypeSelection(); }); // Sanitize Funktionen /** * JavaScript Input Sanitization Functions (Prozedural) * Verschiedene Funktionen zum Bereinigen von User-Inputs */ /** * HTML-Tags und gefährliche Zeichen entfernen/escapen * @param {string} input * @returns {string} */ function sanitizeHTML(input) { if (typeof input !== 'string') return ''; return input .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') .replace(/\//g, '/'); } /** * SQL Injection Zeichen escapen (für dynamische Queries) * @param {string} input * @returns {string} */ function sanitizeSQL(input) { if (typeof input !== 'string') return ''; return input .replace(/'/g, "''") // Single quotes escapen .replace(/"/g, '""') // Double quotes escapen .replace(/\\/g, '\\\\') // Backslashes escapen .replace(/\0/g, '\\0') // Null bytes .replace(/\n/g, '\\n') // Newlines .replace(/\r/g, '\\r') // Carriage returns .replace(/\x1a/g, '\\Z'); // Ctrl+Z } /** * Email-Adresse validieren und bereinigen * @param {string} email * @returns {string|null} */ function sanitizeEmail(email) { if (typeof email !== 'string') return null; // Whitespace entfernen und lowercase email = email.trim().toLowerCase(); // Basis Email Regex const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/; return emailRegex.test(email) ? email : null; } /** * Telefonnummer bereinigen (nur Zahlen, +, -, (, ), Leerzeichen) * @param {string} phone * @returns {string} */ function sanitizePhone(phone) { if (typeof phone !== 'string') return ''; // Nur erlaubte Zeichen behalten return phone.replace(/[^0-9+\-\(\)\s]/g, '').trim(); } /** * URL validieren und bereinigen * @param {string} url * @returns {string|null} */ function sanitizeURL(url) { if (typeof url !== 'string') return null; url = url.trim(); try { const urlObj = new URL(url); // Nur HTTP/HTTPS erlauben if (urlObj.protocol === 'http:' || urlObj.protocol === 'https:') { return urlObj.href; } } catch (e) { // Falls URL ungültig ist return null; } return null; } /** * Numerische Inputs bereinigen * @param {string|number} input * @param {number|null} min - Minimum Wert * @param {number|null} max - Maximum Wert * @param {number|null} decimals - Anzahl Dezimalstellen * @returns {number|null} */ function sanitizeNumber(input, min = null, max = null, decimals = null) { // Zu Number konvertieren let num = parseFloat(input); if (isNaN(num)) return null; // Dezimalstellen begrenzen if (decimals !== null) { num = parseFloat(num.toFixed(decimals)); } // Min/Max Grenzen prüfen if (min !== null && num < min) return null; if (max !== null && num > max) return null; return num; } /** * Integer bereinigen * @param {string|number} input * @param {number|null} min * @param {number|null} max * @returns {number|null} */ function sanitizeInteger(input, min = null, max = null) { const num = parseInt(input); if (isNaN(num)) return null; if (min !== null && num < min) return null; if (max !== null && num > max) return null; return num; } /** * Allgemeine Textbereinigung * @param {string} input * @param {number|null} maxLength * @param {string|null} allowedCharsRegex - Regex Pattern für erlaubte Zeichen * @param {boolean} trim * @param {boolean} removeMultipleSpaces * @returns {string} */ function sanitizeText(input, maxLength = null, allowedCharsRegex = null, trim = true, removeMultipleSpaces = true) { if (typeof input !== 'string') return ''; let sanitized = input; // Trimmen if (trim) { sanitized = sanitized.trim(); } // Mehrfache Leerzeichen entfernen if (removeMultipleSpaces) { sanitized = sanitized.replace(/\s+/g, ' '); } // Nur erlaubte Zeichen behalten if (allowedCharsRegex) { const regex = new RegExp(allowedCharsRegex, 'g'); const matches = sanitized.match(regex); sanitized = matches ? matches.join('') : ''; } // Länge begrenzen if (maxLength && sanitized.length > maxLength) { sanitized = sanitized.substring(0, maxLength); } return sanitized; } /** * Username bereinigen (nur Buchstaben, Zahlen, Underscore) * @param {string} username * @param {number} minLength * @param {number} maxLength * @returns {string|null} */ function sanitizeUsername(username, minLength = 3, maxLength = 20) { if (typeof username !== 'string') return null; // Nur erlaubte Zeichen, trim, lowercase const sanitized = username .trim() .toLowerCase() .replace(/[^a-z0-9_]/g, ''); // Länge prüfen if (sanitized.length < minLength || sanitized.length > maxLength) { return null; } // Nicht mit Zahl oder Underscore beginnen if (/^[0-9_]/.test(sanitized)) { return null; } return sanitized; } /** * Dateinamen bereinigen * @param {string} filename * @returns {string} */ function sanitizeFilename(filename) { if (typeof filename !== 'string') return ''; return filename .replace(/[<>:"/\\|?*\x00-\x1f]/g, '') // Ungültige Zeichen entfernen .replace(/^\.+/, '') // Führende Punkte entfernen .replace(/\.+$/, '') // Trailing Punkte entfernen .replace(/\s+/g, '_') // Leerzeichen durch Unterstriche .substring(0, 255); // Max Länge } /** * XSS-sichere Ausgabe für HTML-Attribute * @param {string} input * @returns {string} */ function sanitizeAttribute(input) { if (typeof input !== 'string') return ''; return input .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } /** * Boolean Wert aus String extrahieren * @param {string|boolean} input * @returns {boolean|null} */ function sanitizeBoolean(input) { if (typeof input === 'boolean') return input; if (typeof input !== 'string') return null; const lower = input.toLowerCase().trim(); if (['true', '1', 'yes', 'on', 'enabled'].includes(lower)) { return true; } if (['false', '0', 'no', 'off', 'disabled'].includes(lower)) { return false; } return null; } /** * Passwort validieren (keine Bereinigung, nur Validation) * @param {string} password * @returns {object} */ function validatePassword(password) { if (typeof password !== 'string') { return { valid: false, errors: ['Password must be a string'], strength: 'invalid' }; } const errors = []; if (password.length < 8) errors.push('Minimum 8 characters required'); if (!/[a-z]/.test(password)) errors.push('Lowercase letter required'); if (!/[A-Z]/.test(password)) errors.push('Uppercase letter required'); if (!/[0-9]/.test(password)) errors.push('Number required'); if (!/[^a-zA-Z0-9]/.test(password)) errors.push('Special character required'); return { valid: errors.length === 0, errors: errors, strength: getPasswordStrength(password) }; } /** * Passwort Stärke berechnen * @param {string} password * @returns {string} */ function getPasswordStrength(password) { if (typeof password !== 'string') return 'invalid'; let score = 0; if (password.length >= 8) score++; if (password.length >= 12) score++; if (/[a-z]/.test(password)) score++; if (/[A-Z]/.test(password)) score++; if (/[0-9]/.test(password)) score++; if (/[^a-zA-Z0-9]/.test(password)) score++; if (password.length >= 16) score++; if (score <= 2) return 'weak'; if (score <= 4) return 'medium'; if (score <= 6) return 'strong'; return 'very-strong'; } /** * Hex Color Code validieren * @param {string} color * @returns {string|null} */ function sanitizeHexColor(color) { if (typeof color !== 'string') return null; // # entfernen falls vorhanden color = color.replace('#', ''); // Nur 3 oder 6 Zeichen erlaubt if (!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(color)) { return null; } return '#' + color.toLowerCase(); } /** * Array von Strings bereinigen * @param {Array} arr * @param {Function} sanitizeFunc - Sanitization Funktion für jeden String * @returns {Array} */ function sanitizeStringArray(arr, sanitizeFunc = sanitizeText) { if (!Array.isArray(arr)) return []; return arr .filter(item => typeof item === 'string') .map(item => sanitizeFunc(item)) .filter(item => item !== null && item !== ''); } // Funktion zum Zurücksetzen aller Radio-Buttons function resetAllRadios() { // Alle Radio-Buttons in den relevanten Formularen finden und zurücksetzen const radioGroups = [ 'publishType', 'licenseType', 'zweitveroeffentlichungSelect', 'OAlicenseType' ]; radioGroups.forEach(groupName => { const radios = document.querySelectorAll(`input[name="${groupName}"]`); radios.forEach(radio => { radio.checked = false; }); }); // Alle Checkboxen zurücksetzen const checkboxes = document.querySelectorAll('.validation-checkbox'); checkboxes.forEach(checkbox => { checkbox.checked = false; }); // Verstecke alle spezifischen Sektionen hideAllSections(); // Validierungsstatus zurücksetzen updateValidationStatus(); } // Funktion zum Verstecken aller Sektionen function hideAllSections() { const sectionsToHide = [ 'divErstveroeffentlichungOpenAccess', 'divErstUrh', 'divZweitveroeffentlichungOpenAccess', 'divZweitUrh4A', 'divZweitUrh4B', 'divCommon', 'Select4A4B', 'erstVeroeffentlichtSection', 'mitteilungSection' ]; sectionsToHide.forEach(sectionId => { const section = document.getElementById(sectionId); if (section) { section.style.display = 'none'; } }); } // Event Listener für publishType Radio-Buttons document.addEventListener('DOMContentLoaded', function() { // Warte einen Moment, um sicherzustellen, dass alle Elemente geladen sind setTimeout(() => { console.log('DOM Content Loaded - Initialisiere Event Listener'); // Debug: Prüfe verfügbare Elemente debugElements(); const publishTypeRadios = document.querySelectorAll('input[name="publishType"]'); const licenseTypeRadios = document.querySelectorAll('input[name="licenseType"]'); console.log('publishType Radios gefunden:', publishTypeRadios.length); console.log('licenseType Radios gefunden:', licenseTypeRadios.length); // Event Listener für publishType publishTypeRadios.forEach(radio => { radio.addEventListener('change', function() { console.log('publishType geändert zu:', this.value); // Nur andere Radio-Gruppen zurücksetzen, nicht die eigene resetSpecificRadioGroups(['licenseType', 'zweitveroeffentlichungSelect', 'OAlicenseType']); resetAllCheckboxes(); hideAllSections(); // Nach dem Zurücksetzen prüfen ob eine neue Auswahl getroffen werden kann setTimeout(() => { checkMultiPublish(); }, 10); }); }); // Event Listener für licenseType licenseTypeRadios.forEach(radio => { radio.addEventListener('change', function() { console.log('licenseType geändert zu:', this.value); // Nur abhängige Radio-Gruppen zurücksetzen resetSpecificRadioGroups(['zweitveroeffentlichungSelect', 'OAlicenseType']); resetAllCheckboxes(); // Nicht alle Sektionen verstecken, sondern direkt checkMultiPublish aufrufen checkMultiPublish(); }); }); // Event Listener für zweitveroeffentlichungSelect /* const zweitveroeffentlichungRadios = document.querySelectorAll('input[name="zweitveroeffentlichungSelect"]'); zweitveroeffentlichungRadios.forEach(radio => { radio.addEventListener('change', function() { console.log('zweitveroeffentlichungSelect geändert zu:', this.value); showNextStep(this.value); }); }); */ // Event Listener für OAlicenseType const oaLicenseRadios = document.querySelectorAll('input[name="OAlicenseType"]'); oaLicenseRadios.forEach(radio => { radio.addEventListener('change', function() { console.log('OAlicenseType geändert zu:', this.value); updateValidationStatus(); }); }); // Event Listener für Checkboxen, um Status zu aktualisieren const checkboxes = document.querySelectorAll('.validation-checkbox'); checkboxes.forEach(checkbox => { checkbox.addEventListener('change', function() { console.log('Checkbox geändert:', this.id, this.checked); updateValidationStatus(); }); }); // Initial status update updateValidationStatus(); }, 100); }); // Hilfsfunktion zum Zurücksetzen spezifischer Radio-Gruppen function resetSpecificRadioGroups(groupNames) { groupNames.forEach(groupName => { const radios = document.querySelectorAll(`input[name="${groupName}"]`); radios.forEach(radio => { radio.checked = false; }); }); } // Hilfsfunktion zum Zurücksetzen aller Checkboxen function resetAllCheckboxes() { const checkboxes = document.querySelectorAll('.validation-checkbox'); checkboxes.forEach(checkbox => { checkbox.checked = false; }); } // Erweiterte checkMultiPublish Funktion function checkMultiPublish() { const publishType = document.querySelector('input[name="publishType"]:checked'); const licenseType = document.querySelector('input[name="licenseType"]:checked'); console.log('checkMultiPublish aufgerufen:', { publishType: publishType ? publishType.value : 'none', licenseType: licenseType ? licenseType.value : 'none' }); // Alle Sektionen zunächst verstecken hideAllSections(); if (publishType && licenseType) { const publishTypeSelection = publishType; const licenseTypeSelection = licenseType; console.log('Zeige Sektionen für:', publishTypeSelection.value, '+', licenseTypeSelection.value); // Logik für die Anzeige der entsprechenden Sektionen if (publishTypeSelection.value == 'Erstveröffentlichung' && licenseTypeSelection.value == 'CC-Lizenz') { showElement("divErstveroeffentlichungOpenAccess"); showElement("divCommon"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Erstveröffentlichung' && licenseTypeSelection.value == 'Deutschem Urheberrecht') { showElement("divErstUrh"); showElement("divCommon"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Zweitveröffentlichung' && licenseTypeSelection.value == 'CC-Lizenz') { showElement("divZweitveroeffentlichungOpenAccess"); showElement("divCommon"); showElement("erstVeroeffentlichtSection"); showElement("mitteilungSection"); } if (publishTypeSelection.value == 'Zweitveröffentlichung' && licenseTypeSelection.value == 'Deutschem Urheberrecht') { showElement("Select4A4B"); } } updateValidationStatus(); } // Hilfsfunktion zum Anzeigen einer Sektion function showSection(sectionId) { const section = document.getElementById(sectionId); if (section) { section.style.display = 'block'; console.log('Sektion angezeigt:', sectionId); } else { console.warn('Sektion nicht gefunden:', sectionId); } } // Funktion zum Verstecken aller Sektionen function hideAllSections() { const sectionsToHide = [ 'divErstveroeffentlichungOpenAccess', 'divErstUrh', 'divZweitveroeffentlichungOpenAccess', 'divZweitUrh4A', 'divZweitUrh4B', 'divCommon', 'Select4A4B', 'erstVeroeffentlichtSection', 'mitteilungSection' ]; sectionsToHide.forEach(sectionId => { const section = document.getElementById(sectionId); if (section) { section.style.display = 'none'; } }); // Upload-Akkordeon deaktivieren deactivateUploadAccordion(); } // Funktion für die nächsten Schritte (4A/4B) function showNextStep(version) { // Verstecke beide 4A/4B Sektionen document.getElementById('divZweitUrh4A').style.display = 'none'; document.getElementById('divZweitUrh4B').style.display = 'none'; // Zeige die entsprechende Sektion if (version === 'Version4A') { document.getElementById('divZweitUrh4A').style.display = 'block'; } else if (version === 'Version4B') { document.getElementById('divZweitUrh4B').style.display = 'block'; } showElement("divCommon"); showElement("erstVeroeffentlichtSection"); showElement("mitteilungSection"); updateValidationStatus(); } // Validierungsstatus aktualisieren function updateValidationStatus() { // Nur sichtbare Checkboxen berücksichtigen const allVisibleCheckboxes = getVisibleCheckboxes(); const checkedVisibleCheckboxes = allVisibleCheckboxes.filter(checkbox => checkbox.checked); // Status aktualisieren - nur wenn sichtbare Checkboxen vorhanden sind if (allVisibleCheckboxes.length === 0) { // Keine sichtbaren Checkboxes - zeige neutralen Status } else if (checkedVisibleCheckboxes.length === allVisibleCheckboxes.length) { // Alle sichtbaren Checkboxes sind aktiviert let i = checkCCLicenseSelection(); if (checkCCLicenseSelection() === true) { //document.getElementById('finishContractSectionButton').disabled = false; document.getElementById('statusTextContract').style.display = 'none'; activateUploadAccordion(); } } else { // Nicht alle sichtbaren Checkboxes sind aktiviert document.getElementById('statusTextContract').style.display = 'block'; deactivateUploadAccordion(); } } // Funktion zum Finden aller sichtbaren Checkboxen function getVisibleCheckboxes() { const allCheckboxes = document.querySelectorAll('.validation-checkbox'); const visibleCheckboxes = []; allCheckboxes.forEach(checkbox => { // Prüfe ob das Checkbox-Element und seine Eltern sichtbar sind if (isElementVisible(checkbox)) { visibleCheckboxes.push(checkbox); } }); console.log('Sichtbare Checkboxes:', visibleCheckboxes.map(cb => cb.id || cb.name)); return visibleCheckboxes; } // Hilfsfunktion zur Überprüfung der Sichtbarkeit eines Elements function isElementVisible(element) { // Prüfe das Element selbst und alle Eltern-Container let currentElement = element; while (currentElement && currentElement !== document.body) { const style = window.getComputedStyle(currentElement); // Prüfe verschiedene CSS-Eigenschaften die Sichtbarkeit beeinflussen if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0' || currentElement.hidden) { return false; } currentElement = currentElement.parentElement; } return true; } // Debug-Funktion zum Testen der Element-Verfügbarkeit function debugElements() { return; console.log('=== DEBUG ELEMENTS ==='); console.log('validation-info:', document.querySelector('.validation-info')); console.log('validation-checkboxes:', document.querySelectorAll('.validation-checkbox')); console.log('====================='); } // Prüfung, ob bei Zweitveröffentlichung unter CC-Lizenz genau eine Lizenz ausgewählt wurde, unter der die Publikation zuerst veröffentlicht wurde function addCCLicenseValidation() { const radioButtons = document.querySelectorAll('#checkCCLicense input[type="radio"][name="OAlicenseType"]'); radioButtons.forEach(radio => { radio.addEventListener('change', function() { const result = checkCCLicenseSelection(); console.log("Ergebnis checkCCLicenseSelection: " +result.message); return result; // Ggf. weitere Aktionen basierend auf der Validierung durchführen // z.B. Fehlermeldungen anzeigen/verstecken }); }); } // Funktion zur Überprüfung, ob genau ein sichtbarer Radio-Button ausgewählt wurde function checkCCLicenseSelection() { // Alle Radio-Buttons innerhalb des checkCCLicense-Divs finden const radioButtons = document.querySelectorAll('#checkCCLicense input[type="radio"][name="OAlicenseType"]'); // Zählen, wie viele sichtbare Radio-Buttons ausgewählt sind let selectedCount = 0; let selectedValue = null; let visibleCount = 0; let invisibleSelectedCount = 0; let isValid = true; radioButtons.forEach(radio => { const isVisible = isElementVisible(radio); if (isVisible) { visibleCount++; if (radio.checked) { selectedCount++; selectedValue = radio.value; } } else if (radio.checked) { // Ausgewählter aber unsichtbarer Radio-Button invisibleSelectedCount++; } }); // ist überhaupt eine Checkbox sichtbar? Wenn nein, return if (visibleCount == 0) return (isValid); // Prüfen, ob genau einer der sichtbaren Radio-Buttons ausgewählt ist isValid = selectedCount === 1 && invisibleSelectedCount === 0; return (isValid); /* return { isValid: isValid, selectedCount: selectedCount, selectedValue: selectedValue, visibleCount: visibleCount, invisibleSelectedCount: invisibleSelectedCount, message: isValid ? `Gültige Auswahl: ${selectedValue}` : selectedCount === 0 && invisibleSelectedCount === 0 ? 'Keine Lizenz ausgewählt' : selectedCount > 1 ? `Ungültig: ${selectedCount} sichtbare Lizenzen ausgewählt` : invisibleSelectedCount > 0 ? `Ungültig: ${invisibleSelectedCount} unsichtbare Radio-Buttons ausgewählt` : 'Ungültige Auswahl' }; */ } // Verwendung beim Formular-Submit function validateFormBeforeSubmit() { const licenseCheck = checkCCLicenseSelection(); if (!licenseCheck.isValid) { alert('Bitte wählen Sie eine Creative Commons Lizenz aus.'); return false; // Verhindert das Absenden des Formulars } console.log('Ausgewählte Lizenz:', licenseCheck.selectedValue); return true; // Formular kann abgesendet werden } // Initialisierung nach dem Laden der Seite document.addEventListener('DOMContentLoaded', function() { addCCLicenseValidation(); }); // Alle required-Felder finden und prüfen function validateRequiredFields() { const requiredFields = document.querySelectorAll('[required]'); let allValid = true; const emptyFields = []; requiredFields.forEach(field => { if (!field.value.trim()) { allValid = false; emptyFields.push(field.name || field.id); } }); // Spezialfall: hidden fields in uploadForm auswerten let a = ''; if(a = document.getElementById('publicatedDocument')) { console.log("hurray: publicatedDocument available" ); } else { emptyFields.push('publicatedDocument'); console.log("publicatedDocument not available" ); } if(a = document.getElementById('publicatedDocumentType')) { console.log("hurray: publicatedDocumentType available" ); } else { emptyFields.push('publicatedDocumentType'); console.log("publicatedDocumentType not available" ); } if (!allValid) { console.log('Leere Pflichtfelder:', emptyFields); } return emptyFields ; } // Prüfung wird in showSummary aufgerufen. Alternativ: bei Form-Submit prüfen /*document.getElementById('VEROData').addEventListener('submit', function(e) { if (!validateRequiredFields()) { e.preventDefault(); alert('Bitte füllen Sie alle Pflichtfelder aus!'); } }); */ // Funktion zum Aktivieren des Upload-Accordions function activateUploadAccordion() { // Accordion-Container und Button finden const accordionItem = document.getElementById('uploadData'); const accordionButton = accordionItem.querySelector('.accordion-button'); const accordionHeader = accordionItem.querySelector('h4'); // Inaktiv-Styling entfernen accordionItem.classList.remove('opacity-50'); accordionButton.classList.remove('text-muted'); accordionButton.style.cursor = ''; // Button aktivieren accordionButton.disabled = false; // Bootstrap-Attribute für Collapse-Funktionalität hinzufügen accordionButton.setAttribute('data-bs-toggle', 'collapse'); accordionButton.setAttribute('data-bs-target', '#collapseUpload'); // Inaktiv-Text entfernen (falls vorhanden) const inactiveText = accordionHeader.querySelector('small.text-muted'); if (inactiveText) { inactiveText.remove(); } // Optional: Text zu "Aktiv" ändern oder einfach nur "Dateiupload" lassen accordionHeader.innerHTML = 'Dateiupload'; console.log('Upload-Accordion wurde aktiviert'); } // Funktion zum Deaktivieren des Upload-Accordions function deactivateUploadAccordion() { // Accordion-Container und Button finden const accordionItem = document.getElementById('uploadData'); const accordionButton = accordionItem.querySelector('.accordion-button'); const accordionHeader = accordionItem.querySelector('h4'); const collapseElement = document.getElementById('collapseUpload'); // Accordion schließen falls geöffnet if (collapseElement.classList.contains('show')) { const bsCollapse = new bootstrap.Collapse(collapseElement); bsCollapse.hide(); } // Inaktiv-Styling hinzufügen accordionItem.classList.add('opacity-50'); accordionButton.classList.add('text-muted'); accordionButton.style.cursor = 'not-allowed'; // Button deaktivieren accordionButton.disabled = true; // Bootstrap-Attribute entfernen accordionButton.removeAttribute('data-bs-toggle'); accordionButton.removeAttribute('data-bs-target'); // Inaktiv-Text hinzufügen accordionHeader.innerHTML = 'Dateiupload - erst nach dem Ausfüllen der Vertragssektion verfügbar'; console.log('Upload-Accordion wurde deaktiviert'); } // DOM Ready Event document.addEventListener('DOMContentLoaded', function() { deactivateUploadAccordion(); });