diff --git a/assets/js/kontaktformular.js b/assets/js/kontaktformular.js index 8e29dcf..5176287 100644 --- a/assets/js/kontaktformular.js +++ b/assets/js/kontaktformular.js @@ -1,229 +1,152 @@ -// Configuration and Messages -const debugEnabled = true -const mouseDebugEnabled = false -const zsrCheckEnabled = false -const interactionThreshold = 15 // Time in seconds -const interactionCountThreshold = 5 // Number of interactions -let botDetected = false -let currentMessages = [] +window.onload = function () { + const FORMDEBUG = false + const btn = document.getElementById('kontaktformular-btn') + const kontaktformular = document.getElementById('kontaktformular') -const messages = { - de: { + // custom Validation messages + const messagesGerman = { required: 'Bitte füllen Sie dieses Feld aus', email: 'Bitte geben Sie eine gültige E-Mail-Adresse ein', - success: 'Die Bestellung wurde erfolgreich übermittelt!', - thankyou: 'Vielen Dank für Ihre Anfrage.', - zsrTooltip: 'Bitte geben Sie eine gültige ZSR-Nummer, oder "beantragt" ein.', - captcha: 'Geben Sie den angezeigten Captcha-Code ein', - captchaButton: 'Überprüfen', - }, - fr: { + minlength: 'Bitte geben Sie mindestens {0} Zeichen ein', + maxlength: 'Bitte geben Sie maximal {0} Zeichen ein', + min: 'Bitte geben Sie mindestens {0} ein', + max: 'Bitte geben Sie maximal {0} ein', + range: 'Bitte geben Sie zwischen {0} und {1} ein', + } + const messagesFrench = { required: 'Veuillez remplir ce champ', email: 'Veuillez saisir une adresse email valide', - success: 'La commande a bien été envoyée!', - thankyou: 'Merci de votre demande.', - zsrTooltip: 'Veuillez saisir une ZSR-Nummer valide, ou indiquer "demandé".', - captcha: 'Entrez le code Captcha affiché', - captchaButton: 'Vérifier', - }, -} - -// DOM Selectors -const debugLabel = document.createElement('div') -const submitButton = document.getElementById('kontaktformular-btn') -const form = document.querySelector('form#kontaktformular') -const notification = document.getElementById('notification') -const zsrTooltip = document.getElementById('zsr-tooltip') -const honeypotInput1 = document.getElementById('age') -const honeypotInput2 = document.getElementById('hobbies') -const verifyEmailInput = document.getElementById('verify_email') -const emailInput = document.getElementById('mail') -const textInputs = document.querySelectorAll('input[type="text"]') -const captcha = document.querySelectorAll('.captcha') -const captchaInput = document.querySelectorAll('.captcha-input') -const captchaVerifyButton = document.querySelectorAll('.captcha-verify') -const botBadge = document.createElement('div') -if (debugEnabled) { - botBadge.className = 'bot-badge' - document.body.appendChild(botBadge) - botBadge.setAttribute( - 'style', - 'position: fixed; top: 0; right: 0; z-index: 9999; background-color: red; color: white; font-weight: bold; height:20px; width:20px' - ) -} - -// Utility variables -let startTime = Date.now() -let interactionCount = 0 -let userInteracted = false -let lastInteractionTime = null -const mousePositions = [] -const interactionTimes = [] -let isStraightLine = true - -// Utility functions -function log(thing) { - console.log(thing) -} - -function getCurrentLangMessages() { - log(messages[document.documentElement.lang.split('-')[0]]) - return messages[document.documentElement.lang.split('-')[0]] -} - -function setUserInteracted() { - userInteracted = true - interactionCount++ - checkForBotBehavior() -} - -function handleMouseMove(event) { - mousePositions.push({ x: event.clientX, y: event.clientY }) - if (debugEnabled && mouseDebugEnabled) log('Mouse Position:', { x: event.clientX, y: event.clientY }) - - if (mousePositions.length > 2) { - const len = mousePositions.length - const { x: x1, y: y1 } = mousePositions[len - 3] - const { x: x2, y: y2 } = mousePositions[len - 2] - const { x: x3, y: y3 } = mousePositions[len - 1] - - // Calculate the area of the triangle formed by three consecutive points - const area = 0.5 * Math.abs(x1 * y2 + x2 * y3 + x3 * y1 - y1 * x2 - y2 * x3 - y3 * x1) - if (debugEnabled && mouseDebugEnabled) log('Triangle Area:', area) - - if (area > 0.5) { - // Threshold for detecting non-straight line, adjust as needed - isStraightLine = false - if (debugEnabled && mouseDebugEnabled) log('Detected non-straight line movement.') - } - } -} - -function checkForBotBehavior() { - let timeSpent = (Date.now() - startTime) / 1000 - botDetected = - !userInteracted || - interactionCount === 0 || - honeypotInput1.value !== '' || - honeypotInput2.value !== '' || - verifyEmailInput.value !== '' - if (debugEnabled) - if (!botDetected) { - botBadge.style.backgroundColor = 'green' - } else { - botBadge.style.backgroundColor = 'red' - } - console.log( - 'Bot Detected: ' + - botDetected + - ' userInteracted:' + - userInteracted + - ' interactionCount:' + - interactionCount + - ' timeSpent:' + - timeSpent + - ' isStraightLine:' + - isStraightLine + - ' mousePositions:' + - mousePositions.length + - ' honeypotInput1:' + - honeypotInput1.value + - ' honeypotInput2:' + - honeypotInput2.value + - ' verifyEmailInput:' + - verifyEmailInput.value - ) -} -function handleSubmit(e) { - e.preventDefault() - - currentMessages = getCurrentLangMessages() - - checkForBotBehavior() - if (botDetected) { - fakeOut() - return false + minlength: 'Veuillez saisir au moins {0} caractères', + maxlength: 'Veuillez saisir au plus {0} caractères', + min: 'Veuillez saisir au moins {0} caractères', + max: 'Veuillez saisir au plus {0} caractères', + range: 'Veuillez saisir au moins {0} et au plus {1} caractères', } - const formData = new FormData(form) - const formDataEncoded = new URLSearchParams(formData).toString() - const formURL = form.action + '.json' + // custom Validation rules + // determine which language depending on html lang attribute + const lang = document.documentElement.lang + console.log('lang', lang) + const messages = lang === 'de-DE' ? messagesGerman : messagesFrench + // set custom validation messages for each validator + console.log('messages', messages) - fetch(formURL, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', // Wichtig für die Vermeidung von CORS-Problemen - }, - body: formDataEncoded, + let textInputs = document.querySelectorAll('input[type="text"]') + const emailInput = document.getElementById('email') + + Array.from(textInputs).forEach(function (input) { + input.addEventListener('invalid', function () { + this.setCustomValidity(messages['required']) + }) }) - .then((response) => { - if (!response.ok) { - throw new Error('Network response was not ok') - } - return response.json() - }) - .then((data) => { - submitButton.disabled = true - submitButton.innerHTML = ` - - ` - setTimeout(() => { - // if data.success is true, show a success message - if (data) { - submitButton.style.display = 'none' - notification.innerHTML = `${currentMessages.thankyou}` - notification.className = 'bg-green-500 text-white px-4 py-2 rounded block' - } else { - submitButton.style.display = 'none' - notification.textContent = 'Es gab ein Problem mit Ihrer Anfrage' - notification.className = 'bg-blue-500 text-white px-4 py-2 rounded block' - } - }, 3000) - }) - .catch((error) => { - submitButton.style.display = 'none' - notification.textContent = 'Fehler beim Senden der Nachricht.' - notification.className = 'bg-blue-500 text-white px-4 py-2 rounded block' - console.error(error) - }) -} -function fakeOut() { - submitButton.disabled = true - submitButton.innerHTML = ` - - ` - setTimeout(() => { - submitButton.style.display = 'none' - notification.innerHTML = `${currentMessages.thankyou}` - notification.className = 'bg-green-500 text-white px-4 py-2 rounded block' - }, 3000) -} -function init() { - // Event Listeners + + emailInput.addEventListener('invalid', function () { + this.setCustomValidity(messages['email']) + }) + + + // initieiere Zeitmessung zur Botprevention + var startTime = Date.now() + + // Messe ob mit der Seite agiert wird + var userInteracted = false + + function setUserInteracted() { + var timeSpent = (Date.now() - startTime) / 1000 // Zeit in Sekunden + if (timeSpent > 5) { + btn.disabled = false + } + userInteracted = true + } + setTimeout(function () { + if (userInteracted) { + btn.disabled = false + } + }, 5000) + // Eventlistener für Interaktionen - setzt userInteracted auf true bei Interaktion document.addEventListener('mousedown', setUserInteracted) document.addEventListener('touchstart', setUserInteracted) document.addEventListener('keydown', setUserInteracted) - document.addEventListener('mousemove', handleMouseMove) - form.addEventListener('submit', handleSubmit) - emailInput.addEventListener('invalid', () => { - const currentMessages = getCurrentLangMessages() - emailInput.setCustomValidity(currentMessages.email) - }) - textInputs.forEach((input) => { - input.addEventListener('invalid', () => { - const currentMessages = getCurrentLangMessages() - input.setCustomValidity(currentMessages.required) + + kontaktformular.addEventListener('submit', function (e) { + e.preventDefault() + + const form = e.target + const notification = document.getElementById('notification') + const zsrTooltip = document.getElementById('zsr-tooltip') + + // Spinner und button disabled anzeigen + + var endTime = Date.now() + var timeSpent = (endTime - startTime) / 1000 // Zeit in Sekunden + + // Setze die Werte für die Botvalidierung zum Auswerten in PHP + document.getElementById('age').value = timeSpent + document.getElementById('hobbies').value = userInteracted ? 'true' : 'false' + + btn.innerHTML = ` + + + + + + ` + + btn.disabled = true + + if (FORMDEBUG) { + console.log('userInteracted: ' + userInteracted) + console.log('timeSpent: ' + timeSpent) + console.log('hobbies: ' + document.getElementById('hobbies').value) + console.log('age: ' + document.getElementById('age').value) + console.log('verify_email(honeypot): ' + document.getElementById('verify_email').value) + } + + // Konvertiere das JSON-Objekt in einen String, um es zu senden + const formData = new FormData(form) + const formDataEncoded = new URLSearchParams(formData).toString() + const formURL = form.action + '.json' + + fetch(formURL, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', // Wichtig für die Vermeidung von CORS-Problemen + }, + body: formDataEncoded, }) - }) - log('captchaInput', captchaInput) - captchaInput?.forEach((input) => { - input.setAttribute('placeholder', getCurrentLangMessages().captcha) - }) - captchaVerifyButton?.forEach((button) => { - button.textContent = getCurrentLangMessages().captchaButton + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok') + } + return response.json() + }) + .then((data) => { + // Erfolgsnachricht anzeigen + // TODO Nachricht anpassen wenn französische Version + notification.textContent = 'Anfrage erfolgreich versendet.' + btn.className = 'submitbutton text-white mx-auto submit-after-valid-captchaaaa fadeOut' + setTimeout(() => { + btn.style.visibility = 'hidden' + btn.style.display = 'none' + notification.style.visibility = 'visible' + notification.style.display = 'block' + notification.classList.remove('fadeIn') // Remove fadeIn class + void notification.offsetWidth + notification.className = 'bg-green-500 text-white px-4 py-2 rounded block fadeIn' + }, 1000) + // setTimeout(() => notification.className = 'bg-green-500 text-white px-4 py-2 rounded hidden', 5000); // Benachrichtigung nach 5 Sekunden ausblenden + }) + .catch((error) => { + // Fehlermeldung anzeigen + notification.textContent = 'Fehler beim Senden der Nachricht.' + console.log(error) + notification.className = 'bg-red-500 text-white px-4 py-2 rounded block' + // setTimeout(() => notification.className = 'bg-red-500 text-white px-4 py-2 rounded hidden', 5000); // Benachrichtigung nach 5 Sekunden ausblenden + }) }) } - -document.addEventListener('DOMContentLoaded', function () { - init() -}) diff --git a/content/french/contact.md b/content/french/contact.md index 217bef2..798a70c 100644 --- a/content/french/contact.md +++ b/content/french/contact.md @@ -32,6 +32,10 @@ Nous vous contacterons dans les plus brefs délais.
+
+ + +
- +
@@ -54,8 +58,8 @@ Nous vous contacterons dans les plus brefs délais.
- - + +
@@ -63,15 +67,14 @@ Nous vous contacterons dans les plus brefs délais.
- +
-
-{{< captcha >}} - - -

-
+ +
+ + +
{{% /section %}} diff --git a/content/german/kontakt.md b/content/german/kontakt.md index 751f7e0..4f7bc71 100644 --- a/content/german/kontakt.md +++ b/content/german/kontakt.md @@ -32,6 +32,10 @@ Wir nehmen zeitnah Kontakt zu Ihnen auf.
+
+ + +
- +
@@ -54,11 +58,8 @@ Wir nehmen zeitnah Kontakt zu Ihnen auf.
- - -
-
- + +
@@ -66,15 +67,14 @@ Wir nehmen zeitnah Kontakt zu Ihnen auf.
- +
-
-{{< captcha >}} - - -

-
+ +
+ + +
{{% /section %}}