PageSourceSearch

https://accreditedgemologists.org/wp-content/plugins/frames-plugin…/Widgets/modal/js/modal.js?ver=1786888814

js accreditedgemologists.org collected 2026-09-24 22:38:02 UTC 43,864 bytes, 1,506 lines download raw bytes

1/* eslint-disable */ //TODO: be aware of unused vars
2function modal_script() {
3
4	const modals = document.querySelectorAll('.fr-modal');
5	const focusableElements = 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
6	const higherIndexTriggerClass = 'fr-modal__trigger--higher-index';
7	let closeSelector;
8	let fadeTime;
9	let isStartModalVideo;
10	let isInQueryBuilder = false;
11	let youtubePlayers = {};
12	let youtubeApiInitiated = false;
13	// TODO @Hakira-Shymuy remove flag after feature finished and tested.
14	// let flag_enable_modal_exit_intent =
15	// 	window.hasOwnProperty('frames_modal_obj') && window.frames_modal_obj.hasOwnProperty('flag_enable_modal_exit_intent') ?
16	// 	window.frames_modal_obj.flag_enable_modal_exit_intent : false
17	// 	//console.log('enable trigger page load', flag_enable_modal_exit_intent)
18	// let flag_modal_slider_compatibility = window.hasOwnProperty('frames_modal_slider_obj') && window.frames_modal_slider_obj.hasOwnProperty('flag_modal_slider_compatibility') ? window.frames_modal_slider_obj.flag_modal_slider_compatibility : false
19	let flag_enable_modal_exit_intent = window.frames_modal_obj?.flag_enable_modal_exit_intent ?? false;
20	if (flag_enable_modal_exit_intent) {
21		console.log('flag modal_exit_intent is on');
22	}
23	let flag_modal_slider_compatibility = window.frames_modal_slider_obj?.flag_modal_slider_compatibility ?? false;
24	if (flag_modal_slider_compatibility) {
25		console.log('flag modal_slider_compatibility is on');
26	}
27
28	/**
29	 * Helper function
30	 * @param {string} data - The JSON string to parse, safely replaces HTML entities
31	 * @returns {Object|null}
31 The parsed JSON object, or null if parsin fails
32	 */
33	function parseJSONData(data) {
34		try {
35			return JSON.parse(data.replace(/"/g, '"'));
36		} catch (e) {
37			console.error('Error parsing JSON data:', e);
38			return null;
39		}
40	}
41
42	/**
43	 * Get the data from modal attributes for configuration
44	 * @param {HTMLElement} modal - The modal element
45	 * @returns {Object} Object containing modal data for configuration
46	 */
47	function getDataAttributesForModal(modal) {
48		// Trigger for modal ( Selector )
49		let modalTrigger;
50
51		// Trigger for modal ( Actions, Time, Page load )
52		let modalTriggerConfig =
53			modal.dataset.frModalTriggerConfig ? parseJSONData(modal.dataset.frModalTriggerConfig) : [];
54		// Modal shown repeat rules
55		let modalRepeatActions =
56			modal.dataset.frModalRepeatActions ? parseJSONData(modal.dataset.frModalRepeatActions) : null;
57
58		if (modal.dataset.frModalTrigger) {
59			modalTrigger = modal.dataset.frModalTrigger;
60
61		}
62		if (modal.dataset.frModalTriggerEdge) {
63			edgeToEdge = modal.dataset.frModalTriggerEdge;
64
65		}
66		if (modal.dataset.frModalClose) {
67			closeSelector = modal.dataset.frModalClose;
68
69		}
70		if (modal.dataset.frModalFadeTime) {
71			fadeTime = Number(modal.dataset.frModalFadeTime);
72
73		}
74		if (modal.dataset.frVideoAutoplay) {
75			isStartModalVideo = modal.dataset.frVideoAutoplay === 'true' ? true : false;
76		}
77
78		if (modal.dataset.frModalQueryBuilder) {
79			isInQueryBuilder = modal.dataset.frModalQueryBuilder === 'true' ? true : false;
80		} else {
81			isInQueryBuilder = false;
82		}
83
84
85		return { modalTrigger, modalTriggerConfig, modalRepeatActions };
86	}
87
88	/**
89	 * Initializes modal triggers and maps with the corresponding modal
90	 * Processes selector-based and action-based triggers
91	 */
92	function generateModalTriggerConnection() {
93
94		const modalsByTrigger = new Map();
95		const modalsByAction = new Map();
96
97		/**
98		 * Iterates over modals that are not party of a Loop
99		 * Binds the modals to the respective Triggers either by Selector or Actions
100		 */
101		modalsNotInQueryBuilder.forEach(modal => {
102			const { modalTrigger, modalTriggerConfig, modalRepeatActions } = getDataAttributesForModal(modal);
103
104			//handle modals with Trigger type of Selector
105			if (modalTrigger) {
106				if (!modalsByTrigger.has(modalTrigger)) {
107					modalsByTrigger.set(modalTrigger, new Set());
108				}
109				modalsByTrigger.get(modalTrigger).add(modal);
110			}
111
112			//handle modals with Trigger type of Action
113			if (modalTriggerConfig) {
114				modalTriggerConfig.forEach(config => {
115					const actionType = config.type;
116					if (!modalsByAction.has(actionType)) {
117						modalsByAction.set(actionType, new Set());
118					}
119
120					modalsByAction.get(actionType).add({ modal, modalRepeatActions, config });
121				});
122			}
123
124			//binds the modal with the action and the repeat type for the action
125			modalsByAction.forEach((modalsWithActions, action) => {
126				modalsWithActions.forEach(({ modal, modalRepeatActions, config }) => {
127					handleAction(action, modal, config, modalRepeatActions);
128				});
129
130			});
131
132			//changed the type of loop to be the same as modalByAction, more readable
133			modalsByTrigger.forEach((modals, triggerSelector) => {
134				const triggers = document.querySelectorAll(triggerSelector);
135
136				triggers.forEach(trigger => {
137					const modal = Array.from(modals)[0];
138					const modalID = modal.id;
139					trigger.setAttribute('href', `#${modalID}`);
140					trigger.setAttribute('tabindex', '0');
141					trigger.setAttribute('role', 'button');
142					openModalWithTrigger(trigger);
143					focusFirstElementOnOpen(trigger);
144					trapFocusInModal(trigger);
145					initModalRelativeToTrigger(trigger);
146
147				});
148
149			});
150
151		});
152	}
153
154
155	function initModalRelativeToTrigger(trigger) {
156		let windowWidth = window.innerWidth;
157		modalRelativeToTrigger(trigger, windowWidth);
158
159		window.addEventListener('resize', () => {
160			windowWidth = window.innerWidth;
161			modalRelativeToTrigger(trigger, windowWidth);
162		});
163
164		window.addEventListener('orientationchange', () => {
165			windowWidth = window.innerWidth;
166			modalRelativeToTrigger(trigger, windowWidth);
167		});
168
169		window.addEventListener('scroll', () => {
170			windowWidth = window.innerWidth;
171			modalRelativeToTrigger(trigger, windowWidth);
172		});
173	}
174
175	function modalRelativeToTrigger(trigger, windowWidth) {
176
177		const modal = document.querySelector(trigger.getAttribute('href'));
178		if (!modal) {
179			return;
180		}
181		const container = modal.querySelector('.fr-modal__body');
182		if (!container) {
183			return;
184		}
185		let positionRelatedToTrigger = modal.dataset.frModalPositionRelatedToTrigger;
186		let placeFromTriggers = modal.dataset.frModalPlaceFromTriggers;
187		let xTriggerOffset = modal.dataset.frModalTriggerXoffset;
188		let yTriggerOffset = modal.dataset.frModalTriggerYoffset;
189		const edgeToEdge = modal.dataset.frModalTriggerEdge === 'true';
190
191		// positionRelatedToTrigger === 'top' || 'bottom'
192		// placeFromTriggers === 'left' || 'right' || 'center' || 'full' || 'container'
193
194		if (xTriggerOffset === '0') {
195			xTriggerOffset = '0px';
196		}
197		if (yTriggerOffset === '0') {
198			yTriggerOffset = '0px';
199		}
200
201		const triggerRect = trigger.getBoundingClientRect();
202		const triggerTopSpace = triggerRect.top;
203		const triggerLeftSpace = triggerRect.left;
204		const triggerWidth = triggerRect.width;
205		const triggerHeight = triggerRect.height;
206		const containerWidth = container.getBoundingClientRect().width;
207		const containerHeight = container.getBoundingClientRect().height;
208
209		let breakpoint;
210		if (modal.dataset.frModalCenterOption) {
211			centerOption = JSON.parse(modal.dataset.frModalCenterOption);
212			breakpoint = centerOption.centerOnBreakpoint;
213		}
214
215
216		if (placeFromTriggers === 'left' && triggerLeftSpace < containerWidth) {
217			placeFromTriggers = 'right';
218		}
219
220		if (placeFromTriggers === 'right' && windowWidth - (triggerLeftSpace + triggerWidth) < containerWidth) {
221			placeFromTriggers = 'left';
222		}
223
224		if (positionRelatedToTrigger === 'bottom' && window.innerHeight - triggerTopSpace - triggerHeight < containerHeight) {
225			positionRelatedToTrigger = 'top';
226		}
227
228		if (positionRelatedToTrigger === 'top' && triggerTopSpace < containerHeight) {
229			positionRelatedToTrigger = 'bottom';
230		}
231
232
233		container.style.position = 'fixed';
234
235		if (positionRelatedToTrigger === 'bottom') {
236			container.style.top = `calc(${triggerTopSpace + triggerHeight}px + ${yTriggerOffset})`;
237			container.style.bottom = '';
238		} else if (positionRelatedToTrigger === 'top') {
239			container.style.bottom = `calc(${window.innerHeight - triggerTopSpace}px + ${yTriggerOffset})`;
240			container.style.top = '';
241		}
242
243		function positionModal() {
244			let scaleSize = 0;
245
246			if ((placeFromTriggers === 'left' || placeFromTriggers === 'right') && breakpoint && window.innerWidth <= breakpoint) {
247
248				container.style.left = '50%';
249				container.style.transform = 'translateX(-50%)';
250
251			} else {
252				if (placeFromTriggers === 'left') {
253					let leftPosition = triggerLeftSpace - containerWidth - scaleSize;
254					if (edgeToEdge) {
255						leftPosition += triggerWidth;
256					}
257					const finalLeftPosition = `calc(${leftPosition}px - ${xTriggerOffset})`;
258
259					container.style.maxWidth = `${triggerLeftSpace}px`;
260					container.style.left = finalLeftPosition;
261
262				} else if (placeFromTriggers === 'right') {
263					let rightPosition = triggerLeftSpace + triggerWidth;
264					const rightSpace = windowWidth - rightPosition;
265					if (edgeToEdge) {
266						rightPosition -= triggerWidth;
267					}
268					const finalRightPosition = `calc(${rightPosition}px + ${xTriggerOffset})`;
269
270					container.style.left = finalRightPosition;
271					container.style.maxWidth = `${rightSpace}px`;
272
273				} else if (placeFromTriggers === 'center') {
274					container.style.left = `calc(${triggerLeftSpace + triggerWidth / 2}px - ${containerWidth / 2}px)`;
275				} else if (placeFromTriggers === 'full') {
276					container.style.left = '0';
277					container.style.maxWidth = '100%';
278					container.style.width = '100%';
279				} else if (placeFromTriggers === 'container') {
280					container.style.left = '50%';
281					container.style.transform = 'translateX(-50%)';
282					container.style.maxWidth = 'var(--content-width)';
283					container.style.width = '100%';
284				}
285			}
286		}
287		positionModal();
288	}
289
290
291
292	function openModalWithTrigger(trigger) {
293		if (!trigger.hasEventListener) {
294			trigger.addEventListener('click', (e) => {
295				const modalId = trigger.getAttribute('href');
296				const modal = document.querySelector(modalId);
297
298				if (modal.classList.contains('fr-modal--open') && modal.dataset.frModalSameCloseTrigger === 'true') {
299					// If the modal is open and sameCloseTrigger is true, close it
300					closeModal(modal, e);
301				} else {
302					// Otherwise, open it
303					openModal(e, trigger);
304					initModalRelativeToTrigger(trigger);
305				}
306			});
307
308			trigger.addEventListener('keydown', (e) => {
309				if (e.key === 'Enter') {
310					const modalId = trigger.getAttribute('href');
311					const modal = document.querySelector(modalId);
312
313					if (modal.classList.contains('fr-modal--open') && modal.dataset.frModalSameCloseTrigger === 'true') {
314						// If the modal is open and sameCloseTrigger is true, close it
315						closeModal(modal, e);
316					} else {
317						// Otherwise, open it
318						openModal(e, trigger);
319						initModalRelativeToTrigger(trigger);
320					}
321				}
322			});
323
324			// Set flag to indicate event listeners are attached
325			trigger.hasEventListener = true;
326		}
327
328		// Get the modal associated with this trigger
329		const modalId = trigger.getAttribute('href');
330		const modal = document.querySelector(modalId);
331
332		// Stop click events inside the modal from bubbling up to the trigger
333		if (modal) {
334			const modalBody = modal.querySelector('.fr-modal__body');
335
336			if (modalBody) {
337				modalBody.addEventListener('click', (e) => {
338					// add check for bricks nav menu
339					if (!e.target.closest('.brxe-nav-menu')) {
340						e.stopPropagation();
341					}
342				});
343			}
344		}
345	}
346
347
348
349
350	function openModal(e, trigger) {
351
352		e.preventDefault();
353		const modalId = trigger.getAttribute('href');
354		const modal = document.querySelector(modalId);
355		// document.body.appendChild(modal);
356
357		if (modal) {
358			modal.triggerElement = trigger;
359		}
360		if (flag_modal_slider_compatibility) {
361			slidesCompatibility(modal);
362		}
363
364
365		if (!modal.closest('header')) {
366			modal.classList.add('fr-modal--open');
367
368		} else {
369			modal.classList.toggle('fr-modal--open');
370		}
371		modal.setAttribute('aria-hidden', 'false');
372		modal.style.display = 'flex';
373
374
375		if ('ontouchstart' in window) {
376			scrollingToggle(modal);
377		} else {
378			scrollingToggle(modal);
379		}
380
381		if (isTriggerAHamburgerWidget(trigger)) {
382			trigger.classList.toggle(higherIndexTriggerClass);
383		}
384
385		initVideo(modal);
386		initAudio(modal);
387
388		focusFirstElementInModal(e, trigger);
389	}
390
391	function slidesCompatibility(modal) {
392
393		let isInsideSlider = modal.closest('.splide__slide');
394
395		if (!bricksIsFrontend || !isInsideSlider) return;
396		const mainElement = document.querySelector('main');
397		if (mainElement) {
398			mainElement.appendChild(modal);
399		} else {
400			document.body.appendChild(modal);
401		}
402	}
403
404	/**
405	 * Toggles the visibility of a action-triggered modal
406	 * I choose to create a new function to avoid complexity attached with the openModal function
407	 * @param {HTMLElement} modal - The mapped modal to reveal or hide.
408	 */
409	function revealModal(modal) {
410		const isOpen = modal.classList.contains('fr-modal--open');
411
412		if (!isOpen) {
413			modal.classList.toggle('fr-modal--open');
414			modal.setAttribute('aria-hidden', 'false');
415			modal.style.display = 'flex';
416		} else {
417			modal.classList.remove('fr-modal--open');
418			modal.setAttribute('aria-hidden', 'true');
419			// modal.style.display = 'none'
420		}
421
422		scrollingToggle(modal);
423		initVideo(modal);
424		initAudio(modal);
425	}
426
427	/**
428	 * Execute the appropriate action to trigger a modal
429	 * @param {string} action - Type of action to handle (e.g, 'mouseLeaveViewport')
430	 * @param {HTMLElement} modal - The modal to apply the action
431	 * @param {Object} modalRepeatActions - Configuration for how the modal should show again
432	 * @param {Object} config - Settings for the Modal type of Action
433	 */
434	function handleAction(action, modal, config, modalRepeatActions) {
435		switch (action) {
436			case 'mouseLeaveViewport':
437				handleMouseLeaveViewport(modal, modalRepeatActions);
438				break;
439			case 'onPageLoad':
440				handleOnPageLoad(modal, config, modalRepeatActions);
441				break;
442			case 'onInactivity':
443				handleOnInactivity(modal, config, modalRepeatActions);
444				break;
445			case 'onHover':
446				handleOnHover(modal, config, modalRepeatActions);
447				break;
448
449			default:
450				console.log(`no action defined: ${action}`);
451		}
452	}
453
454	// TODO: @Hakira-Shymuy handleOnScrollToEl
455	if (flag_enable_modal_exit_intent) {
456		function handleAction(action, modal, config, modalRepeatActions) {
457			switch (action) {
458				case 'mouseLeaveViewport':
459					handleMouseLeaveViewport(modal, modalRepeatActions);
460					break;
461				case 'onPageLoad':
462					handleOnPageLoad(modal, config, modalRepeatActions);
463					break;
464				case 'onInactivity':
465					handleOnInactivity(modal, config, modalRepeatActions);
466					break;
467				case 'onHover':
468					handleOnHover(modal, config, modalRepeatActions);
469					break;
470				case 'onScrollToEl':
471					handleOnScrollToEl(modal, config, modalRepeatActions);
472					break;
473
474				default:
475					console.log(`no action defined: ${action}`);
476			}
477		}
478	};
479
480	//TODO: if everything works, remove this it's a duplicate of handleAction
481	// function handleAction(action, modal, config, modalRepeatActions) {
482	// 	switch (action) {
483	// 		case 'mouseLeaveViewport':
484	// 			handleMouseLeaveViewport(modal, modalRepeatActions);
485	// 			break;
486	// 		case 'onPageLoad':
487	// 			handleOnPageLoad(modal, config, modalRepeatActions);
488	// 			break;
489	// 		case 'onInactivity':
490	// 			handleOnInactivity(modal, config, modalRepeatActions);
491	// 			break;
492	// 		case 'onHover':
493	// 			handleOnHover(modal, config, modalRepeatActions);
494	// 			break;
495
496	// 		default:
497	// 			console.log(`no action defined: ${action}`)
498	// 	}
499	// };
500
501	/**
502	 * Reveals a modal when mouse leave viewport
503	 * @param {HTMLElement} modal
504	 * @param {Object} modalRepeatActions
505	 */
506	function handleMouseLeaveViewport(modal, modalRepeatActions) {
507
508		const listener = (event) => {
509			if (!event.relatedTarget && !event.toElement) {
510				const action = modalRepeatActions.repeatActions;
511				const shouldReveal = handleRepeatActions(modal, action);
512
513				if (shouldReveal) {
514					revealModal(modal);
515				}
516			}
517		};
518
519		if (!modal.hasAttribute('data-mouse-listener-added')) {
520			document.body.addEventListener('mouseleave', listener);
521			modal.setAttribute('data-mouse-listener-added', 'true');
522		}
523	}
524
525	/**
526	 * Creates a throttled function that only invokes `func` once per every `limit` milliseconds
527	 * this helper function is used to control the rate at we call the functions to check for
528	 * the activity events, otherwise we can affect the performance of the site
529	 *
530	 * @param {Function} func - The function to be throttled
531	 * @param {number} limit - The time limit in milliseconds for the throttle
532	 * @returns {Function} - A throttled version of the input function
533	 */
534	function throttle(func, limit) {
535		// Hold the timeout for the function to be executed
536		let lastFunc;
537		// Stores the timestamp of the last time that we ran the function
538		let lastRan;
539
540		return function () {
541			// Context from the function can be an object, window, etc, the args are passed on the function call
542			const context = this;
543			const args = arguments;
544
545			if (!lastRan) {
546				// If the function wasnt called then execute it
547				func.apply(context, args);
548				lastRan = Date.now();
549			} else {
550				clearTimeout(lastFunc);
551
552				// Set a new execution scheduled
553				lastFunc = setTimeout(function () {
554					if ((Date.now() - lastRan) >= limit) {
555						func.apply(context, args);
556						lastRan = Date.now();
557					}
558				}, Math.max(limit - (Date.now() - lastRan), 0));
559			}
560		};
561	}
562
563	/**
564	 * Reveals a modal with a delay when the page loads
565	 * @param {HTMLElement} modal
566	 * @param {Object} modalRepeatActions
567	 */
568	function handleOnPageLoad(modal, config, modalRepeatActions) {
569
570		// was using typeof config.options.afterPageLoad !== 'number') , but we are actually sending a number inside of a string
571		if (!config || !config.options || isNaN(Number(config.options.afterPageLoad))) {
572			console.error('After Page Load option is not a valid number or does not exist', modal);
573			return;
574		}
575
576		const delayOption = config.options.afterPageLoad;
577		const delay = delayOption * 1000;
578		setTimeout(() => {
579			const shouldReveal = handleRepeatActions(modal, modalRepeatActions.repeatActions);
580			if (shouldReveal) {
581				revealModal(modal);
582			}
583		}, delay);
584	}
585
586	/**
587 * Reveals a modal when user hovers over specified elements
588 * @param {HTMLElement} modal - The modal element to be revealed
589 * @param {Object} config - Settings for the Modal type of Action
590 * @param {Object} modalRepeatActions - Configuration for how the modal should show again
591 */
592	function handleOnHover(modal, config, modalRepeatActions) {
593		if (!config || !config.options || !config.options.hoverSelector) {
594			console.error('Invalid config or hover selector not found in config:', config);
595			return;
596		}
597		const hoverSelector = config.options.hoverSelector;
598		const elements = document.querySelectorAll(hoverSelector);
599		if (!elements.length) {
600			console.warn(`Modal hover trigger: No elements found with selector "${hoverSelector}"`);
601			return;
602		}
603		// Create a function to handle the hover event
604		const handleHover = () => {
605			if (!modal.classList.contains('fr-modal--open')) {
606				const shouldReveal = handleRepeatActions(modal, modalRepeatActions.repeatActions);
607				if (shouldReveal) {
608					revealModal(modal);
609				}
610			}
611		};
612		// Add hover listeners to all matching elements
613		elements.forEach(element => {
614			element.addEventListener('mouseenter', handleHover);
615		});
616	}
617
618
619	/**
620	 * Handle On Inactivity Action
621	 * uses the throttle function to throttle the addEventListeners to dont spam the Page
622	 *
623	 * @param {HTMLElement} modal
624	 * @param {Object} config - Settings for the Modal type of Action
625	 * @param {*} modalRepeatActions
626	 */
627	function handleOnInactivity(modal, config, modalRepeatActions) {
628		if (!config ||
629			!config.options ||
630			!['mouseInactivity', 'keyboardInactivity', 'scrollInactivity'].some(key => config.options[key]) ||
631			!config.options.inactivityTime) {
632
633			console.warn('Inactivity Config does not have any (option) or (time) set', config.options);
634			return;
635		}
636
637		const inactivityTime = config.options.inactivityTime * 1000;
638		let inactivityTimeout;
639
640		const resetInactivityTimeout = () => {
641			clearTimeout(inactivityTimeout);
642
643			inactivityTimeout = setTimeout(() => {
644				const shouldReveal = handleRepeatActions(modal, modalRepeatActions.repeatActions);
645
646				if (shouldReveal) {
647					revealModal(modal);
648				}
649			}, inactivityTime);
650		};
651
652		const throttledResetTimeout = throttle(resetInactivityTimeout, 150);
653
654		if (config.options.mouseInactivity) {
655			document.addEventListener('mousemove', throttledResetTimeout);
656		}
657		if (config.options.keyboardInactivity) {
658			document.addEventListener('keydown', throttledResetTimeout);
659		}
660		if (config.options.scrollInactivity) {
661			document.addEventListener('scroll', throttledResetTimeout);
662		}
663
664		resetInactivityTimeout();
665	}
666
667	if (flag_enable_modal_exit_intent) {
668		// TODO @Hakira-Shymuy before release put handleOnScrollToEl under Flag Feature, and exclude from release.
669		// TODO: @Hakira-Shymuy not working on sections if it does not have any other container without a Slider, might be Splide.JS
670		/**
671		 * IF there is another container than not a slider or contains a slider it is working
672		 */
673		/**
674		 * Handle on Scroll To Element
675		 * @param {HTMLElement} modal
676		 * @param {Object} config
677		 * @param {*} modalRepeatActions
678		 * @returns
679		 */
680		function handleOnScrollToEl(modal, config, modalRepeatActions) {
681			if (!config || !config.options || typeof config.options.scrollSelector !== 'string') {
682				console.error('Invalid config or scroll Selector not found in config:', config);
683				return;
684			}
685
686			const targetElement = document.querySelector(config.options.scrollSelector);
687			console.log('selector', targetElement);
688
689			if (!targetElement) {
690				console.error(`Selector not found: ${config.options.scrollSelector}`);
691				return;
692			}
693
694			if (bricksIsFrontend) {
695				console.log('is bricks frontend');
696				const observerCallback = (entries, observer) => {
697					console.log('observer callback');
698					entries.forEach(entry => {
699						console.log('entry', entry);
700						if (entry.isIntersecting) {
701							console.log('is intersecting');
702							const shouldReveal = handleRepeatActions(modal, modalRepeatActions.repeatActions);
703
704							if (shouldReveal) {
705								console.log('should reveal');
706								revealModal(modal);
707								observer.unobserve(entry.target);
708							}
709						}
710					});
711				};
712
713				const selectorThreshold = config.options.selectorThreshold ? parseInt(config.options.selectorThreshold, 10) / 100 : 0.5;
714				const observer = new IntersectionObserver(observerCallback, {
715					root: null,
716					threshold: selectorThreshold,
717				});
718
719				observer.observe(targetElement);
720				console.log(observer);
721				console.log(targetElement);
722			}
723		}
724	}
725	// End Flag
726
727
728	/**
729	 * Determines if a modal should be shown based on repeat action configuration
730	 * @param {HTMLElement} modal
731	 * @param {string} action - The type of repeat action to handle
732	 * @returns {boolean} True if the modal should be shown
733	 */
734	function handleRepeatActions(modal, action) {
735		switch (action) {
736			case 'neverShowAgain':
737				return handleNeverShowAgain(modal);
738			case 'perPageVisit':
739				return handleOncePerPageVisit(modal);
740			case 'alwaysShow':
741				return true;
742
743			default:
744				console.log('Unexpected modalRepeatActions value:', modalRepeatActions);
745				return false;
746		}
747	}
748
749	/**
750	 * Handles the logic for modals that should never be shown again
751	 * @param {HTMLElement} modal
752	 * @returns {boolean}
753	 */
754	function handleNeverShowAgain(modal) {
755		const modalID = modal.id;
756		const modalKey = `frames_neverShowAgainModal_${modalID}`;
757		const neverShow = localStorage.getItem(modalKey) === 'true';
758
759		if (!neverShow) {
760			localStorage.setItem(modalKey, 'true');
761			return true;
762		}
763		return false;
764	}
765
766	/**
767	 * @handleOncePerPageVisit
768	 *
769	 * Helper for Firefox, Firefox persists the running of javascript through back_forward navigation
770	 * performance.navigation is deprecated
771	 * https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation
772	 *
773	 */
774	function clearFramesSessionStorage() {
775		for (let i = sessionStorage.length - 1; i >= 0; i--) {
776			const key = sessionStorage.key(i);
777			if (key.startsWith('framesModal_')) {
778				sessionStorage.removeItem(key);
779			}
780		}
781	}
782
783	window.addEventListener('pageshow', (event) => {
784		if (event.persisted || window.PerformanceEventTiming.type === 2) {
785			clearFramesSessionStorage();
786		}
787	});
788
789	window.addEventListener('load', () => {
790		clearFramesSessionStorage();
791	});
792
793	function handleOncePerPageVisit(modal) {
794		const modalId = modal.id;
795		const modalShownKey = `framesModal_oncePerPageVisitModal_${modalId}`;
796		const shownThisVisit = sessionStorage.getItem(modalShownKey) === 'true';
797
798		if (!shownThisVisit) {
799			sessionStorage.setItem(modalShownKey, true);
800			return true;
801		}
802
803		return false;
804	}
805
806	// audio
807	function initAudio(modal) {
808		if (isHtmlAudio(modal)) {
809			initHtmlAudio(modal);
810		}
811		// Later, you can add checks for other audio types here.
812	}
813
814	function isHtmlAudio(modal) {
815		const audio = modal.querySelector('audio');
816		return audio?.src !== undefined;
817	}
818
819	function initHtmlAudio(modal) {
820		const audio = modal.querySelector('audio');
821		console.log('audio', audio);
822		if (modal.dataset.frModalVideoAutoplay === 'true') {
823			audio.play();
824		}
825	}
826
827	function stopAudio(modal) {
828		stopHtmlAudio(modal);
829	}
830
831	function stopHtmlAudio(modal) {
832		if (!isHtmlAudio(modal)) return;
833		const audio = modal.querySelector('audio');
834		if (audio) {
835			audio.pause();
836		}
837	}
838
839	// video
840	function initVideo(modal) {
841
842		if (isYoutubeVideo(modal)) {
843			initYoutubePlayer(modal);
844		} else if (isVimeoVideo(modal)) {
845			initVimeoPlayer(modal);
846		} else if (isHtmlVideo(modal)) {
847			initHtmlVideo(modal);
848		}
849		// Later, you can add checks for other video types here.
850	}
851
852	function isHtmlVideo(modal) {
853		if (!modal.querySelector('video')) return false;
854		const video = modal.querySelector('video');
855		return video && video.src;
856	}
857
858	function isVimeoVideo(modal) {
859		if (!modal.querySelector('iframe')) return false;
860		const iframe = modal.querySelector('iframe');
861
862		return iframe && iframe.src.includes('vimeo.com');
863	}
864
865	function initVimeoPlayer(modal) {
866		const iframe = modal.querySelector('iframe');
867		if (modal.dataset.frModalVideoAutoplay === 'true') {
868			const iframeSrc = iframe.src;
869
870			iframe.src = `${iframeSrc}&autoplay=1`;
871		}
872	}
873
874	function isYoutubeVideo(modal) {
875		if (!modal.querySelector('iframe')) return false;
876		const iframe = modal.querySelector('iframe');
877		let isYoutube = false;
878		if (iframe && iframe.src.includes('youtube.com')) {
879			isYoutube = true;
880		}
881		return isYoutube && window.YT && window.YT.Player;
882	}
883
884
885	// Load YouTube API if there are any YouTube videos in the modals
886
887	window.addEventListener('load', () => {
888		let modalsWithYoutubeVideoCounter = 0;
889		modals.forEach(modal => {
890			if (!modal.querySelector('iframe')) return false;
891			const iframe = modal.querySelector('iframe');
892			if (iframe.src.includes('youtube.com')) {
893				loadYoutubeApi();
894				modalsWithYoutubeVideoCounter++;
895			}
896		});
897	});
898
899	function initHtmlVideo(modal) {
900		const video = modal.querySelector('video');
901		if (modal.dataset.frModalVideoAutoplay === 'true') {
902			video.play();
903		}
904	}
905
906	function initYoutubePlayer(modal) {
907		const iframe = modal.querySelector('iframe');
908		const videoId = iframe.src.split('embed/')[1].split('?')[0];
909
910		if (!iframe.player) {
911			iframe.player = new YT.Player(iframe, {
912				videoId: videoId,
913				events: {
914					'onReady': function (event) {
915						if (modal.dataset.frModalVideoAutoplay === 'true') {
916							event.target.playVideo();
917						}
918					}
919				}
920			});
921		} else if (modal.dataset.frModalVideoAutoplay === 'true') {
922			iframe.player.playVideo();
923		}
924	}
925
926	function loadYoutubeApi() {
927		if (window.YT && window.YT.Player) {
928			// YouTube API is already loaded
929			return;
930		}
931
932		// This function will be called when the script has finished loading
933		window.onYouTubeIframeAPIReady = function () {
934			// YouTube API is ready to use
935			// console.log('YouTube IFrame API is ready');
936			// Initialize video players or anything else that depends on the API here
937		};
938
939		// Create a new script element for the YouTube IFrame API
940		var tag = document.createElement('script');
941		tag.src = 'https://www.youtube.com/iframe_api';
942		var firstScriptTag = document.getElementsByTagName('script')[0];
943		firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
944	}
945
946
947	function stopVideo(modal) {
948		stopYoutubeVideo(modal);
949		stopVimeoVideo(modal);
950		stopHtmlVideo(modal);
951	}
952
953	function stopHtmlVideo(modal) {
954		if (!isHtmlVideo(modal)) return;
955		const video = modal.querySelector('video');
956		if (video) {
957			video.pause();
958		}
959	}
960
961	function stopYoutubeVideo(modal) {
962		if (!isYoutubeVideo(modal)) return;
963		const iframe = modal.querySelector('iframe');
964		if (iframe && iframe.player) {
965			iframe.player.stopVideo();
966		}
967	}
968
969	function stopVimeoVideo(modal) {
970		if (!isVimeoVideo(modal)) return;
971		const iframe = modal.querySelector('iframe');
972		const iframeSrc = iframe.src;
973		iframe.src = iframeSrc.replace('&autoplay=1', '');
974	}
975
976	function closeModalWithHamburgerWidget(modals) {
977		modals.forEach(modal => {
978			const trigger = document.querySelector(`[href="#${modal.id}"]`);
979			if (isTriggerAHamburgerWidget(trigger)) {
980
981				addEventListenerWithEventInfo(trigger, 'click', (e) => {
982					if (modal.classList.contains('fr-modal--open') && !trigger.classList.contains(higherIndexTriggerClass)) {
983						closeModal(modal, e);
984					}
985				});
986
987				addEventListenerWithEventInfo(trigger, 'keydown', (e) => {
988					if (e.key === 'Enter') {
989						if (modal.classList.contains('fr-modal--open') && !trigger.classList.contains(higherIndexTriggerClass)) {
990							closeModal(modal, e);
991						}
992					}
993				});
994			}
995		});
996	}
997
998
999	function closeModalWithCloseIcon(modals) {
1000		modals.forEach(modal => {
1001			if (modal.querySelector('.fr-modal__close-icon-wrapper')) {
1002				const fadeTime = Number(modal.dataset.frModalFadeTime);
1003				const closeIcon = modal.querySelector('.fr-modal__close-icon-wrapper');
1004
1005				addEventListenerWithEventInfo(closeIcon, 'click', (e) => {
1006					closeModal(modal, e);
1007					removeActiveBurgerClassOnModalClose(modal);
1008				});
1009
1010				addEventListenerWithEventInfo(closeIcon, 'keydown', (e) => {
1011					if (e.key === 'Enter') {
1012						closeModal(modal, e);
1013						removeActiveBurgerClassOnModalClose(modal);
1014					}
1015				});
1016			}
1017		});
1018
1019	}
1020
1021	function closeModalWithEscKey(modals) {
1022		document.addEventListener('keydown', (e) => {
1023			if (e.key === 'Escape') {
1024				modals.forEach(modal => {
1025					const fadeTime = Number(modal.dataset.frModalFadeTime);
1026					if (modal.classList.contains('fr-modal--open')) {
1027						closeModal(modal, e);
1028						removeActiveBurgerClassOnModalClose(modal);
1029					}
1030				});
1031			}
1032
1033
1034		});
1035	}
1036
1037	function closeModalWithACustomSelector(modals) {
1038		modals.forEach(modal => {
1039			getDataAttributesForModal(modal);
1040			if (modal.querySelector(closeSelector)) {
1041				const closeElement = modal.querySelector(closeSelector);
1042				if (closeElement) {
1043					addEventListenerWithEventInfo(closeElement, 'click', (e) => {
1044						closeModal(modal, e);
1045						removeActiveBurgerClassOnModalClose(modal);
1046					});
1047				}
1048			}
1049		});
1050	}
1051
1052
1053
1054	function closeModalOnOverlayClick(modals) {
1055		modals.forEach(modal => {
1056			let disableCloseOutside = modal.dataset.frModalDisableCloseOutside === 'true';
1057
1058			if (!disableCloseOutside) {
1059				const fadeTime = Number(modal.dataset.frModalFadeTime);
1060				const overlay = modal.querySelector('.fr-modal__overlay');
1061				overlay.addEventListener('click', (e) => {
1062					closeModal(modal, e);
1063					removeActiveBurgerClassOnModalClose(modal);
1064				});
1065			}
1066		});
1067	}
1068
1069
1070
1071
1072	/**
1073	 * wrapper function for the addEventListener to help get the type of interaction
1074	 *
1075	 * @param {HTMLElement} element - the DOM element that will receive the event
1076	 * @param {string} eventType - represents the type of event (click, keydown)
1077	 * @param {Function} callback - the functions to be called when the event is triggered
1078	 */
1079	function addEventListenerWithEventInfo(element, eventType, callback) {
1080		element.addEventListener(eventType, (event) => {
1081			event.isKeyboardEvent = (eventType === 'keydown');
1082
1083			callback(event);
1084		});
1085	}
1086
1087
1088	function closeModal(modal, closeTrigger) {
1089		const fadeTime = parseInt(modal.dataset.frModalFadeTime);
1090		const fadeOutTime = parseInt(modal.dataset.frModalFadeOutTime) || fadeTime;
1091		const currentScrollPosition = window.scrollY;
1092		let disableCloseOutside = modal.dataset.frModalDisableCloseOutside === 'true';
1093		let sameCloseTrigger = modal.dataset.frModalSameCloseTrigger === 'true';
1094
1095		if (closeTrigger && closeTrigger.target.classList.contains('fr-modal__overlay') && disableCloseOutside) {
1096			return;
1097		}
1098
1099		let isTriggerClose = closeTrigger && closeTrigger.target.closest(modal.dataset.frModalTrigger);
1100
1101		//TODO remove this
1102		// if (!isTriggerClose && sameCloseTrigger && closeTrigger &&
1103		// !closeTrigger.target.classList.contains('fr-modal__close-icon') &&
1104		// !closeTrigger.target.closest('.fr-modal__close-icon') &&
1105		// !closeTrigger.target.closest(modal.dataset.frModalClose)) {
1106		// 	return;
1107		// }
1108
1109		if (closeTrigger) {
1110			closeTrigger.stopPropagation();
1111		}
1112
1113		modal.classList.add('fr-modal--closing');
1114		modal.classList.remove('fr-modal--open');
1115		modal.setAttribute('aria-hidden', 'true');
1116
1117		setTimeout(() => {
1118			modal.classList.remove('fr-modal--closing');
1119			scrollingToggle(modal);
1120			window.scrollTo(0, currentScrollPosition);
1121		}, fadeOutTime);
1122
1123		stopVideo(modal);
1124		stopAudio(modal);
1125
1126		if (isTriggerClose && sameCloseTrigger) {
1127			const trigger = closeTrigger.target.closest(modal.dataset.frModalTrigger);
1128			if (trigger) {
1129				trigger.classList.remove('fr-modal__trigger--higher-index');
1130				if (trigger.classList.contains('fr-hamburger--active')) {
1131					trigger.classList.remove('fr-hamburger--active');
1132				}
1133				if (trigger.classList.contains('fr-button-trigger--active')) {
1134					trigger.classList.remove('fr-button-trigger--active');
1135				}
1136			}
1137		}
1138
1139		if (closeTrigger.isKeyboardEvent) {
1140			setFocusBackToTrigger(modal);
1141		}
1142	}
1143
1144
1145
1146
1147
1148	function setFocusBackToTrigger(modal) {
1149
1150		const modalTrigger = modal.triggerElement;
1151
1152		if (modalTrigger) {
1153			const fadeOutTime = parseInt(modal.dataset.frModalFadeOutTime) || 300;
1154			setTimeout(() => {
1155				modalTrigger.focus();
1156			}, fadeOutTime);
1157		}
1158	}
1159
1160
1161
1162
1163
1164
1165	// Global Modal Functions
1166
1167	function setTransitionTime(modals) {
1168		modals.forEach(modal => {
1169			const fadeTime = Number(modal.dataset.frModalFadeTime);
1170			const fadeOutTime = Number(modal.dataset.frModalFadeOutTime);
1171			const modalBody = modal.querySelector('.fr-modal__body');
1172
1173			// modal.style.transition = `all ${fadeTime}ms ease-in-out`;
1174			// modalBody.style.transition = `all ${fadeTime}ms ease-in-out`;
1175
1176			modal.style.setProperty('--fade-in-time', `${fadeTime}ms`);
1177			modal.style.setProperty('--fade-out-time', `${fadeOutTime}ms`);
1178		});
1179	}
1180
1181	// Focus Functions
1182
1183	function focusFirstElementOnOpen(trigger) {
1184		// trigger.addEventListener('click', (e) => {
1185		//   focusFirstElementInModal(e, trigger)
1186		// });
1187		trigger.addEventListener('keydown', (e) => {
1188			if (e.key === 'Enter') {
1189				e.preventDefault();
1190				focusFirstElementInModal(e, trigger);
1191			}
1192		});
1193	}
1194
1195	function focusFirstElementInModal(e, trigger) {
1196		e.preventDefault();
1197		const modalId = trigger.getAttribute('href');
1198		const modal = document.querySelector(modalId);
1199		const modalBody = modal.querySelector('.fr-modal__body');
1200		const fadeTime = Number(modal.dataset.frModalFadeTime);
1201
1202		const setModalFocus = () => {
1203			const focusableContent = modalBody.querySelectorAll(focusableElements);
1204
1205			if (focusableContent.length > 0) {
1206				focusableContent[0].focus();
1207			} else {
1208				modalBody.setAttribute('tabindex', '-1');
1209				modalBody.focus();
1210			}
1211		};
1212
1213		if (fadeTime >= 100) {
1214			setTimeout(() => {
1215				setModalFocus();
1216			}, fadeTime);
1217		} else {
1218			setTimeout(() => {
1219				setModalFocus();
1220			}, 100);
1221		}
1222	}
1223
1224	function trapFocusInModal(trigger) {
1225		const modalId = trigger.getAttribute('href');
1226		const modal = document.querySelector(modalId);
1227		const modalBody = modal.querySelector('.fr-modal__body');
1228		const closeButton = modal.querySelector('.fr-modal__close-icon');
1229		const customCloseButton = modal.dataset.frModalClose ?
1230			modal.querySelector(modal.dataset.frModalClose) : null;
1231
1232		function handleFocusTrap(e) {
1233			// Get all focusable elements, including close buttons
1234			const focusableContent = [
1235				...(closeButton ? [closeButton] : []),
1236				...(customCloseButton ? [customCloseButton] : []),
1237				...Array.from(modalBody.querySelectorAll(focusableElements))
1238			].filter(el => el.offsetParent !== null); // Filter out any hidden elements
1239
1240			if (focusableContent.length === 0) {
1241				focusableContent.push(modalBody);
1242				modalBody.setAttribute('tabindex', '-1');
1243			}
1244
1245			const firstElement = focusableContent[0];
1246			const lastElement = focusableContent[focusableContent.length - 1];
1247
1248			if (e.key === 'Tab') {
1249				if (e.shiftKey && document.activeElement === firstElement) {
1250					e.preventDefault();
1251					lastElement.focus();
1252				} else if (!e.shiftKey && document.activeElement === lastElement) {
1253					e.preventDefault();
1254					firstElement.focus();
1255				}
1256			}
1257		}
1258
1259		modal.removeEventListener('keydown', handleFocusTrap);
1260		modal.addEventListener('keydown', handleFocusTrap);
1261	}
1262
1263
1264
1265
1266
1267
1268	// Focus Functions Helpers
1269
1270	function loopThroughFocusElements(firstFocusableElement, lastFocusableElement) {
1271		firstFocusableElement.addEventListener('keydown', (e) => {
1272			if (e.key === 'Tab' && e.shiftKey) {
1273				e.preventDefault();
1274				lastFocusableElement.focus();
1275			}
1276		});
1277
1278		lastFocusableElement.addEventListener('keydown', (e) => {
1279			if (e.key === 'Tab' && !e.shiftKey) {
1280				e.preventDefault();
1281				firstFocusableElement.focus();
1282			}
1283		});
1284	}
1285
1286	function preventScrolling() {
1287		document.body.style.overflow = 'hidden';
1288	}
1289
1290
1291
1292	const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
1293	document.documentElement.style.setProperty('--fr-scrollbar-width', `${scrollBarWidth}px`);
1294
1295	function scrollingToggle(modal) {
1296		if (modal.dataset.frModalAllowScroll === 'true') return;
1297
1298		const bodyHeight = document.body.scrollHeight;
1299		const windowHeight = window.innerHeight;
1300
1301		if (bodyHeight > windowHeight) {
1302			if (window.innerWidth > 767 && scrollBarWidth > 0) {
1303				document.body.classList.toggle('fr-modal-body-padding');
1304			}
1305		}
1306
1307		document.body.classList.toggle('fr-modal-prevent-scroll');
1308		if (modal.getAttribute('aria-hidden') === 'true' && document.body.classList.contains('fr-modal-prevent-scroll')) {
1309			document.body.classList.remove('fr-modal-prevent-scroll');
1310		}
1311	}
1312
1313	function removeAllInBuilder() {
1314		const modals = document.querySelectorAll('.iframe .fr-modal');
1315		modalsInQueryBuilder.forEach(modal => {
1316			if (modal !== modals[0]) {
1317				modal.style.display = 'none';
1318			}
1319			modals[0].style.display = 'flex';
1320		});
1321	}
1322
1323	function setModalBodyToOverflowScroll(modal) {
1324		const modalBody = modal.querySelector('.fr-modal__body');
1325		if (modal.dataset.frModalScroll === 'true') {
1326			modalBody.style.overflow = 'scroll';
1327		}
1328		else {
1329			return;
1330		}
1331	}
1332
1333
1334	function removeActiveBurgerClassOnModalClose(modal) {
1335		const trigger = document.querySelector(`[href="#${modal.id}"]`);
1336		if (isTriggerAHamburgerWidget(trigger)) {
1337			if (trigger.classList.contains(higherIndexTriggerClass)) {
1338				trigger.classList.remove(higherIndexTriggerClass);
1339				// if trigger containe fr-hamburger--active
1340				if (trigger.classList.contains('fr-hamburger--active')) {
1341					trigger.classList.remove('fr-hamburger--active');
1342				}
1343				if (trigger.classList.contains('fr-button-trigger--active')) {
1344					let options = {};
1345					if (trigger.dataset.frTriggerOptions) {
1346						try {
1347							options = JSON.parse(trigger.dataset.frTriggerOptions);
1348						} catch (error) {
1349							console.error('Error parsing frTriggerOptions', error);
1350						}
1351					}
1352
1353					if (options.useActiveText) {
1354
1355						trigger.querySelector('.fr-button-trigger__text').innerHTML = options.buttonText;
1356
1357					}
1358					trigger.classList.remove('fr-button-trigger--active');
1359				}
1360			}
1361		}
1362	}
1363
1364	function isTriggerAHamburgerWidget(trigger) {
1365
1366		if (trigger) {
1367			if (trigger.classList.contains('brxe-fr-trigger')) {
1368				return true;
1369			} else {
1370				return false;
1371			}
1372		}
1373	}
1374
1375	function showOnlyFirstModalInBuilderInsideQuery() {
1376		const modals = document.querySelectorAll('.iframe .fr-modal');
1377		modals.forEach((modal, index) => {
1378
1379			if (modal.dataset.frModalInsideQuery === 'true' && index !== 0) {
1380				modal.remove();
1381			}
1382		});
1383	}
1384
1385	// Logic
1386
1387
1388
1389	for (let i = 0; i < modals.length; i++) {
1390		const modal = modals[i];
1391		modal.classList.remove('fr-modal--hide');
1392	}
1393
1394	for (let i = 0; i < modals.length; i++) {
1395		const modal = modals[i];
1396		getDataAttributesForModal(modal);
1397	}
1398
1399
1400	function generateModalTriggerConnectionInQueryBuilder() {
1401		const modalsIDs = [];
1402		modalsInQueryBuilder.forEach((modal, index) => {
1403			const triggerSelector = modal.dataset.frModalTrigger;
1404			modalsIDs.push(modal.id);
1405			const triggers = document.querySelectorAll(triggerSelector);
1406			triggers.forEach((trigger, index) => {
1407				let sharedParent = trigger.closest(`.${modal.dataset.frModalQueryId}`);
1408
1409				if (sharedParent) {
1410					let innerModal, innerTrigger;
1411					if (sharedParent === trigger) {
1412						// Trigger is the sharedParent itself
1413						innerModal = sharedParent.querySelector('.fr-modal');
1414						innerTrigger = trigger;
1415					} else {
1416						innerModal = sharedParent.querySelector('.fr-modal');
1417						innerTrigger = sharedParent.querySelector(`${innerModal.dataset.frModalTrigger}`);
1418					}
1419
1420					let newID;
1421					if (document.querySelectorAll(`#${innerModal.id}`).length > 1) {
1422						newID = `${innerModal.id}-${Math.random().toString(36).substr(2, 5)}`;
1423					} else {
1424						newID = innerModal.id;
1425					}
1426					innerModal.id = newID;
1427					innerTrigger.setAttribute('href', `#${innerModal.id}`);
1428					if (innerModal.id === innerTrigger.getAttribute('href').slice(1)) {
1429						innerTrigger.setAttribute('tabindex', '0');
1430						innerTrigger.setAttribute('role', 'button');
1431						openModalWithTrigger(innerTrigger);
1432						focusFirstElementOnOpen(innerTrigger);
1433						trapFocusInModal(innerTrigger);
1434					}
1435				}
1436			});
1437
1438		});
1439	}
1440
1441
1442
1443	const modalsInQueryBuilder = Array.from(modals).filter(modal => modal.dataset.frModalInsideQuery === 'true');
1444	const modalsNotInQueryBuilder = Array.from(modals).filter(modal => modal.dataset.frModalInsideQuery === 'false');
1445
1446
1447	generateModalTriggerConnection();
1448	generateModalTriggerConnectionInQueryBuilder();
1449
1450	// modals.forEach(modal => {
1451	//   setModalBodyToOverflowScroll(modal)
1452	// });
1453
1454
1455
1456	setTransitionTime(modals);
1457
1458	// Close Modal Functions
1459	closeModalWithHamburgerWidget(modals);
1460	closeModalWithEscKey(modals);
1461	if (!document.querySelector('.iframe .fr-modal')) {
1462		closeModalOnOverlayClick(modals);
1463		closeModalWithACustomSelector(modals);
1464		closeModalWithCloseIcon(modals);
1465	}
1466
1467	// Builder Functions
1468	showOnlyFirstModalInBuilderInsideQuery();
1469
1470}
1471
1472
1473function wpgb_modal_script() {
1474	window.WP_Grid_Builder && WP_Grid_Builder.on('init', function (wpgb) {
1475
1476		// console.log(wpgb); // Holds all instances.
1477		// console.log(wpgb.element); // Holds all instances.
1478
1479		if (wpgb.element.classList.contains('wp-grid-builder')) return;
1480		wpgb.facets.on('appended', function (nodes) {
1481
1482			modal_script();
1483
1484		});
1485
1486	});
1487}
1488
1489function runModalScriptsOnBricksFilters() {
1490	if (typeof window.bricksFilters !== 'function') return;
1491
1492
1493	const bricksFilterRun = bricksFiltersFn.run;
1494	bricksFiltersFn.run = function () {
1495
1496		bricksFilterRun.apply();
1497		modal_script();
1498	};
1499
1500}
1501
1502document.addEventListener('DOMContentLoaded', function (e) {
1503	bricksIsFrontend && modal_script();
1504	bricksIsFrontend && wpgb_modal_script();
1505	bricksIsFrontend && runModalScriptsOnBricksFilters();
1506});

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.