PageSourceSearch

https://www.chp.ca.gov/js/custom.min.js

js ca.gov collected 2026-09-24 06:03:15 UTC 15,064 bytes, 494 lines download raw bytes

1let retryCount = 0;
2const maxRetries = 5; // Maximum number of retries
3const retryInterval = 3000; // Retry interval in ms (3 seconds)
4
5function isFormLoaded() {
6	// Check if .EPiServerForms elements exist
7	const epiForms = document.querySelectorAll('.EPiServerForms');
8	if (epiForms.length > 0) {
9		loadCustomStyles();
10	} else {
11		if (retryCount < maxRetries) {
12			retryCount++;
13			setTimeout(isFormLoaded, retryInterval);
14		} else {
15			console.log(`No .EPiServerForms elements found after ${maxRetries * retryInterval / 1000} seconds. Stopping retry attempts.`);
16		}
17	}
18}
19
20function loadCustomStyles() {
21	document.querySelectorAll('input:not([type="radio"]):not([type="checkbox"]), select,textarea').forEach(el => {
22		el.classList.add('form-control');
23	});
24
25	document.querySelectorAll('.EPiServerForms button').forEach(el => {
26		el.classList.add('btn');
27		el.classList.add('btn-outline-secondary');
28	})
29	document.querySelectorAll('.FormDateTime__Input').forEach(el => {
30		el.classList.add('w-100');
31	})
32	document.querySelectorAll('.FormCaptcha').forEach(el => {
33		const button = el.querySelector('.FormCaptcha__Refresh');
34		const img = el.querySelector('.FormCaptcha__Image');
35
36		if (button && img) {
37			// Move the button after the image
38			img.insertAdjacentElement('afterend', button);
39			img.style.marginRight = '0.375rem';
40			img.style.marginBottom = '0.375rem';
41		}
42	})
43	document.querySelectorAll('.FormCaptcha .Form__Element__Caption').forEach(el => {
44		el.style.display = 'block';
45	})
46	document.querySelectorAll('.FormCaptcha button').forEach(el => {
47		el.setAttribute('aria-label', 'refresh captcha')
48		el.innerHTML = '<span class="ca-gov-icon-update" aria-hidden="true"></span>'
49		el.style.borderRadius = '50%';
50	})
51
52	document.querySelectorAll('.FormCaptcha input').forEach(el => {
53		el.style.verticalAlign = 'bottom';
54	})
55}
56
57// Initial check when DOM content is fully loaded
58document.addEventListener('DOMContentLoaded', function () {
59	isFormLoaded();
60});
61
62((($) => {
63	'use strict';
64	/**-----------------------------------------------------------------
65	 * UTILITY HEADER
66	 *
67	 * Note: utility-header.js does not modify objects in the DOM by adding
68	 * classes or other markup other than the following two things:
69	 *
70	 *  1. Setting aria-expanded on any drawer, and any button that has a
71	 * 	   drawer, depending upon whether the drawer is expanded or not.
72	 *
73	 * 	2. Changing the tabindex to 0 if a tabable item is
74	 * 	   focused, or -1 if not (i.e. - "roving tab index"). This feature
75	 * 	   currently disabled (ie - commented out).
76	 *
77	 * Author <Muir Adams - SymSoft Solutions>
78	 -----------------------------------------------------------------*/
79
80	function utilityHeader() {
81		// JQuery DOM objects
82		const $utilityHeader = $('.utility-header');
83		const $menuItems = $utilityHeader
84			.find('.utility-header__drawer-toggle, .settings-links a, .header-cagov-logo a');
85		const $menuItemsWithDrawers = $utilityHeader.find('.utility-header__drawer-toggle');
86		const $drawers = $('.utility-header__drawer');
87		const $drawersClose = $('.utility-header__drawer-close');
88		const elementsThatReceiveFocus = 'a, button, input, select, textarea, [tabindex="0"]';
89		const $allDrawersTabContents = $drawers.find(elementsThatReceiveFocus);
90
91		// Conditional variables (true/false)
92		const isTouch = Modernizr.touchevents;
93
94		function isScreenXS() {
95			return window.innerWidth;
96		}
97
98		function isSubMenuOpen($toggle) {
99			return $toggle.attr('aria-expanded') === 'true';
100		}
101
102		function doesItHaveADrawer($menuItem) {
103			return $menuItem.hasClass('utility-header__drawer-toggle');
104		}
105
106		function openSubMenu($toggle) {
107			const drawerId = $toggle.attr('aria-controls');
108			// const $drawer = $utilityHeader.find(`#${drawerId}`);
109			const $drawer = $drawers.filter(`#${drawerId}`);
110
111			$toggle.attr('aria-expanded', 'true');
112			$drawer.attr('aria-expanded', 'true');
113
114			// unsetTabIndex($toggle);
115			setTabIndexToDrawersFirstTabContent($toggle);
116		}
117
118		function closeSubMenu($toggle) {
119			const drawerId = $toggle.attr('aria-controls');
120			// const $drawer = $utilityHeader.find(`#${drawerId}`);
121			const $drawer = $drawers.filter(`#${drawerId}`);
122
123			$toggle.attr('aria-expanded', 'false');
124			$drawer.attr('aria-expanded', 'false');
125
126			unsetTabIndexToDrawersFirstTabContent($toggle);
127			// setTabIndex($toggle);
128		}
129
130		function closeOpenSubMenus($toggle) {
131			$menuItemsWithDrawers.each(function (index, toggle) {
132				const $toggle = $(toggle);
133
134				if (isSubMenuOpen($toggle)) closeSubMenu($toggle);
135			});
136
137			// Put the focus back on whichever toggle was sent as a parameter
138			// $toggle.focus();
139		}
140
141		function setTabIndex($menuItem) {
142			$menuItem.attr('tabindex', '0');
143			return $menuItem;
144		}
145
146		function unsetTabIndex($menuItem) {
147			$menuItem.attr('tabindex', '-1');
148			return $menuItem;
149		}
150
151		function findDrawerToggle($drawer) {
152			return $utilityHeader.find(`[aria-controls=${$drawer.attr('id')}]`);
153		}
154
155		function findDrawerTabContents($drawer) {
156			return $drawer.find('a, button, input, select, textarea, [tabindex="0"]');
157		}
158
159		function setTabIndexToDrawersFirstTabContent($toggle) {
160			const drawerId = $toggle.attr('aria-controls');
161			// const $drawer = $utilityHeader.find(`#${drawerId}`);
162			const $drawer = $drawers.filter(`#${drawerId}`);
163
164			const $drawerTabContents = findDrawerTabContents($drawer);
165
166			if ($drawerTabContents.length > 0) setTabIndex($($drawerTabContents[0])).focus();
167		}
168
169		function unsetTabIndexToDrawersFirstTabContent($toggle) {
170			const drawerId = $toggle.attr('aria-controls');
171			// const $drawer = $utilityHeader.find(`#${drawerId}`);
172			const $drawer = $drawers.filter(`#${drawerId}`);
173
174			const $drawerTabContents = findDrawerTabContents($drawer);
175
176			if ($drawerTabContents.length > 0) unsetTabIndex($drawerTabContents);
177		}
178
179		// Set tabindex of all menuItems - first item is 0, and the rest are -1 for roving tab index.
180		// $menuItems.each(function(index, menuItem) {
181		// 	const $menuItem = $(menuItem);
182
183		// 	if (index === 0) {
184		// 		setTabIndex($menuItem);
185		// 	} else {
186		// 		unsetTabIndex($menuItem);
187		// 	}
188		// });
189
190		// Set tabindex of all drawer elements to -1 for roving tab index.
191		// unsetTabIndex($allDrawersTabContents);
192
193		/**-----------------------------------------------------------------
194		 *
195		 * 	MOUSE & TOUCH EVENTS
196		 *
197		 -----------------------------------------------------------------*/
198
199		function closeMenuOnClickOutside(event) {
200			const $clickTarget = $(event.target);
201			const isClickedOutsideUtilityHeader = $clickTarget.closest('.utility-header__drawer').length === 0;
202			const isClickedOutsideUtilityHeaderButton = $clickTarget.closest('.utility-header__drawer-toggle[aria-expanded="true"]').length === 0;
203
204			if (isClickedOutsideUtilityHeader && isClickedOutsideUtilityHeaderButton) {
205				const $openMenuToggle = $menuItemsWithDrawers.filter('[aria-expanded="true"]');
206
207				// Is there a menu toggle that is expanded
208				if ($openMenuToggle.length > 0) {
209					closeSubMenu($openMenuToggle);
210
211					// If user didn't click on an element that can receive focus, then put the focus
212					// on the toggle of the menu that was just closed.
213					if (!$clickTarget.is(elementsThatReceiveFocus) &&
214						$clickTarget.closest(elementsThatReceiveFocus).length === 0) {
215
216						$openMenuToggle.focus();
217					}
218				}
219			}
220		}
221
222		// Toggle the menu when user clicks the toggle button
223		$menuItemsWithDrawers.on('click', function (event) {
224			const $toggle = $(this);
225
226			if (!isSubMenuOpen($toggle)) {
227				closeOpenSubMenus($toggle);
228				openSubMenu($toggle);
229			} else {
230				closeSubMenu($toggle);
231				$toggle.focus();
232			}
233
234			event.preventDefault();
235		});
236
237		// Close button
238		$drawersClose.on('click', function (event) {
239			const $toggle = $('.utility-header__drawer-toggle[aria-expanded="true"]');
240			closeOpenSubMenus($toggle);
241
242			// Allows time for toggle's aria-expanded to change before focusing
243			setTimeout(() => {
244				$toggle.focus();
245			}, 300);
246		});
247
248		// Toggle tabindex when user clicks on a menu item
249		// $menuItems.on('click', function(event) {
250		// 	$menuItems.each(function(index, menuItem) {
251		// 		if (menuItem !== event.target) {
252		// 			unsetTabIndex($(menuItem));
253		// 		}
254		// 	});
255		// });
256
257		// Close menu if user clicked/touched outside the menu
258		if (isTouch) {
259			// iOS scrolling fires touchstart --> touchmove --> touchend,
260			// and we need to be sure we're not registering a scroll as a click.
261			let documentClick;
262
263			$(document).on('touchstart', function () {
264				documentClick = true;
265			});
266
267			$(document).on('touchmove', function () {
268				documentClick = false;
269			});
270
271			$(document).on('click touchend', function (event) {
272				if (event.type == "click") documentClick = true;
273				if (documentClick) {
274					closeMenuOnClickOutside(event);
275				}
276			});
277		} else {
278			$(document).on('click', function (event) {
279				closeMenuOnClickOutside(event);
280			});
281		}
282
283		/**-----------------------------------------------------------------
284		 *
285		 * 	KEYBOARD EVENTS
286		 *
287		 -----------------------------------------------------------------*/
288
289		// Keycodes
290		const enterKey = 13;
291		const spaceKey = 32;
292		const escKey = 27;
293		const tabKey = 9;
294		const downArrowKey = 40;
295		const upArrowKey = 38;
296		const leftArrowKey = 37;
297		const rightArrowKey = 39;
298		const homeKey = 36;
299		const endKey = 35;
300
301		function moveFocusToFirstItem($tabItems) {
302			const $firstTabItem = $($tabItems[0]);
303
304			// Move to the first navItem
305			setTabIndex($firstTabItem).focus();
306		}
307
308		function moveFocusToLastItem($tabItems) {
309			const $lastTabItem = $($tabItems[$tabItems.length - 1]);
310
311			// Move to the last navItem
312			setTabIndex($lastTabItem).focus();
313		}
314
315		function moveFocusToNextItem($tabItems, event) {
316			$tabItems.each(function (index, tabItem) {
317
318				if (tabItem === event.target) {
319					const $tabItem = $(tabItem);
320					unsetTabIndex($tabItem);
321
322					// If it's the last navItem then...
323					if (index === $tabItems.length - 1) {
324						moveFocusToFirstItem($tabItems);
325					} else {
326						const $nextTabItem = $($tabItems[index + 1]);
327
328						// Move tabindex to the next navItem
329						setTabIndex($nextTabItem).focus();
330					}
331				}
332			});
333
334			// Prevents scrolling when down arrow key is pressed
335			event.preventDefault();
336		}
337
338		function moveFocusToPreviousItem($tabItems, event) {
339			$tabItems.each(function (index, tabItem) {
340
341				if (tabItem === event.target) {
342					const $tabItem = $(tabItem);
343					unsetTabIndex($tabItem);
344
345					// If it's the first navItem then...
346					if (index === 0) {
347						moveFocusToLastItem($tabItems);
348					} else {
349						const $prevTabItem = $($tabItems[index - 1]);
350						// Move tabindex to the previous navItem
351						setTabIndex($prevTabItem).focus();
352					}
353				}
354			});
355
356			// Prevents scrolling when down arrow key is pressed
357			event.preventDefault();
358		}
359
360		function moveFocusToNextItemThatMatchesCharacter($tabItems, event) {
361			$tabItems.each(function (index, tabItem) {
362				if (tabItem === event.target) { // Find the currently focused item
363					const $tabItem = $(tabItem);
364
365					for (let i = 1; i < $tabItems.length + 1; i++) {
366						const indexToSearch = (index + i) % $tabItems.length;
367						const $thisTabItem = $($tabItems[indexToSearch]);
368						const firstLetter = $thisTabItem.text().replace(/[^0-9a-z]/gi, '').charCodeAt(0);
369						const pressedKey = event.which;
370
371						if (pressedKey === firstLetter) {
372							unsetTabIndex($tabItem);
373							setTabIndex($thisTabItem).focus();
374							break;
375						}
376					}
377				}
378			});
379		}
380
381		// Utility Header Menu Items
382		$menuItems.on('keydown', function (event) {
383			const $thisMenuItem = $(this);
384			const pressedKey = event.which;
385
386			// Move between menu items
387			// if(!isSubMenuOpen($thisMenuItem)) {
388			// 	if (pressedKey === homeKey) {
389			// 		unsetTabIndex($thisMenuItem);
390			// 		moveFocusToFirstItem($menuItems);
391			// 		event.preventDefault();
392			// 	}
393
394			// 	if (pressedKey === endKey) {
395			// 		unsetTabIndex($thisMenuItem);
396			// 		moveFocusToLastItem($menuItems);
397			// 		event.preventDefault();
398			// 	}
399
400			// 	// Moves focus to the next item having a name that starts with the typed character
401			// 	if ((pressedKey >= 48 && pressedKey <= 57) || 	// 0 - 9
402			// 		(pressedKey >= 65 && pressedKey <= 90)) {		// a - z
403
404			// 		moveFocusToNextItemThatMatchesCharacter($menuItems, event);
405			// 	}
406
407			// 	// Move tabindex down the list
408			// 	if (pressedKey === rightArrowKey) {
409			// 		moveFocusToNextItem($menuItems, event);
410			// 	}
411
412			// 	// Move tabindex up the list
413			// 	if (pressedKey === leftArrowKey) {
414			// 		moveFocusToPreviousItem($menuItems, event);
415			// 	}
416
417			// 	if (pressedKey === downArrowKey ||
418			// 		pressedKey === upArrowKey) event.preventDefault();
419			// }
420
421			// Open and close menu items with drawers
422			if (doesItHaveADrawer($thisMenuItem)) {
423				const $toggle = $thisMenuItem;
424
425				if (pressedKey === spaceKey ||
426					pressedKey === enterKey) {
427
428					if (!isSubMenuOpen($thisMenuItem)) {
429						closeOpenSubMenus($toggle);
430						openSubMenu($toggle);
431					} else {
432						closeSubMenu($toggle);
433					}
434
435					event.preventDefault()
436				}
437
438				if (pressedKey === escKey && isSubMenuOpen($thisMenuItem)) {
439					closeSubMenu($toggle);
440					$toggle.focus();
441				}
442
443				if (pressedKey === tabKey && isSubMenuOpen($thisMenuItem)) {
444					event.preventDefault();
445				}
446			}
447		});
448
449		// Drawers
450		$drawers.on('keydown', function (event) {
451			const $thisDrawer = $(this);
452			const $thisToggle = findDrawerToggle($thisDrawer);
453			const pressedKey = event.which;
454
455			if (pressedKey === escKey) {
456				closeSubMenu($thisToggle);
457
458				// Allows time for toggle's aria-expanded to change before focusing
459				setTimeout(() => {
460					$thisToggle.focus();
461				}, 300);
462			}
463
464			if (pressedKey === tabKey) {
465				event.preventDefault();
466			}
467		});
468
469		// Drawers' tabable content
470		$allDrawersTabContents.on('keydown', function (event) {
471			const $thisContent = $(this);
472			const $thisDrawer = $thisContent.closest('.utility-header__drawer');
473			const $thisDrawerTabContent = findDrawerTabContents($thisDrawer);
474			const pressedKey = event.which;
475
476			if (pressedKey === tabKey) {
477				if (event.shiftKey) {
478					unsetTabIndex($thisContent);
479					moveFocusToPreviousItem($thisDrawerTabContent, event)
480					event.preventDefault();
481				} else {
482					unsetTabIndex($thisContent);
483					moveFocusToNextItem($thisDrawerTabContent, event)
484					event.preventDefault();
485				}
486			}
487		});
488	}
489
490	// Requires on load because Google Translate markup is loaded via JS
491	$(window).on('load', function () {
492		utilityHeader();
493	});
494})(jQuery));

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.