PageSourceSearch

https://www.dentalplans.com/_static/??-eJydzDEOwjAMheELYayIIWVAnMU…OwRld5JZgWmzD2TlbaThn7fbs77afJXd3HrF6O4f0k=

js dentalplans.com collected 2026-09-25 19:38:33 UTC 30,868 bytes, 862 lines download raw bytes

1function fillPACode(form) {
2	var hiddenInput = form.querySelector('input[name="pa_code"]');
3	var textInput = form.querySelector('.pacode-input');
4	if ( hiddenInput && textInput ) {
5		hiddenInput.value = 'PA' + textInput.value.replace(/\D/g, '');
6	}
7}
8
9function checkForResults(form) {
10	var hiddenInput = form.querySelector('input[name="pa_code"]');
11	if ( ! hiddenInput ) {
12		return;
13	}
14	fillPACode(form);
15	var pa_code = hiddenInput.value;
16
17	jQuery.ajax({
18		method: "GET",
19		url: `${window.DP_REST_API.v1}/dpapi/proxy/dentist/v1/dentalsearch/dentist/${pa_code}`,
20		success: async function (data) {
21			if ( data.dentists.length === 0 ) {
22				doFormError(form);
23			} else {
24				if ( data.dentists && data.dentists[0].dentistAddress && data.dentists[0].dentistAddress.zip ) {
25					var pa_code_zip = data.dentists[0].dentistAddress.zip;
26					if ( typeof window.overrideLocation === 'function' ) {
27						await window.overrideLocation(pa_code_zip);
28					}
29				}
30				form.submit();
31			}
32		},
33		error: function (data) {
34			console.error("pa code search Error: " + pa_code, data);
35		},
36	});
37}
38
39function doFormError(form) {
40	var textInput = form.querySelector('.pacode-input');
41	if ( textInput ) {
42		textInput.classList.add('error');
43	}
44	form.querySelectorAll('.error-message').forEach(function (el) {
45		el.classList.remove('hidden');
46	});
47}
48
49function clearFormError(form) {
50	var textInput = form.querySelector('.pacode-input');
51	if ( textInput ) {
52		textInput.classList.remove('error');
53	}
54	form.querySelectorAll('.error-message').forEach(function (el) {
55		el.classList.add('hidden');
56	});
57}
58
59function disableFormSubmit(form, disable) {
60	var submitBtn = form.querySelector('[type="submit"]');
61	if ( submitBtn ) {
62		submitBtn.disabled = disable;
63	}
64}
65
66function isFormSubmitDisabled(form) {
67	var submitBtn = form.querySelector('[type="submit"]');
68	return submitBtn ? submitBtn.disabled : true;
69}
70
71document.addEventListener("DOMContentLoaded", function () {
72	var forms = document.querySelectorAll('.dentist-pa-code-form');
73
74	forms.forEach(function (form) {
75		var input = form.querySelector('.pacode-input');
76		if ( ! input ) {
77			return;
78		}
79
80		input.addEventListener('input', function (event) {
81			input.value = event.target.value.replace(/\D/g, '');
82			clearFormError(form);
83			disableFormSubmit(form, input.value.length < 1);
84		});
85
86		input.addEventListener('paste', function (event) {
87			event.preventDefault();
88			input.value = (event.clipboardData || window.clipboardData).getData("text").replace(/\D/g, '');
89			clearFormError(form);
90			disableFormSubmit(form, input.value.length < 1);
91		});
92	});
93
94	document.body.addEventListener("submit", function (event) {
95		var form = event.target;
96		if ( ! form || ! form.classList || ! form.classList.contains('dentist-pa-code-form') ) {
97			return;
98		}
99
100		event.preventDefault();
101		if ( ! isFormSubmitDisabled(form) ) {
102			fillPACode(form);
103			checkForResults(form);
104		}
105	});
106});
107;
108
109document.addEventListener('DOMContentLoaded', function () {
110
111	/////////////////////////////////////////////////////////////////////////////////////////////
112	// Define elements.
113
114	let searchFormBlock = null;
115
116	let overlay = null;
117
118	let closeButton = null;
119
120	let searchForm = null;
121
122	let filterByWrapper            = null;
123	let filterByToggleButton       = null;
124	let filterByOptionsWrapper     = null;
125	let filterByOptionsInputs      = null;
126	let filterByOptionsInputsArray = null;
127
128	let searchInput = null;
129
130	let autosuggestWrapper        = null;
131	let autosuggestContent        = null;
132
133	let bootstrapFocusTrapModals = [];
134
135	/////////////////////////////////////////////////////////////////////////////////////////////
136	// Define state variables.
137
138	let autosuggestAbortController = null;
139	let filterByOptionPreviousValue = null;
140
141	/////////////////////////////////////////////////////////////////////////////////////////////
142	// Define helpers and handlers.
143
144	function renderMobileHeaderBrand( container ) {
145		const brand = window.dp_search_form && window.dp_search_form.mobile_header_brand;
146		if ( ! container || ! brand || ! brand.home_url ) {
147			return;
148		}
149		const link = document.createElement( 'a' );
150		link.href = brand.home_url;
151		if ( brand.logo && brand.logo.url ) {
152			link.className = 'site-home-link';
153			const img = document.createElement( 'img' );
154			img.src = brand.logo.url;
155			if ( brand.logo.srcset ) {
156				img.setAttribute( 'srcset', brand.logo.srcset );
157			}
158			if ( brand.logo.sizes ) {
159				img.setAttribute( 'sizes', brand.logo.sizes );
160			}
161			img.alt = typeof brand.logo.alt === 'string' ? brand.logo.alt : '';
162			img.decoding = 'async';
163			link.appendChild( img );
164			container.appendChild( link );
165		} else if ( brand.site_title ) {
166			link.textContent = brand.site_title;
167			container.appendChild( link );
168		}
169	}
170
171	function init() {
172
173		if ( ! searchFormBlock ) {
174			searchFormBlock = document.createElement('div');
175			searchFormBlock.id = 'dp-site-search-form';
176			searchFormBlock.classList.add('dp-block-search-form');
177
178			searchFormBlock.innerHTML = `
179				<div class="dp-block-search-form__overlay"></div>
180				<div class="dp-block-search-form__inner">
181					<div class="dp-block-search-form__mobile-header">
182						<button type="button" class="dp-block-search-form__close" aria-label="Close search">
183							<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
184								<path d="M4 4L20 20" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
185								<path d="M4 20L20 4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
186							</svg>
187						</button>
188						<div class="dp-block-search-form__mobile-logo"></div>
189					</div>
190					<form name="dp-search-form" method="get" action="${window.dp_search_form.form_action}">
191						<div class="dp-search-form-main">
192							<div class="dp-search-form__filter-by-dropdown">
193								<button type="button" class="filter-by-dropdown__toggle" aria-controls="dp-site-search-form__category-options">
194									<span class="filter-by-dropdown__toggle-label">Category:</span>
195									<span class="filter-by-dropdown__toggle-value">All</span>
196									<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none">
197										<path d="M12.3135 1.65674L6.65662 7.31359L0.999769 1.65674" stroke="#2445EA" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
198									</svg>
199								</button>
200								<div id="dp-site-search-form__category-options" class="filter-by-dropdown__options visually-hidden">
201									<label>
202										<input type="radio" name="facet" value="all" class="visually-hidden" checked />
203										All
204									</label>
205									${window.dp_search_form.search_filter_options.map(option => {
206										return `
207											<label>
208												<input type="radio" name="facet" value="${option.value}" class="visually-hidden" />
209												${option.label}
210											</label>
211										`;
212									}).join('')}
213								</div>
214							</div>
215							<input name="s" type="search" placeholder="What are you looking for..." autocomplete="off" required />
216							<input type="reset" value="Clear" class="clear-search-input" />
217							<button type="submit" class="submit-search-input">
218								<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25" fill="none">
219									<title>Search</title>
220									<circle cx="9.6" cy="9.6" r="8.6" stroke="currentColor" stroke-width="2"/>
221									<path d="M16.8 16.7998L24 23.9998" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
222								</svg>
223							</button>
224						</div>
225						<div class="dp-search-form-autosuggest">
226							<div class="dp-search-form-autosuggest__content"></div>
227							<p class="default-message">Need to find a dentist? Look <a href="${window.dp_search_form.dentist_href}">here &rarr;</a></p>
228						</div>
229					</form>
230				</div>
231			`;
232
233			document.body.appendChild(searchFormBlock);
234
235			const mobileLogoEl = searchFormBlock.querySelector( '.dp-block-search-form__mobile-logo' );
236			renderMobileHeaderBrand( mobileLogoEl );
237		}
238
239		overlay = searchFormBlock.querySelector('.dp-block-search-form__overlay');
240
241		closeButton = searchFormBlock.querySelector('.dp-block-search-form__close');
242
243		searchForm = searchFormBlock.querySelector('form[name="dp-search-form"]');
244
245		filterByWrapper            = searchFormBlock.querySelector('.dp-search-form__filter-by-dropdown');
246		filterByToggleButton       = filterByWrapper.querySelector('.filter-by-dropdown__toggle');
247		filterByOptionsWrapper     = filterByWrapper.querySelector('.filter-by-dropdown__options');
248		filterByOptionsInputs      = filterByOptionsWrapper.querySelectorAll('input[name="facet"]');
249		filterByOptionsInputsArray = Array.from(filterByOptionsInputs);
250
251		searchInput = searchFormBlock.querySelector('input[name="s"]');
252
253		autosuggestWrapper = searchFormBlock.querySelector('.dp-search-form-autosuggest');
254		autosuggestContent = autosuggestWrapper.querySelector('.dp-search-form-autosuggest__content');
255
256		bootstrapFocusTrapModals = [];
257
258		// Define state variables.
259
260		autosuggestAbortController = null;
261		filterByOptionPreviousValue = getFilterByOptionCurrentValue();
262
263		// Attach event listeners.
264
265		overlay.addEventListener('click', event => {
266			if ( event.target === event.currentTarget ) {
267				// Only toggle visibility if no child element was targeted.
268				toggleSearchFormVisibility();
269			}
270		});
271
272		if ( closeButton ) {
273			closeButton.addEventListener('click', () => {
274				if ( document.body.classList.contains('dp-block-search-form--open') ) {
275					toggleSearchFormVisibility();
276				}
277			});
278		}
279
280		filterByToggleButton.addEventListener('click', toggleFilterByOptionsVisibility);
281
282		searchForm.addEventListener('reset', event => {
283			setTimeout(
284				() => {
285					// This changes the selected category, so remember the value after reset.
286					// It's now the new "previous" option.
287					filterByOptionPreviousValue = getFilterByOptionCurrentValue();
288					// Now handle search input change.
289					handleSearchInputChange(event);
290				},
291				0 // Fire right after this event to ensure the form values have already been reset.
292			);
293		});
294
295		searchForm.addEventListener('submit', event => {
296			const query               = searchInput.value.trim();
297			const [ , filterByLabel ] = getFilterByOptionCurrentValue();
298			dataLayerPush({
299				event: ( event?.submitter?.classList?.contains('submit-more-results') ? "more_search_success" : "term_search_success" ),
300				search_term: query,
301				search_category: filterByLabel,
302			});
303		});
304
305		filterByOptionsInputs.forEach(input => {
306			input.addEventListener('change', handleSearchInputChange);
307		});
308
309		searchInput.addEventListener('input', handleSearchInputChange);
310	}
311
312	function dataLayerPush(data) {
313		window.dataLayer = window.dataLayer || [];
314		window.dataLayer.push(data);
315		window.console.log('pushed to dataLayer ->', JSON.stringify(data, null, 4));
316	}
317
318	function toggleSearchFormVisibility() {
319		if ( !! document.body.classList.toggle('dp-block-search-form--open') ) {
320			// Prevent Bootstrap's modal focus trapping from preventing focus.
321			bootstrapFocusTrapModals.length = 0;
322			bsModals = document.querySelectorAll('.modal.show[aria-modal="true"][role="dialog"]');
323			if ( bsModals ) {
324				bsModals.forEach(modal => {
325					const bsModalInstance = bootstrap.Modal.getInstance(modal);
326					if ( bsModalInstance?._focustrap?._isActive ) {
327						// Only capture modals with focus trapping enabled.
328						bootstrapFocusTrapModals.push(bsModalInstance);
329						bsModalInstance._focustrap.deactivate(); // See https://github.com/twbs/bootstrap/blob/v5.2.3/js/src/modal.js#L70
330					}
331				});
332			}
333			// Auto-focus the search input field.
334			searchInput.focus();
335			// Send analytics event.
336			dataLayerPush({
337				event: "search_overlay_opened",
338			});
339		} else {
340			// Re-activate Bootstrap modal focus trapping.
341			if ( bootstrapFocusTrapModals ) {
342				bootstrapFocusTrapModals.forEach(modalInstance => {
343					modalInstance._focustrap.activate();
344				})
345			}
346		}
347	}
348
349	function toggleFilterByOptionsVisibility() {
350		filterByOptionsWrapper.classList.toggle('visually-hidden');
351	}
352
353	async function handleSearchInputChange(event) {
354
355		// Ensure current filter option is set.
356		setStateFilterBy(getFilterByOptionCurrent());
357
358		if (filterByOptionsInputsArray.includes(event.target)) {
359			// Change event from filter category input selection.
360			const [ , prevCategoryLabel ] = filterByOptionPreviousValue;
361			filterByOptionPreviousValue = getFilterByOptionCurrentValue();
362			const [ , newCategoryLabel ] = filterByOptionPreviousValue;
363			dataLayerPush({
364				event: "search_category_interest",
365				previous_category: prevCategoryLabel,
366				new_category: newCategoryLabel,
367			});
368		}
369
370		// Ensure the filter options are hidden while user searches.
371		filterByOptionsWrapper.classList.add('visually-hidden');
372
373		// Act based on input value.
374		if ( searchInput?.value ) {
375
376			searchFormBlock.classList.add('has-query-input');
377
378			const query                            = searchInput.value.trim();
379			const [ filterByValue, filterByLabel ] = getFilterByOptionCurrentValue();
380			const limit                            = 4;
381			const autosuggestResults               = await fetchAutosuggestResults(query, filterByValue, limit);
382			if (
383				'success' === autosuggestResults?.status &&
384				autosuggestResults?.data?.topSearchResults?.length
385			) {
386				// Found search results.
387
388				const topSearchResultsListItems = autosuggestResults.data.topSearchResults.map(
389					post => {
390						if ( ! post?.search_result_item_html ) {
391							return '';
392						}
393						return `<li>${post.search_result_item_html}</li>`;
394					}
395				);
396
397				let maybeMoreButton = ``;
398				if ( autosuggestResults?.data?.totalSearchResultsCount > limit ) {
399					maybeMoreButton = `<button type="submit" class="submit-more-results">More...</button>`;
400				}
401
402				autosuggestContent.innerHTML = `
403					<div class="top-search-results">
404						<p class="heading">Top Results For <strong>${query}</strong> in <strong>${filterByLabel}</strong></p>
405						<ul>
406							${topSearchResultsListItems.join("\n")}
407						</ul>
408						${maybeMoreButton}
409					</div>
410				`;
411
412				autosuggestContent.querySelectorAll('.top-search-results li a').forEach(el => {
413					el.addEventListener('click', () => {
414						const itemTitle = el.querySelector('.search-result-item__title');
415						dataLayerPush({
416							event: "suggested_search_success",
417							search_term: query,
418							search_category: filterByLabel,
419							suggested_name: ( itemTitle?.innerText ) ? itemTitle.innerText.trim() : el.innerText.trim(),
420							suggested_url: el.href,
421						});
422					});
423				});
424			} else {
425				// No search results retrieved.
426
427				const viewHoursTooltipHTML = `
428					<strong>Mon&ndash;Fri:</strong> 8:30am &ndash; 9pm<br />
429					<strong>Sat:</strong> 9am &ndash; 6pm<br />
430					<strong>Sun:</strong> Closed<br />
431					<small>All times are in EST</small>
432				`;
433
434				autosuggestContent.innerHTML = `
435					<div class="top-search-results no-results">
436						<p class="heading">We didn't find anything that matches &ldquo;${query}&rdquo;.</p>
437						<div class="no-results__cta">
438							<div class="cta__see-faq">
439								<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none">
440									<path d="M2.55996 35.9501C2.99996 33.8101 3.54996 31.6801 4.50996 29.3401C2.92996 26.3301 1.51996 23.1101 1.39996 19.7101C1.17996 13.2801 5.74996 7.46005 11.33 4.25005C13.06 3.26005 14.9 2.45005 16.84 1.98005C23.55 0.340052 31.1 3.16005 35.17 8.74005C39.24 14.3201 39.64 22.3101 36.21 28.3101C32.79 34.3101 25.77 38.0301 18.88 37.5801C15.87 37.3801 12.84 36.4101 10.76 34.2701C8.02996 35.
4400101 5.29996 35.7501 2.54996 35.9501H2.55996Z" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
441									<path d="M15.3096 15.6403C15.4596 13.8203 16.5596 12.0803 18.1896 11.2503C19.8196 10.4203 21.9296 10.5903 23.3596 11.7303C24.7896 12.8703 25.3896 14.9703 24.7096 16.6703C24.2796 17.7403 23.4196 18.5803 22.5096 19.3003C21.7396 19.9103 20.8996 20.4803 20.3496 21.3003C19.7996 22.1203 19.6496 23.3003 20.2796 24.0503" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
442									<path d="M20.3203 28.6702L20.3703 29.1902C20.5403 29.2902 20.8003 29.2202 20.8903 29.0402C20.9803 28.8602 20.8903 28.6102 20.3203 28.6702Z" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
443									<path d="M2.55996 35.9501C2.99996 33.8101 3.54996 31.6801 4.50996 29.3401C2.92996 26.3301 1.51996 23.1101 1.39996 19.7101C1.17996 13.2801 5.74996 7.46005 11.33 4.25005C13.06 3.26005 14.9 2.45005 16.84 1.98005C23.55 0.340052 31.1 3.16005 35.17 8.74005C39.24 14.3201 39.64 22.3101 36.21 28.3101C32.79 34.3101 25.77 38.0301 18.88 37.5801C15.87 37.3801 12.84 36.4101 10.76 34.2701C8.02996 35.
4430101 5.29996 35.7501 2.54996 35.9501H2.55996Z" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
444									<path d="M15.3096 15.6403C15.4596 13.8203 16.5596 12.0803 18.1896 11.2503C19.8196 10.4203 21.9296 10.5903 23.3596 11.7303C24.7896 12.8703 25.3896 14.9703 24.7096 16.6703C24.2796 17.7403 23.4196 18.5803 22.5096 19.3003C21.7396 19.9103 20.8996 20.4803 20.3496 21.3003C19.7996 22.1203 19.6496 23.3003 20.2796 24.0503" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
445									<path d="M20.3203 28.6702L20.3703 29.1902C20.5403 29.2902 20.8003 29.2202 20.8903 29.0402C20.9803 28.8602 20.8903 28.6102 20.3203 28.6702Z" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
446								</svg>
447								<p>Take a look at our frequently asked&nbsp;questions</p>
448								<a href="${dp_search_form.faq_href}" class="dp-button dp-button--tertiary">Go to FAQ</a>
449							</div>
450							<div class="cta__call-us">
451								<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none">
452									<g clip-path="url(#clip0_1_828)">
453									<path d="M20.0001 38.8801C30.4273 38.8801 38.8801 30.4273 38.8801 20.0001C38.8801 9.57298 30.4273 1.12012 20.0001 1.12012C9.57298 1.12012 1.12012 9.57298 1.12012 20.0001C1.12012 30.4273 9.57298 38.8801 20.0001 38.8801Z" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
454									<path d="M9.29004 29.2897C10.09 25.6597 12.76 22.4897 16.21 21.0897C17.93 20.3897 19.8 20.1097 21.57 19.5297C23.34 18.9497 25.1 17.9897 26.01 16.3597C27.04 14.4997 26.68 12.0197 25.3 10.3897C23.92 8.7597 21.67 7.9897 19.55 8.2097C18.48 8.3197 17.42 8.6797 16.57 9.3397C14.9 10.6497 14.31 13.0597 14.93 15.0897C15.55 17.1197 17.22 18.7197 19.18 19.5397C20.93 20.2697 22.89 20.4197 24.64 21.1497C27.97 22.5297 30.25 26.1397 30.06 29.7397" stroke="#2445EA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
455									</g>
456									<defs>
457									<clipPath id="clip0_1_828">
458										<rect width="40" height="40" fill="white"/>
459									</clipPath>
460									</defs>
461								</svg>
462								<p>Give us a call, we are here&nbsp;to&nbsp;help</p>
463								<button type="button" class="call-us__view-hours" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="top" data-bs-fallbackPlacements="['top', 'bottom', 'left', 'right']" data-bs-title="${viewHoursTooltipHTML}">View Hours</button>
464								<a href="${dp_search_form.dp_phone_href}" class="dp-button dp-phone dp-phone-without-country-code">${dp_search_form.dp_phone_label}</a>
465							</div>
466						</div>
467					</div>
468				`;
469
470				// Enable the Bootstrap tooltip.
471				autosuggestContent.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
472					return new bootstrap.Tooltip(el);
473				});
474			}
475
476			// Retain query params on dynamically added hyperlinks.
477			dpSetPhoneNumber(autosuggestContent);
478		} else {
479			// No search input value.
480			searchFormBlock.classList.remove('has-query-input');
481			autosuggestContent.innerHTML = '';
482		}
483	}
484
485	function setStateFilterBy(inputEl) {
486		let buttonLabel = 'All';
487		if ( inputEl?.labels?.length ) {
488			buttonLabel = inputEl.labels[0].innerText;
489		}
490		filterByToggleButton.querySelector('span.filter-by-dropdown__toggle-value').innerText = buttonLabel;
491		filterByOptionsWrapper.classList.add('visually-hidden');
492	}
493
494	function getFilterByOptionCurrent() {
495		for ( const input of filterByOptionsInputs ) {
496			if ( input.checked ) {
497				return input;
498			}
499		}
500		return null;
501	}
502
503	function getFilterByOptionCurrentValue() {
504		const inputEl = getFilterByOptionCurrent();
505
506		let value = 'all';
507		if ( inputEl?.value ) {
508			value = inputEl.value;
509		}
510
511		let label = 'All';
512		if ( inputEl?.labels?.[0]?.innerText ) {
513			label = inputEl.labels[0].innerText;
514		}
515
516		return [ value, label ];
517	}
518
519	async function fetchAutosuggestResults(query, filterBy, limit) {
520
521		if ( ! query ) {
522			return null; // Don't fetch for blank queries.
523		}
524
525		// Abort any existing request.
526		if ( autosuggestAbortController ) {
527			autosuggestAbortController.abort();
528		}
529
530		// Create a new AbortController for the current request.
531		autosuggestAbortController = new AbortController();
532
533		try {
534
535			const response = await fetch(
536				`${window.DP_REST_API.v1}/search/autosuggest/?s=${query}&facet=${filterBy}&limit=${limit}`,
537				{
538					"method": 'GET',
539					"credentials": 'same-origin',
540					"signal": autosuggestAbortController.signal
541				}
542			);
543
544			if ( ! response.ok ) {
545				throw new Error('Network response was not ok');
546			}
547
548			const data = await response.json();
549			return data;
550		} catch ( error ) {
551			if ( 'AbortError' !== error.name ) {
552				window.console.error('Failed to fetch search autosuggestion results:', error);
553			}
554		}
555
556		return null; // The data couldn't be fetched.
557	}
558
559	/////////////////////////////////////////////////////////////////////////////////////////////
560	// Attach entry point event listeners.
561
562	document.querySelectorAll('.search-link').forEach(link => {
563		link.addEventListener('click', event => {
564			event.preventDefault();
564 // Do not navigate href.
565
566			// Initialize the search form if it's not already initialized.
567			if ( ! searchFormBlock ) {
568				init();
569			}
570
571			// Toggle the search form visibility.
572			toggleSearchFormVisibility();
573		});
574	});
575}, { once: true } );
576;
577(function () {
578
579	let prevAccordionWindowLocationHash = ( window.location.hash.startsWith('#faq-') ) ? window.location.hash : '';
580
581	function openAccordionForWindowLocationHash() {
582		if ( window.location.hash.startsWith('#faq-') ) {
583
584			document.querySelectorAll(`.»active[href*="${prevAccordionWindowLocationHash}"]`).forEach(el => { el.classList.remove('»active'); });
585
586			const targetAccordion = document.querySelector(`.wp-block-details[id="${window.location.hash.substring(1)}"]`);
587			targetAccordion.parentElement.querySelectorAll('.wp-block-details[open]').forEach(el => { el.open = false; });
588			targetAccordion.open = true;
589
590			if ( 'function' === typeof targetAccordion?.scrollIntoViewIfNeeded ) {
591				targetAccordion.scrollIntoViewIfNeeded({ "behavior": "smooth" });
592			} else if ( 'function' === typeof targetAccordion?.scrollIntoView ) {
593				targetAccordion.scrollIntoView({ "behavior": "smooth" });
594			}
595
596			document.querySelectorAll(`[href*="${window.location.hash}"]`).forEach(el => { el.classList.add('»active'); });
597
598			prevAccordionWindowLocationHash = window.location.hash;
599		}
600	}
601
602	document.addEventListener('DOMContentLoaded', openAccordionForWindowLocationHash);
603	window.addEventListener('hashchange', openAccordionForWindowLocationHash);
604})();
605;
606maxProcCount = 10;
607minAdultCount = 1;
608maxAdultCount = 2;
609maxChildCount = 3;
610
611function dpSynchSavingsCalcDrawers() {
612	if (jQuery('input[name="plan"]:checked').val() === "family") {
613		jQuery("#savings-calculator-form").removeClass("»list-one--hidden");
614	} else {
615		jQuery("#savings-calculator-form").addClass("»list-one--hidden");
616		jQuery('input[name="adultCount"]').val(1);
617		jQuery('input[name="childrenCount"]').val(0);
618	}
619
620	$procInputs = jQuery('input[name^="prc"]');
621	if (jQuery('input[name="procedures"]:checked').val() === "yes") {
622		$procInputs.prop("disabled", false);
623		jQuery("#savings-calculator-form").removeClass("»list-two--hidden");
624	} else {
625		$procInputs.prop("disabled", true);
626		jQuery("#savings-calculator-form").addClass("»list-two--hidden");
627	}
628}
629
630jQuery(document).ready(function () {
631	dpSynchSavingsCalcDrawers();
632
633	jQuery('input[name="procedures"], input[name="plan"]').change(function (e) {
634		dpSynchSavingsCalcDrawers();
635	});
636
637	//assert email is not disabled in the case of back button
638	jQuery('input[name="email"]', "#savings-calculator-form").prop('disabled', false);
639
640	jQuery('input[name="email"]', "#savings-calculator-form").change(function (e) {
641		let email = jQuery(this).val();
642		email = email.trim();
643		jQuery('input[name="eid"]', "#savings-calculator-form").val(btoa(email));
644
645	});
646
647	//deal with +/- clicks
648	jQuery(".savings-calculator-procedures--list").on(
649		"click",
650		".savings-calculator-item--minus, .savings-calculator-item--plus",
651		function (e) {
652			e.preventDefault();
653			let $button = jQuery(this);
654			let $input = $button.parents(".savings-calculator-item").find("input");
655			//mas o menos
656			let val = parseInt($input.val());
657
658			//case procs
659			if ($button.hasClass("savings-calculator-item--plus")) {
660				let $form = jQuery($button).parents("form");
661				let procTotal = 0;
662				$form
663					.find(
664						".savings-calculator-procedures--list .savings-calculator-item--input"
665					)
666					.each(function (idx, el) {
667						procTotal += parseInt(jQuery(this).val());
668					});
669				if (procTotal >= maxProcCount) {
670					alert(
671						"Please limit selection to " + maxProcCount + " or less procedures"
672					);
673				} else {
674					$input.val(Math.max(val + 1, 0));
675				}
676			} else {
677				$input.val(Math.max(val - 1, 0));
678			}
679		}
680	);
681
682	//deal with +/- clicks
683	jQuery(".savings-calculator-members").on(
684		"click",
685		" .savings-calculator-item--minus, .savings-calculator-item--plus",
686		function (e) {
687			e.preventDefault();
688			let $button = jQuery(this);
689			let $input = $button.parents(".savings-calculator-item").find("input");
690			//mas o menos
691			let val = parseInt($input.val());
692
693			//case procs
694			if ($button.hasClass("savings-calculator-item--plus")) {
695				if ($input.attr("name") == "adultCount" && val >= maxAdultCount) {
696					alert(
697						"Please limit adults selection to " + maxAdultCount + " or less "
698					);
699				} else if (
700					$input.attr("name") == "childrenCount" &&
701					val >= maxChildCount
702				) {
703					alert(
704						"Please limit children selection to " + maxChildCount + " or less "
705					);
706				} else {
707					$input.val(Math.max(val + 1, 0));
708				}
709			} else {
710				if ($input.attr("name") == "adultCount" && val <= minAdultCount) {
711					alert(
712						"Please limit adults selection to " + minAdultCount + " or more "
713					);
714				} else {
715					$input.val(Math.max(val - 1, 0));
716				}
717			}
718		}
719	);
720
721	jQuery("input", "#savings-calculator-form").on("input", function () {
722		var $this = jQuery(this);
723		var value = $this.val();
724
725		if (value) {
726			$this.addClass("»dirty");
727			$this.removeClass("»error");
728		} else {
729			$this.removeClass("»dirty");
730		}
731	});
732
733	jQuery(".savings-calculator .dp-input--input").each(function (i, e) {
734		var $this = jQuery(e);
735		$this.addClass("»dirty");
736		$this.removeClass("»error");
737	});
738	setTimeout(() => {
739		jQuery(".savings-calculator .dp-input--input").each(function (i, e) {
740			var $this = jQuery(e);
741			var value = $this.val();
742			if (value) {
743				$this.addClass("»dirty");
744				$this.removeClass("»error");
745			} else {
746				$this.removeClass("»dirty");
747			}
748		});
749	}, 100);
750
751	// Multistep form: Next/Back navigation (only when multistep-form DOM is present).
752	if (jQuery("#sc-question2").length) {
753		jQuery("#btn-next-one").on("click", function () {
754			jQuery("#sc-question2").show();
755			jQuery(".step2").show();
756			jQuery("#sc-question1").hide();
757			jQuery(".step1").hide();
758		});
759		jQuery("#btn-next-two").on("click", function () {
760			jQuery("#sc-question3").show();
761			jQuery(".step3").show();
762			jQuery("#sc-question2").hide();
763			jQuery(".step2").hide();
764		});
765		jQuery("#btn-back-two").on("click", function () {
766			jQuery("#sc-question1").show();
767			jQuery(".step1").show();
768			jQuery("#sc-question2").hide();
769			jQuery(".step2").hide();
770		});
771		jQuery("#btn-back-three").on("click", function () {
772			jQuery("#sc-question2").show();
773			jQuery(".step2").show();
774			jQuery("#sc-question3").hide();
775			jQuery(".step3").hide();
776		});
777	}
778});
779
780// Add event listener to the body element's submit event
781document.body.addEventListener("submit", async function (event) {
782	var form = event.target;
783	if (!form.matches(".savings-calculator--form")) {
784		return; // ignore submits from other forms
785	}
786
787	// Prevent the default action of the form
788	event.preventDefault();
789
790	if (DP_VISITORID) {
791		form.querySelectorAll("[name=visitorId]").forEach(function (input) {
792			input.value = DP_VISITORID;
793		});
794	}
795
796	if (DP_AFFID) {
797		form.querySelectorAll("[name=affid]").forEach(function (input) {
798			input.value = DP_AFFID;
799		});
800	}
801
802	if (dpIsPPC()) {
803		form.querySelectorAll("[name=includeTopPlan]").forEach(function (input) {
804			input.value = 'true';
805		});
806	}
807
808	//disable input so we don't see in Query Params
809	const emailInput = form.querySelector("[name=email]");
810	if ( emailInput ) {
811		emailInput.disabled = true;
812	}
813
814	//disable inputs to keep URL clean
815	const procedureInputs = form.querySelectorAll(".savings-calculator-procedures--list input");
816	procedureInputs.forEach(function (input) {
817		if (parseInt(input.value) === 0) {
818			input.disabled = true;
819		}
820	});
821
822	window.dataLayer = window.dataLayer || [];
823	// prevent multiple Calculate GTM events
824	if (!dataLayer.find(function (obj) { return obj.event === "Calculate" })) {
825		window.dataLayer.push({
826			'event': 'Calculate',
827			'category': 'Button'
828		});
829	}
830
831	//detect input changes
832	var changedInputs = form.querySelectorAll("input.changed");
833	if (changedInputs.length) {
834		//build query for radar
835		var radarQuery = form.querySelector("input.radar-location").value;
836		// they changed the input, update the location
837		await overrideLocation(radarQuery, form);
838	}
839
840	// submit the form if input validation passed.
841	if (form.checkValidity()) {
842		tidyAndSubmit(form);
843	} else {
844		// re-enable inputs for user to edit their submission.
845		emailInput.disabled = false;
846		procedureInputs.forEach(function (input) {
847			if (parseInt(input.value) === 0) {
848				input.disabled = false;
849			}
850		});
851	}
852});
853
854// reset savings calculator form on back button cache
855window.addEventListener('pageshow', (event) => {
856	if (event.persisted || performance.getEntriesByType("navigation")[0].type === 'back_forward') {
857		jQuery('input[name="plan"][value="individual"]').click();
858		jQuery('input[name="procedures"][value="no"]').click();
859		jQuery('#savings-calculator-form .savings-calculator-procedures--list input[type="checkbox"]').prop('checked', false);
860	}
861});
862;

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.