VERO/js/script.js
2026-03-04 10:12:09 +01:00

2557 lines
83 KiB
JavaScript

//
// 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 = '<div class="modal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Modal title</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <p>Modal body text goes here.</p> </div> </div></div></div>'
alert (r);
break;
case 'helpFirstTitle': var r = "<h5>Hinweis zur Erfassung von AutorInnen</h5>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 = `
<div class="toast align-items-center text-white bg-danger border-0" role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body">
<strong>Fehler:</strong> ${message}
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
`;
// 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 type="button" class="btn btn-outline-secondary btn-sm" onclick="backToDocumentTypeSelection()">
<i class="bi bi-arrow-left"></i> Zurück zur Dokumenttyp-Auswahl
</button>
`;
// 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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#x27;')
.replace(/\//g, '&#x2F;');
}
/**
* 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, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#x27;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
/**
* 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 <span style="font-size:20px;" class="text-muted"> - erst nach dem Ausfüllen der Vertragssektion verfügbar</span>';
console.log('Upload-Accordion wurde deaktiviert');
}
// DOM Ready Event
document.addEventListener('DOMContentLoaded', function() {
deactivateUploadAccordion();
});