PageSourceSearch

https://www.frauenbund-augsburg.de/_js/form-validation.js?b4b256f200075592

js frauenbund-augsburg.de collected 2026-10-08 02:36:29 UTC 8,620 bytes, 240 lines download raw bytes

1//Variablen aus header_global_js.elem.php
2/** @var string formValidationError */
3/** @var string formValidationErrorDateTooOld */
4/** @var string formValidationErrorDateTooYoung */
5
6
7$(document).ready(function () {
8    const $form = $('.defaultform');
9    let liveValidationActive = false;
10    // Alle Eingabefelder im Formular auswählen
11    $form.find('input:not(.validate-fields)').on('keypress', function (event) {
12        if (event.key === 'Enter') {
13            event.preventDefault();
14        }
15    });
16
17    function validateField($input) {
18        const element = $input.get(0);
19        const type = $input.attr('type');
20        const name = $input.attr('name');
21        const isCheckboxOrRadio = type === 'radio' || type === 'checkbox';
22        const isFile = type === 'file';
23        let valueValid = true;
24        let errorType = '';
25
26        if (isCheckboxOrRadio) {
27            valueValid = $form.find(`input[name="${name}"]:checked`).length > 0;
28        } else if (isFile) {
29            valueValid = $input.get(0).files.length > 0;
30        } else {
31            valueValid = $input.get(0).checkValidity();
32
33            // IBAN prüfen
34            if (valueValid && $input.hasClass('validation-iban')) {
35                valueValid = isValidGermanIban(element.value);
36
37                if (!valueValid) {
38                    errorType = 'ibanChecksumInvalid';
39                }
40            }
41            if (!valueValid && !errorType) {
42                const v = element.validity;
43
44                if (v.valueMissing) errorType = 'valueMissing';
45                else if (v.patternMismatch) errorType = 'patternMismatch';
46                else if (v.rangeUnderflow) errorType = 'rangeUnderflow';
47                else if (v.rangeOverflow) errorType = 'rangeOverflow';
48                else errorType = 'invalid';
49            }
50        }
51
52        const $container = $input.closest('.form-row, fieldset');
53        let $label;
54
55        if (isCheckboxOrRadio) {
56            $label = $container.find('legend');
57
58        } else if (isFile) {
59            const cleanName = name.replace(/\[\]$/, '');
60            $label = $container.find(`label[for="${cleanName}"]`);
61        } else {
62            $label = $container.find(`label[for="${$input.attr('id')}"]`);
63        }
64
65        if (valueValid) {
66            $input.removeClass('error').removeAttr('aria-invalid');
67            if (isCheckboxOrRadio) {
68                let container = $($input.parents('.form-row').first());
69                $(container).find('input').removeClass('error').removeAttr('aria-invalid');
70            }
71            if ($label.length && $label.data('original')) {
72                $label.text($label.data('original'));
73            }
74        } else {
75            if ($label.length && !$label.data('original')) {
76                $label.data('original', $label.text());
77            }
78            let errorMsg = formValidationError;
79            if (errorType === 'rangeUnderflow') {
80                errorMsg = formValidationErrorDateTooOld;
81            }
82            if (errorType === 'rangeOverflow') {
83                errorMsg = formValidationErrorDateTooYoung;
84            }
85            if (errorType === 'ibanChecksumInvalid') {
86                errorMsg = formValidationErrorIbanChecksumInvalid;
87            }
88
89            if ($label.length) {
90                $label.text(`${$label.data('original')} – ${errorMsg}`);
91            }
92
93            $input.addClass('error').attr('aria-invalid', 'true');
94        }
95
96        return valueValid;
97    }
98
99    function validateDate($input) {
100        const element = $input.get(0);
101        let valueValid = true;
102        let errorType = '';
103
104
105        valueValid = $input.get(0).checkValidity();
106
107        if (!valueValid) {
108            const v = element.validity;
109
110            if (v.rangeUnderflow) errorType = 'rangeUnderflow';
111            else if (v.rangeOverflow) errorType = 'rangeOverflow';
112        }
113
114
115        const $container = $input.closest('.form-row, fieldset');
116        let $label;
117
118        $label = $container.find(`label[for="${$input.attr('id')}"]`);
119
120
121        if (valueValid) {
122            $input.removeClass('error').removeAttr('aria-invalid');
123            if ($label.length && $label.data('original')) {
124                $label.text($label.data('original'));
125            }
126        } else {
127            if ($label.length && !$label.data('original')) {
128                $label.data('original', $label.text());
129            }
130            let errorMsg = formValidationError;
131            if (errorType === 'rangeUnderflow') {
132                errorMsg = formValidationErrorDateTooOld;
133            }
134            if (errorType === 'rangeOverflow') {
135                errorMsg = formValidationErrorDateTooYoung;
136            }
137
138            if ($label.length) {
139                $label.text(`${$label.data('original')} – ${errorMsg}`);
140            }
141
142            $input.addClass('error').attr('aria-invalid', 'true');
143        }
144
145        return valueValid;
146    }
147
148    $form.find('.validate-fields').on('click', function (e) {
149        let isValid = true;
150
151        // Fehler zurücksetzen
152        $form.find('.form-row').each(function () {
153            const $container = $(this);
154            const $input = $container.find('input, select, textarea').first();
155            const isCheckboxOrRadio = $input.is(':checkbox') || $input.is(':radio');
156            const isFile = $input.is('[type="file"]');
157
158            let $label;
159            if (isCheckboxOrRadio) {
160                $label = $container.find('legend');
161                $container.find('input').removeClass('error').removeAttr('aria-invalid');
162            } else if (isFile) {
163                $label = $container.find(`label[for="${$container.find('.filepond--root').attr('id')}"]`);
164                $input.removeClass('error').removeAttr('aria-invalid');
165            } else {
166                $label = $container.find(`label[for="${$input.attr('id')}"]`);
167                $input.removeClass('error').removeAttr('aria-invalid');
168            }
169
170            if ($label.length && $label.data('original')) {
171                $label.text($label.data('original'));
172            }
173        });
174
175        // Validierung aller required Felder
176        $form.find('input[required], select[required], textarea[required]').each(function () {
177            if (!validateField($(this))) {
178                isValid = false;
179            }
180        });
181
182        // Überprüfung für korrekte Angabe von Date-Feldern die nicht wegen required gecheckt wurden
183        $form.find('input[type="date"]:not([required])').each(function () {
184            if (!validateDate($(this))) {
185                isValid = false;
186            }
187        });
188
189        // Live-Validierung aktivieren nach dem ersten Klick
190        if (!liveValidationActive) {
191            liveValidationActive = true;
192            $form.on('blur change', 'input[required], select[required], textarea[required]', function () {
193                if (liveValidationActive) {
194                    validateField($(this));
195                }
196            });
197
198            $form.on('blur change', 'input[type="date"]:not([required])', function () {
199                if (liveValidationActive) {
200                    validateDate($(this));
201                }
202            });
203        }
204
205        let buttonIsSubmit = $(this).is('button[type="submit"], input[type="submit"]');
206        if (!isValid && !buttonIsSubmit) {
207            $('.error').first().focus();
208        }
209
210
211        // Wenn du ein tatsächliches `submit` verhindern willst, kannst du hier `e.preventDefault()` verwenden
212        // if (!isValid) e.preventDefault();
213    });
214});
215
216function isValidGermanIban(value) {
217    const iban = value.replace(/\s+/g, '').toUpperCase();
218
219    // Deutsche IBAN: DE + 2 Prüfziffern + 18 Ziffern = 22 Zeichen
220    if (!/^DE\d{20}$/.test(iban)) {
221        return false;
222    }
223
224    // IBAN-Prüfung:
225    // 1. Erste 4 Zeichen nach hinten
226    // 2. Buchstaben in Zahlen umwandeln: A=10, B=11, ..., Z=35
227    const rearranged = iban.slice(4) + iban.slice(0, 4);
228
229    const numeric = rearranged.replace(/[A-Z]/g, char => {
230        return String(char.charCodeAt(0) - 55);
231    });
232
233    // Modulo 97 iterativ berechnen, weil die Zahl zu groß für JS Number ist
234    let remainder = 0;
235
236    for (const digit of numeric) {
237        remainder = (remainder * 10 + Number(digit)) % 97;
238    }
239    return remainder === 1;
240}

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.