1/** 2 * Formularversand für training-therapie-gesundheit.de 3 * Verschickt per fetch, zeigt Rückmeldungen direkt im Formular. 4 * Ohne JavaScript funktioniert das Formular weiterhin per normalem POST. 5 */ 6(function () { 7 'use strict'; 8 9 var formulare = document.querySelectorAll('form[data-ttg-form]'); 10 if (!formulare.length) return; 11 12 // Rückmeldung nach einer Weiterleitung (Absenden ohne JavaScript) 13 (function () { 14 var status = (window.location.search.match(/[?&]status=([^&]+)/) || [])[1]; 15 if (!status) return; 16 var feld = document.querySelector('.ttg-status'); 17 if (!feld) return; 18 if (status === 'ok') { 19 feld.textContent = 'Danke â deine Nachricht ist bei uns angekommen. Wir melden uns zeitnah bei dir.'; 20 feld.className = 'ttg-status ttg-status--erfolg'; 21 } else { 22 feld.textContent = 23 'Das hat leider nicht geklappt. Prüf bitte deine Angaben oder ruf uns an: 0 51 39 - 98 48 48 4'; 24 feld.className = 'ttg-status ttg-status--fehler'; 25 } 26 feld.hidden = false; 27 })(); 28 29 Array.prototype.forEach.call(formulare, function (form) { 30 // Zeitstempel für den Bot-Schutz setzen 31 var ts = form.querySelector('input[name="ts"]'); 32 if (ts) ts.value = Math.floor(Date.now() / 1000); 33 34 var status = form.querySelector('.ttg-status'); 35 var button = form.querySelector('button[type="submit"], input[type="submit"]'); 36 var buttonText = button ? (button.innerHTML || button.value) : ''; 37 38 function meldung(text, typ) { 39 if (!status) return; 40 status.textContent = text; 41 status.className = 'ttg-status ttg-status--' + typ; 42 status.setAttribute('role', typ === 'fehler' ? 'alert' : 'status'); 43 status.hidden = false; 44 } 45 46 function fehlerLeeren() { 47 Array.prototype.forEach.call(form.querySelectorAll('.ttg-feldfehler'), function (el) { 48 el.remove(); 49 }); 50 Array.prototype.forEach.call(form.querySelectorAll('.ttg-ungueltig'), function (el) { 51 el.classList.remove('ttg-ungueltig'); 52 el.removeAttribute('aria-invalid'); 53 }); 54 } 55 56 function feldFehler(name, text) { 57 var feld = form.querySelector('[name="' + name + '"]'); 58 if (!feld) return; 59 feld.classList.add('ttg-ungueltig'); 60 feld.setAttribute('aria-invalid', 'true'); 61 var hinweis = document.createElement('span'); 62 hinweis.className = 'ttg-feldfehler'; 63 hinweis.textContent = text; 64 (feld.parentNode || form).appendChild(hinweis); 65 } 66 67 form.addEventListener('submit', function (event) { 68 event.preventDefault(); 69 fehlerLeeren(); 70 71 if (button) { 72 button.disabled = true; 73 if ('innerHTML' in button) button.innerHTML = 'Wird gesendet â¦'; 74 else button.value = 'Wird gesendet â¦'; 75 } 76 meldung('Nachricht wird gesendet â¦', 'wartet'); 77 78 fetch(form.getAttribute('action'), { 79 method: 'POST', 80 body: new FormData(form), 81 headers: { 'X-Requested-With': 'XMLHttpRequest', Accept: 'application/json' } 82 }) 83 .then(function (antwort) { 84 return antwort.json().catch(function () { 85 throw new Error('Unerwartete Antwort vom Server'); 86 }); 87 }) 88 .then(function (daten) { 89 if (daten.ok) { 90 form.reset(); 91 if (ts) ts.value = Math.floor(Date.now() / 1000); 92 meldung(daten.message, 'erfolg'); 93 if (status && status.scrollIntoView) { 94 status.scrollIntoView({ behavior: 'smooth', block: 'center' }); 95 } 96 } else { 97 meldung(daten.message, 'fehler'); 98 if (daten.fields) { 99 Object.keys(daten.fields).forEach(function (name) { 100 feldFehler(name, daten.fields[name]); 101 }); 102 var erstes = form.querySelector('.ttg-ungueltig'); 103 if (erstes) erstes.focus(); 104 } 105 } 106 }) 107 .catch(function () { 108 meldung( 109 'Die Verbindung hat nicht geklappt. Versuch es bitte noch einmal oder ruf uns an: 0 51 39 - 98 48 48 4', 110 'fehler' 111 ); 112 }) 113 .finally(function () { 114 if (button) { 115 button.disabled = false;
116 if ('innerHTML' in button) button.innerHTML = buttonText; 117 else button.value = buttonText; 118 } 119 }); 120 }); 121 }); 122})();
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.