document.addEventListener('DOMContentLoaded', function () {
// Simple email regex (sufficient for validation UX)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Initialize all CF7 forms on the page
function setupForm(form) {
if (!form || form._cf7_validated) return;
form._cf7_validated = true;
// Gather fields we care about (required ones)
const inputs = Array.from(form.querySelectorAll('input[placeholder], textarea[placeholder], select[placeholder]'));
// Defensive: if any field currently equals its placeholder, clear it
inputs.forEach(f => {
if (f.value && f.getAttribute('placeholder') && f.value === f.getAttribute('placeholder')) {
f.value = '';
}
});
// Create/return an error element for a field
function getErrorEl(field) {
let el = field.parentNode.querySelector('.inline-field-error');
if (!el) {
el = document.createElement('div');
el.className = 'inline-field-error';
el.style.color = '#d04545';
el.style.fontSize = '13px';
el.style.marginTop = '6px';
el.style.display = 'none';
field.parentNode.appendChild(el);
}
return el;
}
// On focus: if value equals placeholder, clear it (prevents placeholder-as-value)
inputs.forEach(f => {
f.addEventListener('focus', function () {
if (this.getAttribute('placeholder') && this.value === this.getAttribute('placeholder')) {
this.value = '';
}
const el = getErrorEl(this);
el.style.display = 'none';
});
});
// On blur: if empty, ensure value is empty (do NOT fill placeholder into value)
inputs.forEach(f => {
f.addEventListener('blur', function () {
if (this.value.trim() === '') {
this.value = '';
}
});
});
// Ensure phone input only contains digits while typing (if exists)
const phone = form.querySelector('input[name="phone"]');
if (phone) {
phone.setAttribute('inputmode', 'numeric');
phone.addEventListener('input', function () {
const digits = this.value.replace(/\D/g, '');
if (this.value !== digits) this.value = digits;
});
}
// Validate on submit — works with CF7 (AJAX) and normal submits
form.addEventListener('submit', function (ev) {
// defensive: clear fields equal to their placeholder before validation/submission
inputs.forEach(f => {
if (f.getAttribute('placeholder') && f.value === f.getAttribute('placeholder')) f.value = '';
});
let valid = true;
// Validate required CF7 fields by checking presence of 'aria-required' or input.required or * in CF7 name?
// We'll assume the most important: fname, email, phone, area should be validated.
const fname = form.querySelector('input[name="fname"], textarea[name="fname"]');
const email = form.querySelector('input[name="email"]');
const area = form.querySelector('select[name="area"]');
const msg = form.querySelector('textarea[name="msg"]');
// helper to show error
function showErr(field, text) {
const el = getErrorEl(field);
el.textContent = text;
el.style.display = 'block';
field.classList.add('field-has-error');
valid = false;
}
// helper to clear error
function clearErr(field) {
const el = getErrorEl(field);
el.style.display = 'none';
field.classList.remove('field-has-error');
}
// Validate name
if (fname) {
if (!fname.value.trim()) showErr(fname, 'Please enter your name.');
else clearErr(fname);
}
// Validate email
if (email) {
if (!email.value.trim()) {
showErr(email, 'Please enter your email.');
} else if (!emailRegex.test(email.value.trim())) {
showErr(email, 'Please enter a valid email address.');
} else {
clearErr(email);
}
}
// Validate phone
if (phone) {
const digits = phone.value.replace(/\D/g, '');
if (!digits) {
showErr(phone, 'Please enter your phone number.');
} else if (digits.length !== 10) {
showErr(phone, 'Phone number must be 10 digits.');
} else {
clearErr(phone);
}
}
// Validate area (select)
if (area) {
const v = (area.value || '').trim();
if (!v || v === 'Practice Area') {
showErr(area, 'Please choose a practice area.');
} else {
clearErr(area);
}
}
// Message optional but clear placeholder condition
if (msg) {
if (msg.getAttribute('placeholder') && msg.value === msg.getAttribute('placeholder')) {
msg.value = '';
}
}
if (!valid) {
// block submission
ev.preventDefault();
try { ev.stopImmediatePropagation(); } catch(e) {}
// scroll to first error for UX
const firstErr = form.querySelector('.field-has-error');
if (firstErr) firstErr.scrollIntoView({behavior:'smooth', block:'center'});
return false;
}
// allow submit
return true;
}, true);
}
// initialize all existing CF7 forms
document.querySelectorAll('form.wpcf7-form').forEach(form => setupForm(form));
// CF7 may replace forms via AJAX — re-init on DOM changes
const mo = new MutationObserver(function (mutations) {
mutations.forEach(m => {
if (m.addedNodes.length) {
document.querySelectorAll('form.wpcf7-form').forEach(f => setupForm(f));
}
});
});
mo.observe(document.body, { childList: true, subtree: true });
});