PageSourceSearch

https://www.empowherto.org/assets/js/forms-inquire.js?v=08272026

js empowherto.org collected 2026-09-29 11:27:08 UTC 4,257 bytes, 124 lines download raw bytes

1(function () {
2	var form = document.getElementById('inquire-form');
3	if (!form) return;
4
5	var fields = [
6		{ id: 'firstName', name: 'first name' },
7		{ id: 'lastName',  name: 'last name'  },
8		{ id: 'email',     name: 'email', email: true },
9		{ id: 'subject',   name: 'subject' },
10		{ id: 'message',   name: 'message' }
11	];
12
13	function fieldWrap(el) {
14		return el.closest('.field') || el.parentElement;
15	}
16	function setState(input, msg) {
17		var wrap = fieldWrap(input);
18		var err  = document.getElementById('err-' + input.id);
19		if (err) err.textContent = msg || '';
20		if (msg) {
21			input.setAttribute('aria-invalid', 'true');
22			if (wrap) { wrap.classList.add('invalid'); wrap.classList.remove('valid'); }
23		} else {
24			input.removeAttribute('aria-invalid');
25			if (wrap) { wrap.classList.remove('invalid'); wrap.classList.add('valid'); }
26		}
27	}
28	function validate(input, meta) {
29		var msg = '';
30		if (input.validity.valueMissing) {
31			msg = 'Please enter your ' + meta.name + '.';
32		} else if (meta.email && input.validity.typeMismatch) {
33			msg = 'Please enter a valid email address.';
34		} else if (input.validity.tooShort) {
35			msg = 'Please enter at least ' + input.minLength + ' characters.';
36		}
37		setState(input, msg);
38		return !msg;
39	}
40	fields.forEach(function (meta) {
41		var el = document.getElementById(meta.id);
42		if (!el) return;
43		el.addEventListener('input', function () { validate(el, meta); });
44		el.addEventListener('blur',  function () { validate(el, meta); });
45	});
46
47	// --- NEW: unify location detection (matches the nav logic) ---
48	function detectLocationSlug() {
49		var path = (location.pathname || '').toLowerCase();
50		if (path.startsWith('/fort-lauderdale')) return 'fort-lauderdale';
51		if (path.startsWith('/toronto')) return 'toronto';
52
53		// Fallback: infer from hidden input if present
54		var locInput = form.querySelector('input[name="location"]');
55		var raw = (locInput && locInput.value || '').toLowerCase();
56		if (raw.includes('fort')) return 'fort-lauderdale';
57		if (raw.includes('toronto')) return 'toronto';
58
59		// Default if truly unknown
60		return 'toronto';
61	}
62
63	// Optional: keep the hidden input in sync for backend/email context
64	(function syncHiddenInput() {
65		var locInput = form.querySelector('input[name="location"]');
66		if (!locInput) return;
67		var slug = detectLocationSlug();
68		locInput.value = (slug === 'fort-lauderdale') ? 'Fort Lauderdale, Florida' : 'Toronto, Canada';
69	})();
70
71	form.addEventListener('submit', function (e) {
72		// 1) Client-side validation
73		var firstInvalid = null;
74		fields.forEach(function (meta) {
75			var el = document.getElementById(meta.id);
76			if (!el) return;
77			if (!validate(el, meta) && !firstInvalid) firstInvalid = el;
78		});
79		if (firstInvalid) {
80			e.preventDefault();
81			firstInvalid.focus({ preventScroll: false });
82			return;
83		}
84
85		// 2) Determine location from URL (primary) or hidden input (fallback)
86		var slug = detectLocationSlug(); // "toronto" | "fort-lauderdale"
87
88		var isLocal = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
89
90		// Base from action (could be "/thank-you" or "/thank-you.html" or location-specific)
91		var base = (form.getAttribute('action') || '/thank-you.html').replace(/\/$/, '');
92
93		// On localhost, force .html because static server won't apply redirects
94		var baseForEnv = isLocal
95			? (base.endsWith('.html') ? base : (base + '.html'))
96			: base;
97
98		// Append l=toronto|fort-lauderdale for location-specific copy on TY page
99		var redirectUrl = baseForEnv + (baseForEnv.includes('?') ? '&' : '?') + 'l=' + encodeURIComponent(slug);
100
101		if (isLocal) {
102			// 3) Localhost flow: POST best-effort then redirect
103			e.preventDefault();
104			var data = new FormData(form);
105			if (!data.has('form-name')) data.append('form-name', form.getAttribute('name'));
106
107			fetch('/', {
108				method: 'POST',
109				headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
110				body: new URLSearchParams(data).toString()
111			})
112			.catch(function (err) {
113				console.warn('Local POST failed:', err);
114			})
115			.finally(function () {
116				window.location.assign(redirectUrl);
117			});
118			return;
119		}
120
121		// 4) Netlify/Prod: set the action to the tagged URL and let the browser POST normally
122		form.setAttribute('action', redirectUrl);
123	});
124})();

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.