PageSourceSearch

https://www.creative-kirche.de/typo3temp/assets/compressed/accessible-form-validator-min.1791454389.js

js creative-kirche.de collected 2026-10-08 10:14:01 UTC 20,429 bytes, 43 lines download raw bytes

1class AccessibleFormValidator{constructor(form){this.inputSelector='input:not([type="hidden"]),select,textarea';this.form=form;this.fields=[...form.querySelectorAll('[data-validators]')];this.summary=this._createSummary();this._onSummaryClick=this._onSummaryClick.bind(this);this.summary.addEventListener('click',this._onSummaryClick);this.translations={de:{errorMessageDefault:'Ungültige Eingabe',summaryTitle:'Bitte korrigieren Sie die folgenden Eingaben:',valueMissing:'Bitte füllen Sie das Pflichtfeld „{label}“ aus.',typeMismatch_email:'Bitte geben Sie eine gültige E‑Mail‑Adresse ein (z. B. [email protected]).',typeMismatch_url:'Bitte geben Sie eine gültige URL ein (z. B. https://beispiel.de).',patternMismatch:'Das Format von „{label}“ ist ungültig. Erwartet: {patternHint}.',tooShort:'„{label}“ ist zu kurz – mindestens {minLength} Zeichen (aktuell {length}).',tooLong:'„{label}“ ist zu lang – höchstens {maxLength} Zeichen (aktuell {length}).',rangeUnderflow:'Der Wert von „{label}“ muss mindestens {min} betragen.',rangeOverflow:'Der Wert von „{label}“ darf höchstens {max} betragen.',stepMismatch:'Bitte verwenden Sie für „{label}“ eine Schrittweite von {step}.',badInput:'Bitte geben Sie in „{label}“ nur numerische Werte ein.',customError:'Ungültige Eingabe.',integerInvalid:'„{label}“ darf nur ganze Zahlen enthalten.',floatInvalid:'„{label}“ muss eine Zahl sein (Dezimaltrennzeichen „.“ oder „,“).',numberRangeInvalid:'Der Wert von „{label}“ muss zwischen {min} und {max} liegen.',dateInvalid:'„{label}“ muss ein gültiges Datum im Format JJJJ‑MM‑TT sein.',dateRangeInvalid:'Das Datum in „{label}“ muss zwischen {min} und {max} liegen.',alphanumericInvalid:'„{label}“ darf nur Buchstaben und Ziffern enthalten (keine Leer‑ oder Sonderzeichen).'},de_du:{errorMessageDefault:'Ungültige Eingabe',summaryTitle:'Bitte korrigiere die folgenden Eingaben:',valueMissing:'Bitte fülle das Pflichtfeld „{label}“ aus.',typeMismatch_email:'Bitte gib eine gültige E‑Mail‑Adresse ein (z. B. [email protected]).',typeMismatch_url:'Bitte gib eine gültige URL ein (z. B. https://beispiel.de).',patternMismatch:'Das Format von „{label}“ ist ungültig. Erwartet: {patternHint}.',tooShort:'„{label}“ ist zu kurz – mindestens {minLength} Zeichen (aktuell {length}).',tooLong:'„{label}“ ist zu lang – maximal {maxLength} Zeichen (aktuell {length}).',rangeUnderflow:'Der Wert von „{label}“ muss mindestens {min} sein.',rangeOverflow:'Der Wert von „{label}“ darf höchstens {max} sein.',stepMismatch:'Bitte verwende für „{label}“ einen zulässigen Schritt von {step}.',badInput:'Bitte gib in „{label}“ nur numerische Werte ein.',customError:'Ungültige Eingabe.',integerInvalid:'„{label}“ darf nur ganze Zahlen enthalten.',floatInvalid:'„{label}“ muss eine Zahl sein (Punkt oder Komma als Dezimaltrennzeichen).',numberRangeInvalid:'Der Wert von „{label}“ muss zwischen {min} und {max} liegen.',dateInvalid:'„{label}“ muss ein gültiges Datum im Format YYYY‑MM‑DD sein.',dateRangeInvalid:'Das Datum in „{label}“ muss zwischen {min} und {max} liegen.',alphanumericInvalid:'„{label}“ darf nur Buchstaben und Ziffern enthalten (keine Leer‑ oder Sonderzeichen).'},en:{errorMessageDefault:'Invalid input',summaryTitle:'Please correct the following fields:',valueMissing:'Please fill in the required field “{label}”.',typeMismatch_email:'Enter a valid e‑mail address (e.g. [email protected]).',typeMismatch_url:'Enter a valid URL (e.g. https://example.com).',patternMismatch:'The format of “{label}” is invalid. Expected: {patternHint}.',tooShort:'“{label}” is too short – minimum {minLength} characters (currently {length}).',tooLong:'“{label}” is too long – maximum {maxLength} characters (currently {length}).',rangeUnderflow:'The value of “{label}” must be at least {min}.',rangeOverflow:'The value of “{label}” must not exceed {max}.',stepMismatch:'Please use a valid step of {step} for “{label}”.',badInput:'Please enter numeric values only in “{label}”.',customError:'Invalid input.',integerInvalid:'“{label}” must contain whole numbers only.',floatInvalid:'“{label}” has to be a number (decimal separator “.” or “,”).',numberRangeInvalid:'The value of “{label}” must be between {min} and {max}.',dateInvalid:'“{label}” must be a valid date in YYYY‑MM‑DD format.',dateRangeInvalid:'The date in “{label}” must be between {min} and {max}.',alphanumericInvalid:'“{label}” may contain letters and digits only (no spaces or special chars).'},fr:{errorMessageDefault:'Entrée non valide',summaryTitle:'Veuillez corriger les informations suivantes :',valueMissing:'Veuillez remplir le champ obligatoire « {label} ».',typeMismatch_email:'Veuillez saisir une adresse e-mail valide (par exemple, [email protected]).',typeMismatch_url:'
1Veuillez saisir une URL valide (par exemple https://beispiel.de).',patternMismatch:'Le format de « {label} » n\'est pas valide. Attendu : {patternHint}.',tooShort:'« {label} » est trop court – au moins {minLength} caractères (actuellement {length}).',tooLong:'« {label} » est trop long – {maxLength} caractères maximum (actuellement {length}).',rangeUnderflow:'La valeur de « {label} » doit être au moins égale à {min}.',rangeOverflow:'La valeur de « {label} » ne doit pas dépasser {max}.',stepMismatch:'Veuillez utiliser un incrément de {step} pour « {label} ».',badInput:'Veuillez saisir uniquement des valeurs numériques dans « {label} ».',customError:'Entrée non valide.',integerInvalid:'« {label} » ne peut contenir que des nombres entiers.',floatInvalid:'« {label} » doit être un nombre (séparateur décimal « . » ou « , »).',numberRangeInvalid:'La valeur de « {label} » doit être comprise entre {min} et {max}.',dateInvalid:'« {label} » doit être une date valide au format AAAA-MM-JJ.',dateRangeInvalid:'La date dans « {label} » doit être comprise entre {min} et {max}.',alphanumericInvalid:'« {label} » ne doit contenir que des lettres et des chiffres (pas d\'espaces ni de caractères spéciaux).'},ru:{errorMessageDefault:'Неверный ввод',summaryTitle:'Пожалуйста, исправьте следующие данные:',valueMissing:'Пожалуйста, заполните обязательное поле «{label}».',typeMismatch_email:'Введите действительный адрес электронной почты (например, [email protected]).',typeMismatch_url:'Введите действительный URL-адрес (например, https://beispiel.de).',patternMismatch:'Формат «{label}» недействителен. Ожидается: {patternHint}.',tooShort:'«{label}» слишком короткий — не менее {minLength} символов (в настоящее время {length}).',tooLong:'«{label}» слишком длинный — не более {maxLength} символов (в настоящее время {length}).',rangeUnderflow:'Значение «{label}» должно быть не менее {min}.',rangeOverflow:'Значение «{label}» не должно превышать {max}.',stepMismatch:'Пожалуйста, используйте для «{label}» шаг {step}.',badInput:'Пожалуйста, введите в поле «{label}» только числовые значения.',customError:'Неверный ввод.',integerInvalid:'«{label}» может содержать только целые числа.',floatInvalid:'«{label}» должен быть числом (десятичный разделитель «.» или «,»).',numberRangeInvalid:'Значение «{label}» должно быть в диапазоне от {min} до {max}.',dateInvalid:'«{label}» должен быть действительной датой в формате ГГГГ-ММ-ДД.',dateRangeInvalid:'Дата в «{label}» должна находиться в диапазоне от {min} до {max}.',alphanumericInvalid:'«{label}» может содержать только буквы и цифры (без пробелов и специальных символов).'},pt:{errorMessageDefault:'Entrada inválida',summaryTitle:'Por favor, corrija os seguintes dados:',valueMissing:'Preencha o campo obrigatório «{label}».',typeMismatch_email:'Insira um endereço de e-mail válido (por exemplo, [email protected]).',typeMismatch_url:'Insira um URL válido (por exemplo, https://beispiel.de).',patternMismatch:'O formato de «{label}» não é válido. Esperado: {patternHint}.',tooShort:'«{label}» é demasiado curto – pelo menos {minLength} caracteres (atualmente {length}).',tooLong:'«{label}» é demasiado longo – no máximo {maxLength} caracteres (atualmente {length}).',rangeUnderflow:'O valor de «{label}» deve ser pelo menos {min}.',rangeOverflow:'O valor de «{label}» não pode ser superior a {max}.',stepMismatch:'Bitte verwenden Sie für „{label}“ eine Schrittweite von {step}.',badInput:'Por favor, insira apenas valores numéricos em «{label}».',customError:'Entrada inválida.',integerInvalid:'«{label}» só pode conter números inteiros.',floatInvalid:'«{label}» deve ser um número (separador decimal «.» ou «,»).',numberRangeInvalid:'O valor de «{label}» deve estar entre {min} e {max}.',dateInvalid:'«{label}» deve ser uma data válida no formato AAAA-MM-DD.',dateRangeInvalid:'A data em «{label}» deve estar entre {min} e {max}.',alphanumericInvalid:'«{label}» só pode conter letras e números (sem espaços ou caracteres especiais).'},es:{errorMessageDefault:'Entrada no válida',summaryTitle:'Por favor, corrija los siguientes datos:',valueMissing:'Por favor, rellene el c
1ampo obligatorio «{label}».',typeMismatch_email:'Introduzca una dirección de correo electrónico válida (por ejemplo, [email protected]).',typeMismatch_url:'Introduzca una URL válida (por ejemplo, https://beispiel.de).',patternMismatch:'El formato de «{label}» no es válido. Se espera: {patternHint}.',tooShort:'«{label}» es demasiado corto: debe tener al menos {minLength} caracteres (actualmente {length}).',tooLong:'«{label}» es demasiado largo: como máximo {maxLength} caracteres (actualmente {length}).',rangeUnderflow:'El valor de «{label}» debe ser como mínimo {min}.',rangeOverflow:'El valor de «{label}» no puede ser superior a {max}.',stepMismatch:'Por favor, utilice un incremento de {step} para «{label}».',badInput:'Por favor, introduzca solo valores numéricos en «{label}».',customError:'Entrada no válida.',integerInvalid:'«{label}» solo puede contener números enteros.',floatInvalid:'«{label}» debe ser un número (separador decimal «.» o «,»).',numberRangeInvalid:'El valor de «{label}» debe estar comprendido entre {min} y {max}.',dateInvalid:'«{label}» debe ser una fecha válida en formato AAAA-MM-DD.',dateRangeInvalid:'La fecha en «{label}» debe estar comprendida entre {min} y {max}.',alphanumericInvalid:'«{label}» solo puede contener letras y números (sin espacios ni caracteres especiales).'},};this._bindEvents();this._processErrorsFromServer()}
2validateAll(){const invalid=this.fields.map(group=>this._validateGroup(group,!1)).filter(Boolean);this._renderSummary(invalid);return invalid.length===0}
3_bindEvents(){this.fields.forEach(group=>{const inputs=group.querySelectorAll(this.inputSelector);inputs.forEach(el=>{const validate=()=>this._validateGroup(group);if(el.tagName==='SELECT'){el.addEventListener('change',validate);return}
4switch(el.type){case 'radio':case 'checkbox':case 'file':case 'color':case 'date':case 'time':case 'datetime-local':case 'month':case 'week':el.addEventListener('change',validate);break;case 'range':el.addEventListener('input',validate);el.addEventListener('change',validate);break;default:el.addEventListener('blur',validate);el.addEventListener('change',validate)}})});this.form.addEventListener('submit',e=>
4{if(!this.validateAll())e.preventDefault();});const submitBtn=this.form.querySelector('button[type="submit"], input[type="submit"]');if(submitBtn){submitBtn.addEventListener('click',e=>{if(!this.validateAll())e.preventDefault();})}}
5_createSummary(){const s=document.createElement('div');s.className='visually-hidden error-summary';s.setAttribute('aria-hidden','true');s.id=`${this.form.id || 'form'}-error-summary`;s.tabIndex=-1;this.form.prepend(s);return s}
6_validateGroup(group,errorIsAlert=!0){const input=group.querySelector(this.inputSelector);if(!input)return null;const errorId=`${input.id}-error`;let msg='';let valid=!0;if(!input.checkValidity()){valid=!1;msg=this._mapValidityToMessage(input)}else{const customValidation=this._checkCustomValidators(group);if(!customValidation.valid){valid=!1;msg=customValidation.message}}
7let msgEl=group.querySelector(`#${errorId}`);if(!valid){if(!msgEl){msgEl=this._buildErrorNode(errorId);group.appendChild(msgEl)}
8if(errorIsAlert){if(msgEl.getAttribute('role')!=='alert'){msgEl.setAttribute('role','alert')}}else{msgEl.removeAttribute('role')}
9msgEl.textContent=msg;msgEl.hidden=!1;if(input.type==='radio'){const radios=group.querySelectorAll('input[type="radio"]');radios.forEach(radio=>{radio.setAttribute('aria-invalid','true');this._addDescribedBy(radio,errorId)});return{input:radios[0],errorMessage:msg}}else{input.setAttribute('aria-invalid','true');input.classList.add('error');this._addDescribedBy(input,errorId);return{input,errorMessage:msg}}}
10if(msgEl)msgEl.hidden=!0;if(input.type==='radio'){const radios=group.querySelectorAll('input[type="radio"]');radios.forEach(radio=>{radio.removeAttribute('aria-invalid');this._removeDescribedBy(radio,errorId)})}else{input.removeAttribute('aria-invalid');input.classList.remove('error');this._removeDescribedBy(input,errorId)}
11return null}
12_getLabel(el){const lblEl=el.form.querySelector(`label[for="${el.id}"]`);if(!lblEl)return el.name||el.id||'Feld';let text=lblEl.textContent.replace(/[*✱*]+/g,'').replace(/\(\s*\)/g,'').trim();return text.length?text:(el.name||el.id||'Feld')}
13_interpolate(str,obj={}){return str.replace(/\{(\w+)}/g,(_,k)=>(k in obj?obj[k]:''))}
14_mapValidityToMessage(el){const v=el.validity;const t=key=>this._translate(key);const lbl=this._getLabel(el);if(v.valueMissing)
15return this._interpolate(t('valueMissing'),{label:lbl});if(v.typeMismatch){if(el.type==='email')
16return this._interpolate(t('typeMismatch_email'),{label:lbl});if(el.type==='url')
17return this._interpolate(t('typeMismatch_url'),{label:lbl});return t('errorMessageDefault')}
18if(v.patternMismatch){const patternHint=el.getAttribute('title')||el.dataset.patternHint||el.getAttribute('pattern')||'';return this._interpolate(t('patternMismatch'),{label:lbl,patternHint})}
19if(v.tooShort)
20return this._interpolate(t('tooShort'),{label:lbl,minLength:el.minLength,length:el.value.length});if(v.tooLong)
21return this._interpolate(t('tooLong'),{label:lbl,maxLength:el.maxLength,length:el.value.length});if(v.rangeUnderflow)
22return this._interpolate(t('rangeUnderflow'),{label:lbl,min:el.min});if(v.rangeOverflow)
23return this._interpolate(t('rangeOverflow'),{label:lbl,max:el.max});if(v.stepMismatch)
24return this._interpolate(t('stepMismatch'),{label:lbl,step:el.step});if(v.badInput)
25return this._interpolate(t('badInput'),{label:lbl});if(v.customError)
26return el.validationMessage||t('customError');return null}
27_checkCustomValidators(group){const input=group.querySelector(this.inputSelector);const raw=input.value;const value=raw.trim();const vReq=(group.dataset.validators||'').split(',').map(v=>v.trim());const lbl=this._getLabel(input);const t=key=>this._translate(key);const msg=(key,obj={})=>this._interpolate(t(key),{label:lbl,...obj});const num=v=>parseFloat(v.replace(',','.'));const validators={IntegerValidator:{test:v=>/^-?\d+$/.test(v),err:()=>msg('integerInvalid')},FloatValidator:{test:v=>/^-?\d+([.,]\d+)?$/.test(v),err:()=>msg('floatInvalid')},NumberRangeValidator:{test:v=>{const n=num(v);if(Number.isNaN(n))return!1;const min=num(input.getAttribute('min')||input.dataset.min||-Infinity);const max=num(input.getAttribute('max')||input.dataset.max||Infinity);return n>=min&&n<=max},err:()=>msg('numberRangeInvalid',{min:input.getAttribute('min')||input.dataset.min,max:input.getAttribute('max')||input.dataset.max})},DateValidator:{test:v=>{if(input.type==='date')return input.checkValidity();return/^\d{4}-\d{2}-\d{2}$/.test(v)&&!Number.isNaN(Date.parse(v))},err:()=>msg('dateInvalid')},DateRangeValidator:{test:v=>{const okDate=validators.DateValidator.test(v);
27if(!okDate)return!1;const ts=Date.parse(v);const minTs=input.getAttribute('min')?Date.parse(input.getAttribute('min')):-Infinity;const maxTs=input.getAttribute('max')?Date.parse(input.getAttribute('max')):Infinity;return ts>=minTs&&ts<=maxTs},err:()=>msg('dateRangeInvalid',{min:input.getAttribute('min')||'–',max:input.getAttribute('max')||'–'})},AlphanumericValidator:{test:v=>v===''||/^[0-9a-zA-Z]+$/.test(v),err:()=>msg('alphanumericInvalid')},NotEmptyValidator:{test:()=>!0},StringLengthValidator:{test:()=>!0},EmailAddressValidator:{test:()=>!0},RegularExpressionValidator:{test:()=>!0},UrlValidator:{test:()=>!0}};if(value!==''){for(const name of vReq){const rule=validators[name];if(rule&&!rule.test(value)){return{valid:!1,message:rule.err?rule.err():t('errorMessageDefault')}}}}
28return{valid:!0,message:null}}
29_buildErrorNode(errorId){let errorNode=document.createElement('p');errorNode.id=errorId;errorNode.className='error help-block';errorNode.setAttribute('role','alert');errorNode.hidden=!0;return errorNode}
30_addDescribedBy(el,id){const ids=new Set((el.getAttribute('aria-describedby')||'').split(/\s+/).filter(Boolean));ids.add(id);el.setAttribute('aria-describedby',[...ids].join(' '))}
31_removeDescribedBy(el,id){const ids=(el.getAttribute('aria-describedby')||'').split(/\s+/).filter(i=>i&&i!==id);ids.length?el.setAttribute('aria-describedby',ids.join(' ')):el.removeAttribute('aria-describedby')}
32_renderSummary(invalid){if(!invalid.length){this.summary.classList.add('visually-hidden');this.summary.setAttribute('aria-hidden','true');this.summary.innerHTML='';return}
33const items=invalid.map(({input,errorMessage})=>`<li><a data-summary-link href="#${input.id}">${errorMessage}</a></li>`).join('')
34this.summary.innerHTML=`<h2 class="h5 mb-2">${this._translate('summaryTitle')}</h2><ul>${items}</ul>`;this.summary.classList.remove('visually-hidden');this.summary.setAttribute('aria-hidden','false');this.summary.focus()}
35_processErrorsFromServer(){let errorsFromServer=[];this.fields.forEach(group=>{if(group.classList.contains('has-error')){const input=group.querySelector(this.inputSelector);if(!input)return;let errorNode=group.querySelector('.error.help-block');if(!errorNode){errorNode=this._buildErrorNode(`${input.id}-error`);errorNode.textContent=input.dataset.errorMessage||'Ungültige Eingabe';group.appendChild(errorNode)}else{errorNode.id=`${input.id}-error`}
36errorNode.hidden=!1;if(input.type==='radio'){const radios=group.querySelectorAll('input[type="radio"]');radios.forEach(radio=>{radio.setAttribute('aria-invalid','true');this._addDescribedBy(radio,errorNode.id)})}else{input.setAttribute('aria-invalid','true');this._addDescribedBy(input,errorNode.id)}
37errorsFromServer.push({input,errorMessage:errorNode.textContent})}});if(errorsFromServer.length>0){this._renderSummary(errorsFromServer)}}
38_translate(key){const doc=document.documentElement;const baseLang=doc.lang?doc.lang.split('-')[0]:'en';let tone=(doc.dataset.tone||'').toLowerCase();if(baseLang==='de'){if(!tone)tone='sie';if(tone==='informal')tone='du';if(tone==='formal')tone='sie'}else{tone=''}
39const langKey=tone&&this.translations[`${baseLang}_${tone}`]?`${baseLang}_${tone}`:baseLang;if(this.translations[langKey]&&this.translations[langKey][key]){return this.translations[langKey][key]}
40if(this.translations[baseLang]&&this.translations[baseLang][key]){return this.translations[baseLang][key]}
41return key}
42_onSummaryClick(e){const link=e.target.closest('[data-summary-link]');if(!link)return;e.preventDefault();const id=link.getAttribute('href').slice(1);const el=document.getElementById(id);if(!el)return;el.focus()}}
43document.addEventListener('DOMContentLoaded',()=>{document.querySelectorAll('form').forEach(f=>new AccessibleFormValidator(f))})

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.