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
|
required
|
||||||
autocomplete="name"
|
autocomplete="name"
|
||||||
maxlength="100"
|
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"
|
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);"
|
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>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -100,9 +104,11 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
|||||||
required
|
required
|
||||||
autocomplete="email"
|
autocomplete="email"
|
||||||
maxlength="200"
|
maxlength="200"
|
||||||
|
aria-describedby="email-error"
|
||||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
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);"
|
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>
|
||||||
|
|
||||||
<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 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 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', () => {
|
window.addEventListener('load', () => {
|
||||||
if (window.grecaptcha && window.grecaptcha.ready) {
|
if (window.grecaptcha && window.grecaptcha.ready) {
|
||||||
window.grecaptcha.ready();
|
window.grecaptcha.ready();
|
||||||
@@ -169,6 +216,22 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
|||||||
status.textContent = '';
|
status.textContent = '';
|
||||||
status.style.color = 'var(--hds-fg-soft)';
|
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 {
|
try {
|
||||||
let token = '';
|
let token = '';
|
||||||
if (window.grecaptcha && window.grecaptcha.execute) {
|
if (window.grecaptcha && window.grecaptcha.execute) {
|
||||||
|
|||||||
@@ -84,9 +84,13 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
|||||||
required
|
required
|
||||||
autocomplete="name"
|
autocomplete="name"
|
||||||
maxlength="100"
|
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"
|
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);"
|
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>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -100,9 +104,11 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
|||||||
required
|
required
|
||||||
autocomplete="email"
|
autocomplete="email"
|
||||||
maxlength="200"
|
maxlength="200"
|
||||||
|
aria-describedby="email-error"
|
||||||
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
|
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);"
|
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>
|
||||||
|
|
||||||
<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 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 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', () => {
|
window.addEventListener('load', () => {
|
||||||
if (window.grecaptcha && window.grecaptcha.ready) {
|
if (window.grecaptcha && window.grecaptcha.ready) {
|
||||||
window.grecaptcha.ready();
|
window.grecaptcha.ready();
|
||||||
@@ -169,6 +216,22 @@ const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
|
|||||||
status.textContent = '';
|
status.textContent = '';
|
||||||
status.style.color = 'var(--hds-fg-soft)';
|
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 {
|
try {
|
||||||
let token = '';
|
let token = '';
|
||||||
if (window.grecaptcha && window.grecaptcha.execute) {
|
if (window.grecaptcha && window.grecaptcha.execute) {
|
||||||
|
|||||||
Reference in New Issue
Block a user