Contact form: name field letters-only validation, email field lowercase + format validation with error messages (ES/EN)
This commit is contained in:
@@ -84,9 +84,13 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
required
|
||||
autocomplete="name"
|
||||
maxlength="100"
|
||||
pattern="[A-Za-záéíóúüñÁÉÍÓÚÜÑçÇ\s]+"
|
||||
inputmode="text"
|
||||
aria-describedby="name-error"
|
||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
||||
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
|
||||
/>
|
||||
<div id="name-error" class="hidden text-xs mt-1" style="color: var(--color-hds-error);" aria-live="polite"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -100,9 +104,11 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
required
|
||||
autocomplete="email"
|
||||
maxlength="200"
|
||||
aria-describedby="email-error"
|
||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
||||
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
|
||||
/>
|
||||
<div id="email-error" class="hidden text-xs mt-1" style="color: var(--color-hds-error);" aria-live="polite"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -153,6 +159,47 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
const successMsg = isEn ? 'Message sent. We will reply soon.' : 'Mensaje enviado. Te respondemos pronto.';
|
||||
const errorMsg = isEn ? 'Could not send. Please try again or contact us via WhatsApp.' : 'No se pudo enviar. Probá de nuevo o contactanos por WhatsApp.';
|
||||
|
||||
const nameInput = document.getElementById('name');
|
||||
const emailInput = document.getElementById('email');
|
||||
const nameError = document.getElementById('name-error');
|
||||
const emailError = document.getElementById('email-error');
|
||||
const nameRegex = /[^a-záéíóúüñç\s]/gi;
|
||||
const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/;
|
||||
const nameErrMsg = isEn ? 'Letters and spaces only' : 'Solo letras y espacios';
|
||||
const emailErrMsg = isEn ? 'Invalid email address' : 'Dirección de correo no válida';
|
||||
|
||||
function showFieldError(input, errorEl, msg) {
|
||||
errorEl.textContent = msg;
|
||||
errorEl.classList.remove('hidden');
|
||||
input.style.borderColor = 'var(--color-hds-error)';
|
||||
}
|
||||
function clearFieldError(input, errorEl) {
|
||||
errorEl.classList.add('hidden');
|
||||
errorEl.textContent = '';
|
||||
input.style.borderColor = '';
|
||||
}
|
||||
|
||||
nameInput.addEventListener('beforeinput', (e) => {
|
||||
if (e.data && nameRegex.test(e.data)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
nameInput.addEventListener('input', () => {
|
||||
const clean = nameInput.value.replace(nameRegex, '');
|
||||
if (clean !== nameInput.value) {
|
||||
nameInput.value = clean;
|
||||
}
|
||||
});
|
||||
emailInput.addEventListener('input', () => {
|
||||
emailInput.value = emailInput.value.toLowerCase();
|
||||
});
|
||||
[nameInput, emailInput].forEach(input => {
|
||||
input.addEventListener('focus', () => {
|
||||
const err = document.getElementById(input.id + '-error');
|
||||
if (err) clearFieldError(input, err);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
if (window.grecaptcha && window.grecaptcha.ready) {
|
||||
window.grecaptcha.ready();
|
||||
@@ -169,6 +216,22 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
status.textContent = '';
|
||||
status.style.color = 'var(--hds-fg-soft)';
|
||||
|
||||
let hasError = false;
|
||||
if (nameInput.value.trim() && nameRegex.test(nameInput.value)) {
|
||||
showFieldError(nameInput, nameError, nameErrMsg);
|
||||
hasError = true;
|
||||
}
|
||||
const emailVal = emailInput.value.trim();
|
||||
if (emailVal && !emailRegex.test(emailVal)) {
|
||||
showFieldError(emailInput, emailError, emailErrMsg);
|
||||
hasError = true;
|
||||
}
|
||||
if (hasError) {
|
||||
label.textContent = originalLabel;
|
||||
submit.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let token = '';
|
||||
if (window.grecaptcha && window.grecaptcha.execute) {
|
||||
|
||||
@@ -84,9 +84,13 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
required
|
||||
autocomplete="name"
|
||||
maxlength="100"
|
||||
pattern="[A-Za-záéíóúüñÁÉÍÓÚÜÑçÇ\s]+"
|
||||
inputmode="text"
|
||||
aria-describedby="name-error"
|
||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
||||
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
|
||||
/>
|
||||
<div id="name-error" class="hidden text-xs mt-1" style="color: var(--color-hds-error);" aria-live="polite"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -100,9 +104,11 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
required
|
||||
autocomplete="email"
|
||||
maxlength="200"
|
||||
aria-describedby="email-error"
|
||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
||||
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
|
||||
/>
|
||||
<div id="email-error" class="hidden text-xs mt-1" style="color: var(--color-hds-error);" aria-live="polite"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -153,6 +159,47 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
const successMsg = isEn ? 'Message sent. We will reply soon.' : 'Mensaje enviado. Te respondemos pronto.';
|
||||
const errorMsg = isEn ? 'Could not send. Please try again or contact us via WhatsApp.' : 'No se pudo enviar. Probá de nuevo o contactanos por WhatsApp.';
|
||||
|
||||
const nameInput = document.getElementById('name');
|
||||
const emailInput = document.getElementById('email');
|
||||
const nameError = document.getElementById('name-error');
|
||||
const emailError = document.getElementById('email-error');
|
||||
const nameRegex = /[^a-záéíóúüñç\s]/gi;
|
||||
const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/;
|
||||
const nameErrMsg = isEn ? 'Letters and spaces only' : 'Solo letras y espacios';
|
||||
const emailErrMsg = isEn ? 'Invalid email address' : 'Dirección de correo no válida';
|
||||
|
||||
function showFieldError(input, errorEl, msg) {
|
||||
errorEl.textContent = msg;
|
||||
errorEl.classList.remove('hidden');
|
||||
input.style.borderColor = 'var(--color-hds-error)';
|
||||
}
|
||||
function clearFieldError(input, errorEl) {
|
||||
errorEl.classList.add('hidden');
|
||||
errorEl.textContent = '';
|
||||
input.style.borderColor = '';
|
||||
}
|
||||
|
||||
nameInput.addEventListener('beforeinput', (e) => {
|
||||
if (e.data && nameRegex.test(e.data)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
nameInput.addEventListener('input', () => {
|
||||
const clean = nameInput.value.replace(nameRegex, '');
|
||||
if (clean !== nameInput.value) {
|
||||
nameInput.value = clean;
|
||||
}
|
||||
});
|
||||
emailInput.addEventListener('input', () => {
|
||||
emailInput.value = emailInput.value.toLowerCase();
|
||||
});
|
||||
[nameInput, emailInput].forEach(input => {
|
||||
input.addEventListener('focus', () => {
|
||||
const err = document.getElementById(input.id + '-error');
|
||||
if (err) clearFieldError(input, err);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
if (window.grecaptcha && window.grecaptcha.ready) {
|
||||
window.grecaptcha.ready();
|
||||
@@ -169,6 +216,22 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
||||
status.textContent = '';
|
||||
status.style.color = 'var(--hds-fg-soft)';
|
||||
|
||||
let hasError = false;
|
||||
if (nameInput.value.trim() && nameRegex.test(nameInput.value)) {
|
||||
showFieldError(nameInput, nameError, nameErrMsg);
|
||||
hasError = true;
|
||||
}
|
||||
const emailVal = emailInput.value.trim();
|
||||
if (emailVal && !emailRegex.test(emailVal)) {
|
||||
showFieldError(emailInput, emailError, emailErrMsg);
|
||||
hasError = true;
|
||||
}
|
||||
if (hasError) {
|
||||
label.textContent = originalLabel;
|
||||
submit.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let token = '';
|
||||
if (window.grecaptcha && window.grecaptcha.execute) {
|
||||
|
||||
Reference in New Issue
Block a user