PageSourceSearch

https://www.abfjournal.com/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.6.2

js abfjournal.com collected 2026-10-02 10:03:31 UTC 67,845 bytes, 2,565 lines download raw bytes

1( function( $ ) {
2
3	"use strict";
4
5	var JetEngineRegisteredStores = window.JetEngineRegisteredStores || {};
6	var JetEngineStores           = window.JetEngineStores || {};
7
8	var JetEngine = {
9
10		currentMonth: null,
11		currentRequest: {},
12		activeCalendarDay: null,
13		lazyLoading: false,
14		addedScripts: [],
15		addedStyles: [],
16		addedPostCSS: [],
17		assetsPromises: [],
18
19		initDone: false,
20
21		commonInit: function() {
22
23			JetEngine.commonEvents();
24
25			$( window ).on( 'jet-popup/render-content/ajax/success', JetEngine.initStores );
26
27			window.JetPlugins.hooks.addFilter(
28				'jet-popup.show-popup.data',
29				'JetEngine.popupData',
30				( popupData, $popup, $triggeredBy ) => {
31
32					if ( ! $triggeredBy ) {
33						return popupData;
34					}
35
36					if ( $triggeredBy.data( 'popupIsJetEngine' ) ) {
37						popupData = JetEngine.prepareJetPopup( popupData, { 'is-jet-engine': true }, $triggeredBy );
38					}
39
40					return popupData;
41				}
42			);
43
44			JetEngine.initStores();
45			JetEngine.customUrlActions.init();
46
47		},
48
49		commonEvents: function( $scope ) {
50			$scope = $scope || $( document );
51
52			$scope
53				.on( 'jet-filter-content-rendered', JetEngine.calendarCache.clear )
54				.on( 'change.JetEngine', '.jet-calendar-caption__date-select', JetEngine.selectCalendarMonth )
55				.on( 'click.JetEngine', '.jet-calendar-nav__link', JetEngine.switchCalendarMonth )
56				.on( 'click.JetEngine', '.jet-calendar-week__day-mobile-overlay', JetEngine.showCalendarEvent )
57				.on( 'click.JetEngine', '.jet-listing-dynamic-link__link[data-delete-link="1"]', JetEngine.showConfirmDeleteDialog )
58				.on( 'jet-filter-content-rendered', JetEngine.maybeReinitSlider )
59				.on( 'click.JetEngine', '.jet-add-to-store', JetEngine.addToStore )
60				.on( 'click.JetEngine', '.jet-remove-from-store', JetEngine.removeFromStore )
61				.on( 'click.JetEngine', '.jet-engine-listing-overlay-wrap:not([data-url*="event=hover"])', JetEngine.handleListingItemClick )
62				.on( 'jet-filter-content-rendered', JetEngine.filtersCompatibility )
63				.on( 'click.JetEngine', '.jet-container[data-url]', JetEngine.handleContainerURL )
64				.on( 'change.JetEngine', '.jet-listing-dynamic-link .qty', JetEngine.handleProductQuantityChange );
65		},
66
67		handleProductQuantityChange: function ( event ) {
68			event.preventDefault();
69			event.stopPropagation();
70
71			const $this = $( this );
72
73			$this.closest( ".jet-listing-dynamic-link" ).find( ".jet-woo-add-to-cart" ).data( "quantity", $this.val() ).attr( "data-quantity", $this.val() );
74		},
75
76		handleContainerURL: function() {
77			var $this  = $( this ),
78				url    = $this.data( 'url' ),
79				target = $this.data( 'target' );
80
81			if ( ! target ) {
82				window.location = url;
83			} else {
84				window.open( url, '_blank' ).focus();
85			}
86
87		},
88
89		filtersCompatibility: function( event, $provider, filtersInstance, providerType ) {
90
91			if ( 'jet-engine' !== providerType ) {
92				return;
93			}
94
95			/*
96			No need anymore to manually re-init the block.
97			JetSmartFilters automatically re-init blocks.
98
99			var $blocksListing = $provider.closest( '.jet-listing-grid--blocks' );
100
101			if ( $blocksListing.length ) {
102				JetEngine.widgetListingGrid( $blocksListing );
103			}
104			*/
105
106			if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) {
107				window.JetPopupFrontend.initAttachedPopups( $provider );
108			}
109		},
110
111		init: function() {
112
113			var widgets = {
114				'jet-listing-dynamic-field.default' : JetEngine.widgetDynamicField,
115				'jet-listing-grid.default': JetEngine.widgetListingGrid,
116			};
117
118			$.each( widgets, function( widget, callback ) {
119				window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback );
120			});
121
122			// Re-init sliders in nested tabs
123			window.elementorFrontend.elements.$window.on(
124				'elementor/nested-tabs/activate',
125				( event, content ) => {
126					const $content = $( content );
127
128					setTimeout( () => {
129						JetEngine.maybeReinitSlider( event, $content );
130						JetEngine.widgetDynamicField( $content );
131					} );
132				}
133			);
134
135			window.elementorFrontend.hooks.addFilter(
136				'jet-popup/widget-extensions/popup-data',
137				JetEngine.prepareJetPopup
138			);
139
140			window.JetPlugins.hooks.addFilter(
141				'jet-popup.show-popup.data',
142				'JetEngine.popupData',
143				( popupData, $popup, $triggeredBy ) => {
144
145					if ( ! $triggeredBy ) {
146						return popupData;
147					}
148
149					if ( $triggeredBy.data( 'popupIsJetEngine' ) ) {
150						popupData = JetEngine.prepareJetPopup( popupData, { 'is-jet-engine': true }, $triggeredBy );
151					}
152
153					return popupData;
154				}
155			);
156
157			JetEngine.updateAddedStyles();
158		},
159
160		initBricks: function( $scope ) {
161
162			if ( window.bricksIsFrontend ) {
163				return;
164			}
165
166			$scope = $scope || $( 'body' );
167			JetEngine.initBlocks( $scope );
168
169		},
170
171		initBlocks: function( $scope ) {
172
173			$scope = $scope || $( 'body' );
174
175			window.JetPlugins.init( $scope, [
176				{
177					block: 'jet-engine/listing-grid',
178					callback: JetEngine.widgetListingGrid
179				},
180				{
181					block: 'jet-engine/dynamic-field',
182					callback: JetEngine.widgetDynamicField
183				}
184			] );
185		},
186
187		initFrontStores: function( $scope ) {
188
189			$scope = $scope || $( 'body' );
190
191			$( '.jet-add-to-store.is-front-store', $scope ).each( function() {
192
193				var $this = $( this ),
194					args  = $this.data( 'args' ),
195					store = JetEngineStores[ args.store.type ],
196					count = 0;
197
198				args = JetEngine.ensureJSON( args );
199
200				if ( ! store ) {
201					return;
202				}
203
204				if ( store.inStore( args.store.slug, '' + args.post_id ) ) {
205					JetEngine.switchDataStoreStatus( $this );
206				}
207
208			} );
209
210			$( '.jet-remove-from-store.is-front-store', $scope ).each( function() {
211
212				var $this = $( this ),
213					args  = $this.data( 'args' ),
214					store = JetEngineStores[ args.store.type ],
215					count = 0;
216
217				args = JetEngine.ensureJSON( args );
218
219				if ( ! store ) {
220					return;
221				}
222
223				if ( ! store.inStore( args.store.slug, '' + args.post_id ) ) {
224					$this.addClass( 'is-hidden' );
225				} else {
226					$this.removeClass( 'is-hidden' );
227				}
228
229			} );
230
231		},
232
233		initStores: function() {
234
235			JetEngine.initFrontStores();
236
237			$.each( JetEngineRegisteredStores, function( storeSlug, storeType ) {
238
239				var store = JetEngineStores[ storeType ],
240					storeData = null,
241					count = 0;
242
243				if ( ! store ) {
244					return;
245				}
246
247				storeData = store.getStore( storeSlug );
248
249				if ( storeData && storeData.length ) {
250					count = storeData.length;
251				}
252
253				$( 'span.jet-engine-data-store-count[data-store="' + storeSlug + '"]' ).text( count );
254
255			} );
256
257			JetEngine.loadFrontStoresItems();
258
259		},
260
261		loadFrontStoresItems: function( $scope ) {
262
263			$scope = $scope || $( 'body' );
264
265			$( '.jet-listing-not-found.jet-listing-grid__items', $scope ).each( function() {
266
267				var $this   = $( this ),
268					nav     = $this.data( 'nav' ),
269					isStore = $this.data( 'is-store-listing' ),
270					query   = nav.query || {};
271
272				nav = JetEngine.ensureJSON( nav );
273
274				if ( query && query.post__in && query.post__in.length && 0 >= query.post__in.indexOf( 'is-front' ) ) {
275
276					var storeType  = query.post__in[1],
277						storeSlug  = query.post__in[2],
278						store      = JetEngineStores[ storeType ],
279						posts      = [],
280						$container = $this.closest( '.elementor-widget-container' );
281
282					if ( ! store ) {
283						return;
284					}
285
286					//Context Gutenberg
287					if ( ! $container.length ) {
288						$container = $this.closest( '.jet-listing-grid--blocks' );
289					}
290
291					// Context Bricks
292					if ( ! $container.length ) {
293						$container = $this.closest( '.brxe-jet-engine-listing-grid' )
294					}
295
296					posts = store.getStore( storeSlug );
297
298					if ( ! posts.length ) {
299						return;
300					}
301
302					query.post__in = posts;
303					query.is_front_store = true;
304
305					JetEngine.ajaxGetListing( {
306						handler: 'get_listing',
307						container: $container,
308						masonry: false,
309						slider: false,
310						append: false,
311						query: query,
312						widgetSettings: nav.widget_settings,
313					}, function( response ) {
314						JetEngine.widgetListingGrid( $container );
315					} );
316
317				} else if ( isStore ) {
318					$( document ).trigger( 'jet-listing-grid-init-store', $this );
319				}
320
321			} );
322		},
323
324		removeFromStore: function( event ) {
325
326			event.preventDefault();
327			event.stopPropagation();
328
329			var $this = $( this ),
330				args  = $this.data( 'args' ),
331				isDataStoreBtn = $this.hasClass( 'jet-data-store-link' );
332
333			args = JetEngine.ensureJSON( args );
334
335			if ( args.store.is_front ) {
336
337				var store = JetEngineStores[ args.store.type ],
338					count = 0;
339
340				if ( ! store ) {
341					return;
342				}
343
344				if ( ! store.inStore( args.store.slug, '' + args.post_id ) ) {
345					var storePosts = store.getStore( args.store.slug );
346					count = storePosts.length;
347				} else {
348					count = store.remove( args.store.slug, args.post_id );
349				}
350
351				$( '.jet-add-to-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() {
352					JetEngine.switchDataStoreStatus( $( this ), true );
353				} );
354
355				$( '.jet-data-store-link.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() {
356					JetEngine.switchDataStoreStatus( $( this ), true );
357				} );
358
359				$( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( count );
360
361				if ( args.remove_from_listing ) {
362					$this.closest( '.jet-listing-dynamic-post-' + args.post_id ).remove();
363				}
364
365				JetEngine.dataStoreSyncListings( args );
366
367				$( document ).trigger( 'jet-engine-data-stores-on-remove', args );
368
369				return;
370
371			}
372
373			if ( $this.hasClass( 'jet-store-processing' ) ) {
374				return;
375			}
376
377			$this.css( 'opacity', 0.3 );
378			$this.addClass( 'jet-store-processing' );
379
380			$.ajax({
381				url: JetEngineSettings.ajaxurl,
382				type: 'POST',
383				dataType: 'json',
384				data: {
385					action: 'jet_engine_remove_from_store_' + args.store.slug,
386					store: args.store.slug,
387					post_id: args.post_id,
388				},
389			}).done( function( response ) {
390
391				$this.css( 'opacity', 1 );
392				$this.removeClass( 'jet-store-processing' );
393
394				if ( response.success ) {
395
396					if ( ! isDataStoreBtn ) {
397						$this.addClass( 'is-hidden' );
398					}
399
400					$( '.jet-add-to-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() {
401						JetEngine.switchDataStoreStatus( $( this ), true );
402					} );
403
404					$( '.jet-data-store-link.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() {
405						JetEngine.switchDataStoreStatus( $( this ), true );
406					} );
407
408					JetEngine.dataStoreSyncListings( args );
409
410					if ( args.remove_from_listing ) {
411						$this.closest( '.jet-listing-grid__item[data-post="' + args.post_id + '"]' ).remove();
412					}
413
414					if ( response.data.fragments ) {
415						$.each( response.data.fragments, function( selector, value ) {
416							$( selector ).html( value );
417						} );
418					}
419
420					$( document ).trigger( 'jet-engine-data-stores-on-remove', args );
421
422				} else {
423					alert( response.data.message );
424				}
425
426				return response;
427
428			} ).done( function( response ) {
429
430				if ( args.remove_from_listing ) {
431					$this.closest( '.jet-listing-grid__item' ).remove();
432				}
433
434				if ( response.success ) {
435					$( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( response.data.count );
436				}
437
438			} ).fail( function( jqXHR, textStatus, errorThrown ) {
439				$this.css( 'opacity', 1 );
440				$this.removeClass( 'jet-store-processing' );
441				alert( errorThrown );
442			} );
443
444		},
445
446		triggerPopup: function( popupID, isJetEngine, postID ) {
447
448			if ( ! popupID ) {
449				return;
450			}
451
452			var popupData = {
453				popupId: 'jet-popup-' + popupID,
454			};
455
456			if ( isJetEngine ) {
457				popupData.isJetEngine = true;
458				popupData.postId      = postID;
459			}
460
461			$( window ).trigger( {
462				type: 'jet-popup-open-trigger',
463				popupData: popupData
464			} );
465
466		},
467
468		dataStoreSyncListings: function( args ) {
469			if ( ! args.synch_id || typeof args.synch_id !== 'string' ) {
470				return;
471			}
472
473			const ids = args.synch_id.split( /[\s,]+/ ).map( ( id ) => id.replace( /\s/, '' ) ).filter( ( id ) => !! id );
474
475			ids.forEach( function ( id ) {
476				let $container     = $( '#' + id ),
477				    $elemContainer = $container.find( '> .elementor-widget-container' ),
478				    $items         = $container.find( '.jet-listing-grid__items' ),
479				    posts          = [],
480				    nav            = $items.data( 'nav' ) || {},
481				    query          = nav.query || {},
482					postID         = window.elementorFrontendConfig?.post?.id || 0;
483
484				nav = JetEngine.ensureJSON( nav );
485
486				// Context Bricks
487				if ( $container.hasClass( 'brxe-jet-engine-listing-grid' ) ) {
488					postID = window.bricksData.postId;
489				}
490				
491				// Context Gutenberg
492				if ( $container.hasClass( 'jet-listing-grid--blocks' )) {
493					postID = JetEngineSettings.post_id;
494				}
495
496				if ( args?.store?.is_front && Object.keys( query ).length ) {
497					let store = JetEngineStores[ args.store.type ];
498
499					posts = store.getStore( args.store.slug );
500
501					if ( ! posts.length ) {
502						posts = [ 'is-front', args.store.type, args.store.slug ];
503					}
504
505					query.post__in = posts;
506					query.is_front_store = true;
507				}
508
509				let options = {
510					handler: 'get_listing',
511					container: $elemContainer.length ? $elemContainer : $container,
512					masonry: false,
513					slider: false,
514					append: false,
515					query: query,
516					widgetSettings: nav.widget_settings,
517					postID: postID,
518					elementID: $container.data( 'id' ),
519				};
520
521				JetEngine.ajaxGetListing( options, function( response ) {
522					JetEngine.widgetListingGrid( $container );
523				} );
524			} );
525		},
526
527		addToStore: function( event ) {
528
529			event.preventDefault();
530			event.stopPropagation();
531
532			var $this = $( this ),
533				args  = $this.data( 'args' );
534
535			args = JetEngine.ensureJSON( args );
536
537			if ( $this.hasClass( 'in-store' ) ) {
538				if ( args.popup ) {
539					JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id );
540				} else if ( '_blank' === $this.attr( 'target' ) ) {
541					window.open( $this.attr( 'href' ) );
542				} else {
543					window.location = $this.attr( 'href' );
544				}
545				return;
546			}
547
548			if ( args.store.is_front ) {
549
550				var store = JetEngineStores[ args.store.type ],
551					count = 0;
552
553				if ( ! store ) {
554					return;
555				}
556
557				if ( store.inStore( args.store.slug, '' + args.post_id ) ) {
558					var storePosts = store.getStore( args.store.slug );
559					count = storePosts.length;
560				} else {
561
562					count = store.addToStore( args.store.slug, args.post_id, args.store.size );
563
564					if ( false === count ) {
565						return;
566					}
567
568				}
569
570				if ( args.popup ) {
571					JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id );
572				}
573
574				JetEngine.switchDataStoreStatus( $this );
575				$( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( count );
576				$( '.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).removeClass( 'is-hidden' );
577
578				JetEngine.dataStoreSyncListings( args );
579
580				$( document ).trigger( 'jet-engine-data-stores-on-add', args );
581
582				return;
583			}
584
585			if ( $this.hasClass( 'jet-store-processing' ) ) {
586				return;
587			}
588
589			$this.css( 'opacity', 0.3 );
590			$this.addClass( 'jet-store-processing' );
591
592			$( document ).trigger( 'jet-engine-on-add-to-store', [ $this, args ] );
593
594			$.ajax({
595				url: JetEngineSettings.ajaxurl,
596				type: 'POST',
597				dataType: 'json',
598				data: {
599					action: 'jet_engine_add_to_store_' + args.store.slug,
600					store: args.store.slug,
601					post_id: args.post_id,
602				},
603			}).done( function( response ) {
604
605				$this.css( 'opacity', 1 );
606				$this.removeClass( 'jet-store-processing' );
607
608				if ( response.success ) {
609
610					JetEngine.switchDataStoreStatus( $this );
611					$( '.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).removeClass( 'is-hidden' );
612
613					if ( response.data.fragments ) {
614						$.each( response.data.fragments, function( selector, value ) {
615							$( selector ).html( value );
616						} );
617					}
618
619					JetEngine.dataStoreSyncListings( args );
620
621					if ( args.popup ) {
622						JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id );
623					}
624
625				} else {
626					alert( response.data.message );
627				}
628
629				$( document ).trigger( 'jet-engine-data-stores-on-add', args );
630
631				return response;
632
633			} ).done( function( response ) {
634
635				if ( response.success ) {
636					$( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( response.data.count );
637				}
638
639			} ).fail( function( jqXHR, textStatus, errorThrown ) {
640				$this.css( 'opacity', 1 );
641				$this.removeClass( 'jet-store-processing' );
642				alert( errorThrown );
643			} );
644
645		},
646
647		switchDataStoreStatus: function( $item, toInitial ) {
648
649			var isDataStoreLink = $item.hasClass( 'jet-data-store-link' ),
650				$label = $item.find( '.jet-listing-dynamic-link__label, .jet-data-store-link__label' ),
651				$icon  = $item.find( '.jet-listing-dynamic-link__icon, .jet-data-store-link__icon' ),
652				args   = $item.data( 'args' ),
653				replaceLabel,
654				replaceURL,
655				replaceIcon;
656
657			args = JetEngine.ensureJSON( args );
658
659			toInitial = toInitial || false;
660
661			if ( isDataStoreLink ) {
662
663				switch ( args.action_after_added ) {
664					case 'remove_from_store':
665
666						if ( toInitial ) {
667							$item.addClass( 'jet-add-to-store' );
668							$item.removeClass( 'jet-remove-from-store' );
669
670							$item.removeClass( 'in-store' );
671						} else {
672							$item.addClass( 'jet-remove-from-store' );
673							$item.removeClass( 'jet-add-to-store' );
674
675							$item.addClass( 'in-store' );
676
677						}
678
679						break;
680
681					case 'hide':
682
683						if ( toInitial ) {
684							$item.removeClass( 'is-hidden' );
685						} else {
686							$item.addClass( 'is-hidden' );
687						}
688
689						return;
690				}
691
692			}
693
694			if ( toInitial ) {
695				replaceLabel = args.label;
696				replaceIcon  = args.icon;
697				replaceURL   = '#';
698			} else {
699				replaceLabel = args.added_label;
700				replaceIcon  = args.added_icon;
701				replaceURL   = args.added_url;
702			}
703
704			if ( $label.length ) {
705				$label.replaceWith( replaceLabel );
706			} else {
707				$item.append( replaceLabel );
708			}
709
710			if ( $icon.length ) {
711				$icon.replaceWith( replaceIcon );
712			} else {
713				$item.prepend( replaceIcon );
714			}
715
716			if ( isDataStoreLink && 'remove_from_store' === args.action_after_added ) {
717				return;
718			}
719
720			$item.attr( 'href', replaceURL );
721
722			if ( toInitial ) {
723				$item.removeClass( 'in-store' );
724			} else if ( ! $item.hasClass( 'in-store' ) ) {
725				$item.addClass( 'in-store' );
726			}
727
728
729		},
730
731		showConfirmDeleteDialog: function( event ) {
732			event.preventDefault();
733			event.stopPropagation();
734
735			var $this = $( this );
736
737			if ( window.confirm( $this.data( 'delete-message' ) ) ) {
738				window.location = $this.attr( 'href' );
739			}
740
741		},
742
743		handleListingItemClick: function( event ) {
744
745			var url    = $( this ).data( 'url' ),
746				target = $( this ).data( 'target' ) || false;
747
748			if ( url ) {
749
750				event.preventDefault();
751
752				if ( window.elementorFrontend && window.elementorFrontend.isEditMode() ) {
753					return;
754				}
755
756				if ( -1 !== url.indexOf( '#jet-engine-action' ) ) {
757
758					JetEngine.customUrlActions.runAction( url );
759
760				} else {
761
762					if ( '_blank' === target ) {
763						window.open( url );
764						return;
765					}
766
767					window.location = url;
768				}
769			}
770
771		},
772
773		customUrlActions: {
774			selectorOnClick: 'a[href^="#jet-engine-action"][href*="event=click"]',
775			selectorOnHover: 'a[href^="#jet-engine-action"][href*="event=hover"], [data-url^="#jet-engine-action"][data-url*="event=hover"]',
776
777			init: function() {
778				var timeout = null;
779
780				$( document ).on( 'click.JetEngine', this.selectorOnClick, function( event ) {
781					event.preventDefault();
782					JetEngine.customUrlActions.actionHandler( event )
783				} );
784
785				$( document ).on( 'click.JetEngine', this.selectorOnHover, function( event ) {
786					if ( 'A' === event.currentTarget.nodeName ) {
787						event.preventDefault();
788					}
789				} );
790
791				$( document ).on( {
792					'mouseenter.JetEngine': function( event ) {
793
794						if ( timeout ) {
795							clearTimeout( timeout );
796						}
797
798						timeout = setTimeout( function() {
799							JetEngine.customUrlActions.actionHandler( event )
800						}, window.JetEngineSettings.hoverActionTimeout );
801					},
802					'mouseleave.JetEngine': function() {
803						if ( timeout ) {
804							clearTimeout( timeout );
805							timeout = null;
806						}
807					},
808				}, this.selectorOnHover );
809			},
810
811			actions: {},
812
813			addAction: function( name, callback ) {
814				this.actions[ name ] = callback;
815			},
816
817			actionHandler: function( event ) {
818				var url = $( event.currentTarget ).attr( 'href' ) || $( event.currentTarget ).attr( 'data-url' );
819
820				this.runAction( url );
821			},
822
823			runAction: function( url ) {
824				var queryParts = url.split( '&' ),
825					settings = {};
826
827				queryParts.forEach( function( item ) {
828					if ( -1 !== item.indexOf( '=' ) ) {
829						var pair = item.split( '=' );
830
831						settings[ pair[0] ] = decodeURIComponent( pair[1] );
832					}
833				} );
834
835				if ( ! settings.action ) {
836					return;
837				}
838
839				var actionCb = this.actions[ settings.action ];
840
841				if ( ! actionCb ) {
842					return;
843				}
844
845				actionCb( settings );
846			}
847		},
848
849		prepareJetPopup: function( popupData, widgetData, $scope ) {
850
851			var postId = null;
852
853			if ( widgetData['is-jet-engine'] ) {
854				popupData['isJetEngine'] = true;
855
856				var $gridItems     = $scope.closest( '.jet-listing-grid__items' ),
857					$gridItem      = $scope.closest( '.jet-listing-grid__item' ),
858					$calendarItem  = $scope.closest( '.jet-calendar-week__day-event' ),
859					$itemObject    = $scope.closest( '[data-item-object]' ),
860					filterProvider = false,
861					filterQueryId  = 'default';
862
863				if ( $gridItems.length ) {
864					popupData['listingSource'] = $gridItems.data( 'listing-source' );
865					popupData['listingId']     = $gridItems.data( 'listing-id' );
866					popupData['queryId']       = $gridItems.data( 'query-id' );
867				} else {
868
869					var $queryItems    = $scope.closest( '[data-query-id]' ),
870						$listingSource = $scope.closest( '[data-listing-source]' );
871
872					if ( $queryItems.length ) {
873						popupData['queryId'] = $queryItems.data( 'query-id' );
874					}
875
876					if ( $listingSource.length ) {
877						popupData['listingSource'] = $listingSource.data( 'listing-source' );
878					}
879				}
880
881				if ( $gridItem.length ) {
882					popupData['postId'] = $gridItem.data( 'post-id' );
883					filterProvider = 'jet-engine';
884				} else if ( $calendarItem.length ) {
885					popupData['postId'] = $calendarItem.data( 'post-id' );
886					filterProvider = 'jet-engine-calendar';
887				} else if ( $itemObject ) {
888					popupData['postId'] = $itemObject.data( 'item-object' );
889				} else if ( window.elementorFrontendConfig && window.elementorFrontendConfig.post ) {
890					popupData['postId'] = window.elementorFrontendConfig.post.id;
891				}
892
893				if ( window.JetEngineFormsEditor && window.JetEngineFormsEditor.hasEditor ) {
894					popupData['hasEditor'] = true;
895				}
896
897				// Add the filtered query to the popup data
898				if ( window.JetSmartFilters ) {
899
900					switch ( filterProvider ) {
901						case 'jet-engine':
902							var nav = $gridItems.data( 'nav' );
903
904							if ( nav.widget_settings?._element_id ) {
905								filterQueryId = nav.widget_settings._element_id;
906							}
907							break;
908
909						case 'jet-engine-calendar':
910							var settings = $calendarItem.closest( '.jet-listing-calendar' ).data( 'settings' );
911
912							if ( settings._element_id ) {
913								filterQueryId = settings._element_id;
914							}
915							break;
916					}
917
918					filterProvider = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterProvider', filterProvider, $scope, widgetData );
919					filterQueryId  = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterQueryId', filterQueryId, $scope, widgetData );
920
921					if ( popupData.queryId && filterProvider
922						&& window.JetSmartFilters?.filterGroups?.[ filterProvider + '/' + filterQueryId ]?.currentQuery
923					) {
924						popupData['filtered_query'] = window.JetSmartFilters.filterGroups[ filterProvider + '/' + filterQueryId ].currentQuery;
925					}
926				}
927
928			}
929
930			return popupData;
931
932		},
933
934		showCalendarEvent: function( event ) {
935
936			var $this       = $( this ),
937				$day        = $this.closest( '.jet-calendar-week__day' ),
938				$week       = $day.closest( '.jet-calendar-week' ),
939				$events     = $day.find( '.jet-calendar-week__day-content' ),
940				activeClass = 'calendar-event-active';
941
942			if ( $day.hasClass( activeClass ) ) {
943				$day.removeClass( activeClass );
944				JetEngine.activeCalendarDay.remove();
945				JetEngine.activeCalendarDay = null;
946				return;
947			}
948
949			if ( JetEngine.activeCalendarDay ) {
950				JetEngine.activeCalendarDay.remove();
951				$( '.' + activeClass ).removeClass( activeClass );
952				JetEngine.activeCalendarDay = null;
953			}
954
955			$day.addClass( 'calendar-event-active' );
956
957			JetEngine.activeCalendarDay = $( '<tr class="jet-calendar-week"><td colspan="7" class="jet-calendar-week__day jet-calendar-week__day-mobile"><div class="jet-calendar-week__day-mobile-event">' + $events.html() + '</div></td></tr>' );
958
959			// Need for re-init popup events
960			JetEngine.activeCalendarDay.find( '.jet-popup-attach-event-inited' ).removeClass( 'jet-popup-attach-event-inited' );
961			JetEngine.initElementsHandlers( JetEngine.activeCalendarDay );
962
963			JetEngine.activeCalendarDay.insertAfter( $week );
964
965		},
966
967		widgetListingGrid: function( $scope ) {
968
969			var widgetID    = $scope.closest( '.elementor-widget' ).data( 'id' ),
970				$wrapper    = $scope.find( '.jet-listing-grid' ).first(),
971				hasLazyLoad = $wrapper.hasClass( 'jet-listing-grid--lazy-load' ),
972				$listing    = $scope.find( '.jet-listing-grid__items' ).first(),
973				$slider     = $listing.parent( '.jet-listing-grid__slider' ),
974				$masonry    = $listing.hasClass( 'jet-listing-grid__masonry' ) ? $listing : false,
975				navSettings = $listing.data( 'nav' ),
976				masonryGrid = false,
977				listingType = 'elementor';
978
979			navSettings = JetEngine.ensureJSON( navSettings );
980
981			if ( hasLazyLoad ) {
982
983				var lazyLoadOptions = $wrapper.data( 'lazy-load' ),
984					widgetSettings = {},
985					$container = $scope.find( '.elementor-widget-container' );
986
987				// Get widget settings from `elementorFrontend` in Editor.
988				if ( window.elementorFrontend && window.elementorFrontend.isEditMode()
989					&& $wrapper.closest( '.elementor[data-elementor-type]' ).hasClass( 'elementor-edit-mode' )
990				) {
991					widgetSettings = JetEngine.getEditorElementSettings( $scope.closest( '.elementor-widget' ) );
992					widgetID       = false; // for avoid get widget settings from document in editor
993				}
994
995				if ( ! $container.length ) {
996					$container = $scope;
997					widgetSettings = $scope.data( 'widget-settings' );
998				}
999
1000				if ( ! widgetID ) {
1001					widgetID    = $scope.data( 'element-id' );
1002					listingType = $scope.data( 'listing-type' );
1003				}
1004
1005				JetEngine.lazyLoadListing( {
1006					container:      $container,
1007					elementID:      widgetID,
1008					postID:         lazyLoadOptions.post_id,
1009					queriedID:      lazyLoadOptions.queried_id || false,
1010					offset:         lazyLoadOptions.offset || '0px',
1011					query:          lazyLoadOptions.query || {},
1012					listingType:    listingType,
1013					widgetSettings: widgetSettings,
1014					extraProps:     lazyLoadOptions.extra_props || false,
1015				} );
1016
1017				return;
1018			}
1019
1020			if ( $slider.length ) {
1021				JetEngine.initSlider( $slider );
1022			}
1023
1024			if ( $masonry && $masonry.length ) {
1025
1026				JetEngine.initMasonry( $masonry );
1027
1028				/* Keep masonry re-init for Bricks */
1029				if ( $scope.hasClass( 'brxe-jet-engine-listing-grid' ) ) {
1030					$( window ).on( 'load', function() {
1031						JetEngine.runMasonry( $masonry );
1032					} );
1033				}
1034
1035			}
1036
1037			if ( navSettings && navSettings.enabled ) {
1038
1039				JetEngine.loadMoreListing( {
1040					container: $listing,
1041					settings:  navSettings,
1042					masonry:   $masonry,
1043					slider:    $slider,
1044				} );
1045
1046			}
1047
1048			// Init elements handlers in editor.
1049			if ( window.elementorFrontend && window.elementorFrontend.isEditMode()
1050				&& $wrapper.closest( '.elementor-element-edit-mode' ).length
1051			) {
1052				JetEngine.initElementsHandlers( $wrapper );
1053			}
1054
1055		},
1056
1057		initMasonry: function( $masonry, masonrySettings ) {
1058			imagesLoaded( $masonry, function() {
1059				JetEngine.runMasonry( $masonry, masonrySettings );
1060			} );
1061		},
1062
1063		runMasonry: function( $masonry, masonrySettings ) {
1064			var defaultSettings = {
1065				itemSelector: '> .jet-listing-grid__item',
1066				columnsKey:   'columns',
1067			};
1068
1069			masonrySettings = masonrySettings || {};
1070			masonrySettings = $.extend( {}, defaultSettings, masonrySettings );
1071
1072			var $eWidget     = $masonry.closest( '.elementor-widget' ),
1073				$items       = $( masonrySettings.itemSelector, $masonry ),
1074				options      = $masonry.data( 'masonry-grid-options' ) || {};
1075
1076			options = JetEngine.ensureJSON( options );
1077
1078			// Reset masonry
1079			$items.css( {
1080				marginTop: ''
1081			} );
1082
1083			// Bricks margin
1084			const { gap } = options;
1085			let margin = null;
1086
1087			if ( gap ) {
1088				margin = {
1089					x: +gap.horizontal,
1090					y: +gap.vertical,
1091				};
1092			}
1093
1094			var args = {
1095				container: $masonry[0],
1096				margin: margin ? margin : 0,
1097			};
1098
1099			if ( $eWidget.length ) {
1100				var settings     = JetEngine.getElementorElementSettings( $eWidget ),
1101					breakpoints  = {},
1102					eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints,
1103					columnsKey   = masonrySettings.columnsKey;
1104
1105				args.columns = settings[columnsKey + '_widescreen'] ? +settings[columnsKey + '_widescreen'] : +settings[columnsKey];
1106
1107				Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) {
1108
1109					if ( settings[columnsKey + '_' + breakpointName] ) {
1110						if ( 'widescreen' === breakpointName ) {
1111							breakpoints[eBreakpoints[breakpointName].value - 1] = +settings[columnsKey];
1112						} else {
1113							breakpoints[eBreakpoints[breakpointName].value] = +settings[columnsKey + '_' + breakpointName];
1114						}
1115					}
1116
1117				} );
1118
1119				args.breakAt = breakpoints;
1120
1121			} else {
1122				args.columns = options.columns.desktop;
1123				args.breakAt = {
1124					1025: options.columns.tablet,
1125					768:  options.columns.mobile,
1126				};
1127			}
1128
1129			var masonryInstance = Macy( args );
1130
1131			masonryInstance.runOnImageLoad( function () {
1132				masonryInstance.recalculate( true );
1133			}, true );
1134
1135			// Event to recalculate current masonry listings.
1136			$masonry.on( 'jet-engine/listing/recalculate-masonry-listing', function() {
1137				masonryInstance.runOnImageLoad( function () {
1138					masonryInstance.recalculate( true );
1139				}, true );
1140			} );
1141
1142			// Event to recalculate all masonry listings.
1143			$( document ).on( 'jet-engine/listing/recalculate-masonry', function() {
1144				masonryInstance.recalculate( true );
1145			} );
1146
1147		},
1148
1149		ajaxGetListing: function( options, doneCallback, failCallback ) {
1150
1151			var container = options.container || false,
1152				handler = options.handler || false,
1153				masonry = options.masonry || false,
1154				slider = options.slider || false,
1155				append = options.append || false,
1156				query = options.query || {},
1157				widgetSettings = options.widgetSettings || {},
1158				postID = options.postID || false,
1159				queriedID = options.queriedID || false,
1160				elementID = options.elementID || false,
1161				page = options.page || 1,
1162				preventCSS = options.preventCSS || false,
1163				listingType = options.listingType || false,
1164				extraProps = options.extraProps || false,
1165				isEditMode = window.elementorFrontend && window.elementorFrontend.isEditMode();
1166
1167			doneCallback = doneCallback || function( response ) {};
1168
1169			if ( ! container|| ! handler ) {
1170				return;
1171			}
1172
1173			if ( ! preventCSS ) {
1174				container.css({
1175					pointerEvents: 'none',
1176					opacity: '0.5',
1177					cursor: 'default',
1178				});
1179			}
1180
1181			var requestData = {
1182					action: 'jet_engine_ajax',
1183					handler: handler,
1184					query: query,
1185					widget_settings: widgetSettings,
1186					page_settings: {
1187						post_id: postID,
1188						queried_id: queriedID,
1189						element_id: elementID,
1190						page: page,
1191					},
1192					listing_type: listingType,
1193					isEditMode: isEditMode,
1194					addedPostCSS: JetEngine.addedPostCSS
1195				};
1196
1197			if ( extraProps ) {
1198				Object.assign( requestData, extraProps );
1199			}
1200
1201			$.ajax({
1202				url: JetEngineSettings.ajaxlisting,
1203				type: 'POST',
1204				dataType: 'json',
1205				data: requestData,
1206			}).done( function( response ) {
1207
1208				// container.removeAttr( 'style' );
1209
1210				// Manual reset container style to prevent removal of masonry styles.
1211				if ( !preventCSS ) {
1212					container.css( {
1213						pointerEvents: '',
1214						opacity: '',
1215						cursor: '',
1216					} );
1217				}
1218
1219				if ( response.success ) {
1220
1221					JetEngine.enqueueAssetsFromResponse( response );
1222
1223					container.data( 'page', page );
1224
1225					var $html = $( response.data.html );
1226
1227					JetEngine.initFrontStores( $html );
1228
1229					if ( slider && slider.length ) {
1230
1231						var $slider = slider.find( '> .jet-listing-grid__items' );
1232
1233						if ( ! $slider.hasClass( 'slick-initialized' ) ) {
1234
1235							if ( append ) {
1236								container.append( $html );
1237							} else {
1238								container.html( $html );
1239							}
1240
1241							var itemsCount = container.find( '> .jet-listing-grid__item' ).length;
1242
1243							slider.addClass( 'jet-listing-grid__slider' );
1244							JetEngine.initSlider( slider, { itemsCount: itemsCount } );
1245
1246						} else {
1247							$html.each( function( index, el ) {
1248								$slider.slick( 'slickAdd', el );
1249							});
1250						}
1251
1252					} else {
1253
1254						if ( append ) {
1255							container.append( $html );
1256						} else {
1257							container.html( $html );
1258						}
1259
1260						if ( masonry && masonry.length ) {
1261							//JetEngine.initMasonry( masonry );
1262							masonry.trigger( 'jet-engine/listing/recalculate-masonry-listing' );
1263						}
1264
1265					}
1266
1267					// Re-init Bricks scripts
1268					JetEngine.reinitBricksScripts();
1269
1270					Promise.all( JetEngine.assetsPromises ).then( function() {
1271						JetEngine.initElementsHandlers( $html );
1272						JetEngine.assetsPromises = [];
1273					} );
1274
1275					if ( response.data.fragments ) {
1276						for ( var selector in response.data.fragments ) {
1277							var $selector = $( selector );
1278
1279							if ( $selector.length ) {
1280								$selector.html( response.data.fragments[ selector ] );
1281							}
1282						}
1283					}
1284				}
1285
1286				$( document ).trigger( 'jet-engine/listing/ajax-get-listing/done', [ $html, options ] );
1287
1288			} ).done( doneCallback ).fail( function() {
1289				container.removeAttr( 'style' );
1290				if ( failCallback ) {
1291					failCallback.call();
1292				}
1293
1294			} );
1295
1296		},
1297
1298		loadMoreListing: function( args ) {
1299
1300			var instance = {
1301
1302				setup: function() {
1303					this.container = args.container;
1304					this.masonry   = args.masonry;
1305					this.slider    = args.slider;
1306					this.settings  = args.settings;
1307
1308					this.wrapper = this.container.closest( '.jet-listing-grid' );
1309
1310					this.type      = this.settings.type || 'click';
1311					this.page      = parseInt( this.container.data( 'page' ), 10 ) || 0;
1312					this.pages     = parseInt( this.container.data( 'pages' ), 10 ) || 0;
1313					this.queriedID = this.container.data( 'queried-id' ) || false;
1314				},
1315
1316				init: function() {
1317
1318					this.setup();
1319
1320					switch ( this.type ) {
1321						case 'click':
1322
1323							this.handleMore();
1324
1325							break;
1326
1327						case 'scroll':
1328
1329							if ( ( ! window.elementorFrontend || ! window.elementorFrontend.isEditMode() ) && ! this.slider.length ) {
1330								this.handleInfiniteScroll();
1331							}
1332
1333							break;
1334					}
1335				},
1336
1337				handleMore: function() {
1338
1339					if ( ! this.settings.more_el ) {
1340						return;
1341					}
1342
1343					var self    = this,
1344						$button = $( this.settings.more_el );
1345
1346					if ( ! $button.length ) {
1347						return;
1348					}
1349
1350					if ( ! this.pages || this.page === this.pages && ! window.elementor ) {
1351						$button.css( 'display', 'none' );
1352					} else {
1353						$button.removeAttr( 'style' );
1354					}
1355
1356					$( document )
1357						.off( 'click', this.settings.more_el )
1358						.on( 'click', this.settings.more_el, function( event ) {
1359							event.preventDefault();
1360
1361							if ( ! self.pages || self.page >= self.pages) {
1362								$button.css( 'display', 'none' );
1363								return;
1364							}
1365
1366							$button.css( {
1367								pointerEvents: 'none',
1368								opacity: '0.5',
1369								cursor: 'default',
1370							} );
1371
1372							self.ajaxGetItems( function( response ) {
1373									$button.removeAttr( 'style' );
1374
1375									if ( response.success && self.page === self.pages ) {
1376										$button.css( 'display', 'none' );
1377									}
1378								}, function() {
1379									$button.button.removeAttr( 'style' );
1380								}
1381							);
1382						} );
1383				},
1384
1385				handleInfiniteScroll: function() {
1386
1387					if ( this.container.hasClass( 'jet-listing-not-found' ) ) {
1388						return;
1389					}
1390
1391					if ( ! this.pages || this.page === this.pages ) {
1392						return;
1393					}
1394
1395					var self     = this,
1396						$trigger = this.wrapper.find( '.jet-listing-grid__loader' ),
1397						offset   = '0%';
1398
1399					if ( ! $trigger.length ) {
1400						$trigger = $( '<div>', {
1401							class: 'jet-listing-grid__loading-trigger'
1402						} );
1403
1404						this.wrapper.append( $trigger );
1405					}
1406
1407					// Prepare offset value.
1408					if ( this.settings.widget_settings && this.settings.widget_settings.load_more_offset ) {
1409						var offsetValue = this.settings.widget_settings.load_more_offset;
1410
1411						switch ( typeof offsetValue ) {
1412							case 'object':
1413								var size = offsetValue.size ? offsetValue.size : '0',
1414									unit = offsetValue.unit ? offsetValue.unit : 'px';
1415
1416								offset = size + unit;
1417								break;
1418
1419							case 'number':
1420							case 'string':
1421								offset = offsetValue + 'px';
1422								break;
1423						}
1424					}
1425
1426					var observer = new IntersectionObserver(
1427						function( entries, observer ) {
1428
1429							if ( entries[0].isIntersecting ) {
1430
1431								self.ajaxGetItems( function() {
1432
1433									// Re-init observer if the last page is not loaded
1434									if ( self.page !== self.pages ) {
1435										setTimeout( function() {
1436											observer.observe( entries[0].target );
1437										}, 250 );
1438									}
1439
1440								} );
1441
1442								// Detach observer
1443								observer.unobserve( entries[0].target );
1444							}
1445						},
1446						{
1447							rootMargin: '0% 0% ' + offset + ' 0%',
1448						}
1449					);
1450
1451					observer.observe( $trigger[0] );
1452				},
1453
1454				ajaxGetItems: function( doneCallback, failCallback ) {
1455					var self = this;
1456
1457					this.page++;
1458
1459					this.wrapper.addClass( 'jet-listing-grid-loading' );
1460
1461					JetEngine.ajaxGetListing( {
1462							handler:        'listing_load_more',
1463							container:      this.container,
1464							masonry:        this.masonry,
1465							slider:         this.slider,
1466							append:         true,
1467							query:          this.settings.query,
1468							widgetSettings: this.settings.widget_settings,
1469							page:           this.page,
1470							queriedID:      this.queriedID,
1471							preventCSS:     !! this.wrapper.find( '.jet-listing-grid__loader' ).length, // Prevent CSS if listing has the loader.
1472						}, function( response ) {
1473
1474							JetEngine.lazyLoading = false;
1475							self.wrapper.removeClass( 'jet-listing-grid-loading' );
1476
1477							if ( doneCallback ) {
1478								doneCallback( response );
1479							}
1480
1481							$( document ).trigger( 'jet-engine/listing-grid/after-load-more', [args, response] );
1482
1483						}, function() {
1484
1485							JetEngine.lazyLoading = false;
1486							self.wrapper.removeClass( 'jet-listing-grid-loading' );
1487
1488							if ( failCallback ) {
1489								failCallback();
1490							}
1491
1492					} );
1493				},
1494			};
1495
1496			instance.init();
1497		},
1498
1499		lazyLoadListing: function( args ) {
1500
1501			var $wrapper = args.container.find( '.jet-listing-grid' ),
1502				observer = new IntersectionObserver(
1503					function( entries, observer ) {
1504
1505						if ( entries[0].isIntersecting ) {
1506
1507							JetEngine.lazyLoading = true;
1508
1509							if ( ! $wrapper.length ) {
1510								$wrapper = args.container;
1511							}
1512
1513							$wrapper.addClass( 'jet-listing-grid-loading' );
1514
1515							JetEngine.ajaxGetListing( {
1516								handler: 'get_listing',
1517								container: args.container,
1518								masonry: false,
1519								slider: false,
1520								append: false,
1521								elementID: args.elementID,
1522								postID: args.postID,
1523								queriedID: args.queriedID,
1524								query: args.query,
1525								widgetSettings: args.widgetSettings,
1526								listingType: args.listingType,
1527								preventCSS: true,
1528								extraProps: args.extraProps,
1529							}, function( response ) {
1530
1531								$wrapper.removeClass( 'jet-listing-grid-loading' );
1532
1533								var $widget = args.container.closest( '.elementor-widget' );
1534
1535								if ( ! $widget.length ) {
1536									$widget = args.container.closest( '.jet-listing-grid--blocks' );
1537								}
1538
1539								if ( ! $widget.length ) {
1540									$widget = args.container;
1541								}
1542
1543								if ( $widget.length ) {
1544									$widget.find( '.jet-listing-grid' ).first().removeClass( 'jet-listing-grid--lazy-load' );
1545								}
1546
1547								JetEngine.widgetListingGrid( $widget );
1548								JetEngine.loadFrontStoresItems( $widget );
1549								JetEngine.lazyLoading = false;
1550
1551								let needReInitFilters = false;
1552								let isFrontend = JetEngine.isFrontend();
1553
1554								if ( isFrontend && window.JetSmartFilterSettings ) {
1555
1556									if ( response.data.filters_data ) {
1557										$.each( response.data.filters_data, function( param, data ) {
1558											if ( 'extra_props' === param ) {
1559												window.JetSmartFilterSettings[ param ] = $.extend(
1560													{},
1561													window.JetSmartFilterSettings[ param ],
1562													data
1563												);
1564											} else {
1565												if ( window.JetSmartFilterSettings[ param ]['jet-engine'] ) {
1566													window.JetSmartFilterSettings[ param ]['jet-engine'] = $.extend(
1567														{},
1568														window.JetSmartFilterSettings[ param ]['jet-engine'],
1569														data
1570													);
1571												} else {
1572													window.JetSmartFilterSettings[ param ]['jet-engine'] = data;
1573												}
1574											}
1575										});
1576
1577										needReInitFilters = true;
1578									}
1579
1580									if ( response.data.indexer_data ) {
1581										const {
1582											provider = false,
1583											query = {}
1584										} = response.data.indexer_data;
1585
1586										window.JetSmartFilters.setIndexedData( provider, query );
1587									}
1588								}
1589
1590								// ReInit filters
1591								if ( needReInitFilters && window.JetSmartFilters ) {
1592									window.JetSmartFilters.reinitFilters();
1593								}
1594
1595								$( document ).trigger( 'jet-engine/listing-grid/after-lazy-load', [ args, response ] );
1596
1597							}, function() {
1598								JetEngine.lazyLoading = false;
1599
1600								if ( ! $wrapper.length ) {
1601									$wrapper = args.container;
1602								}
1603
1604								$wrapper.removeClass( 'jet-listing-grid-loading' );
1605							} );
1606
1607							// Detach observer after the first load the listing
1608							observer.unobserve( entries[0].target );
1609						}
1610					},
1611					{
1612						rootMargin: '0% 0% ' + args.offset + ' 0%'
1613					}
1614				);
1615
1616			observer.observe( args.container[0] );
1617		},
1618
1619		ensureJSON: function( maybeJSON ) {
1620
1621			if ( ! maybeJSON ) {
1622				return maybeJSON;
1623			}
1624
1625			if ( 'string' === typeof maybeJSON ) {
1626				console.log( maybeJSON );
1627				//maybeJSON = JSON.parse( maybeJSON );
1628			}
1629
1630			return maybeJSON;
1631
1632		},
1633
1634		initSlider: function( $slider, customOptions ) {
1635			var $eWidget    = $slider.closest( '.elementor-widget' ),
1636				options     = $slider.data( 'slider_options' ),
1637				windowWidth = $( window ).width(),
1638				tabletBP    = 1025,
1639				mobileBP    = 768,
1640				tabletSlides, mobileSlides, defaultOptions, slickOptions;
1641
1642			options = JetEngine.ensureJSON( options );
1643
1644			customOptions = customOptions || {};
1645
1646			options = $.extend( {}, options, customOptions );
1647
1648			if ( $eWidget.length ) {
1649
1650				var settings     = JetEngine.getElementorElementSettings( $eWidget ),
1651					responsive   = [],
1652					deviceMode   = elementorFrontend.getCurrentDeviceMode(),
1653					eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints;
1654
1655				options.slidesToShow = settings.columns_widescreen ? +settings.columns_widescreen : +settings.columns;
1656
1657				Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) {
1658
1659					if ( settings['columns_' + breakpointName] ) {
1660
1661						if ( 'widescreen' === breakpointName ) {
1662
1663							responsive.push( {
1664								breakpoint: eBreakpoints[breakpointName].value,
1665								settings: {
1666									slidesToShow: +settings['columns'],
1667								}
1668							} );
1669
1670						} else {
1671							var breakpointSettings = {
1672									breakpoint: eBreakpoints[breakpointName].value + 1,
1673									settings:   {
1674										slidesToShow: +settings['columns_' + breakpointName],
1675									}
1676								};
1677
1678							if ( options.slidesToScroll > breakpointSettings.settings.slidesToShow ) {
1679								breakpointSettings.settings.slidesToScroll = breakpointSettings.settings.slidesToShow;
1680							}
1681
1682							// if ( 'mobile' === breakpointName ) {
1683							// 	breakpointSettings.settings.slidesToScroll = 1;
1684							// }
1685
1686							responsive.push( breakpointSettings );
1687						}
1688					}
1689
1690				} );
1691
1692				options.responsive = responsive;
1693
1694			} else {
1695
1696				// Ensure we have at least some options to avoid errors
1697				if ( ! options.slidesToShow ) {
1698					options.slidesToShow = {
1699						desktop: 3,
1700						tablet: 1,
1701						mobile: 1,
1702					}
1703				}
1704
1705				if ( options.itemsCount <= options.slidesToShow.desktop && windowWidth >= tabletBP ) { // 1025 - ...
1706					$slider.removeClass( 'jet-listing-grid__slider' );
1707					return;
1708				} else if ( options.itemsCount <= options.slidesToShow.tablet && tabletBP > windowWidth && windowWidth >= mobileBP ) { // 768 - 1024
1709					$slider.removeClass( 'jet-listing-grid__slider' );
1710					return;
1711				} else if ( options.itemsCount <= options.slidesToShow.mobile && windowWidth < mobileBP ) { // 0 - 767
1712					$slider.removeClass( 'jet-listing-grid__slider' );
1713					return;
1714				}
1715
1716				if ( options.slidesToShow.tablet ) {
1717					tabletSlides = options.slidesToShow.tablet;
1718				} else {
1719					tabletSlides = 1 === options.slidesToShow.desktop ? 1 : 2;
1720				}
1721
1722				if ( options.slidesToShow.mobile ) {
1723					mobileSlides = options.slidesToShow.mobile;
1724				} else {
1725					mobileSlides = 1;
1726				}
1727
1728				options.slidesToShow = options.slidesToShow.desktop;
1729
1730				options.responsive = [
1731					{
1732						breakpoint: 1025,
1733						settings: {
1734							slidesToShow: tabletSlides,
1735							slidesToScroll: options.slidesToScroll > tabletSlides ? tabletSlides : options.slidesToScroll
1736						}
1737					},
1738					{
1739						breakpoint: 768,
1740						settings: {
1741							slidesToShow: mobileSlides,
1742							slidesToScroll: 1
1743						}
1744					}
1745				];
1746			}
1747
1748			defaultOptions = {
1749				customPaging: function( slider, i ) {
1750					return $( '<span />' ).text( i + 1 ).attr( 'role', 'tab' );
1751				},
1752				slide: '.jet-listing-grid__item',
1753				dotsClass: 'jet-slick-dots',
1754			};
1755
1756			slickOptions = $.extend( {}, defaultOptions, options );
1757
1758			var $sliderItems = $slider.find( '> .jet-listing-grid__items' );
1759
1760			if ( slickOptions.infinite ) {
1761				$sliderItems.on( 'init', function() {
1762					var $items        = $( this ),
1763						$clonedSlides = $( '> .slick-list > .slick-track > .slick-cloned.jet-listing-grid__item', $items );
1764
1765					if ( !$clonedSlides.length ) {
1766						return;
1767					}
1768
1769					JetEngine.initElementsHandlers( $clonedSlides );
1770
1771					if ( $slider.find('.bricks-lazy-hidden').length ) {
1772						bricksLazyLoad();
1773					}
1774				} );
1775			}
1776
1777			// Temporary solution issue with Lazy Load images + RTL on Chrome.
1778			// Remove after fix in Chrome.
1779			// See: https://github.com/Crocoblock/issues-tracker/issues/7552
1780			if ( slickOptions.rtl ) {
1781				$sliderItems.on( 'init', function() {
1782					var $items      = $( this ),
1783						$lazyImages = $( 'img[loading=lazy]', $items ),
1784						lazyImageObserver = new IntersectionObserver(
1785							function( entries, observer ) {
1786								entries.forEach( function( entry ) {
1787									if ( entry.isIntersecting ) {
1788										// If an image does not load, need to remove the `loading` attribute.
1789										if ( ! entry.target.complete ) {
1790											entry.target.removeAttribute( 'loading' );
1791										}
1792
1793										// Detach observer
1794										observer.unobserve( entry.target );
1795									}
1796								} );
1797							}
1798						);
1799
1800					$lazyImages.each( function() {
1801						const $img = $( this );
1802						lazyImageObserver.observe( $img[0] );
1803					} );
1804				} );
1805			}
1806
1807			if ( $sliderItems.hasClass( 'slick-initialized' ) ) {
1808				$sliderItems.slick( 'refresh', true );
1809				return;
1810			}
1811
1812			if ( slickOptions.variableWidth ) {
1813				slickOptions.slidesToShow = 1;
1814				slickOptions.slidesToScroll = 1;
1815				slickOptions.responsive = null;
1816			}
1817
1818			$sliderItems.slick( slickOptions );
1819		},
1820
1821		maybeReinitSlider: function( event, $scope ) {
1822			var $slider = $scope.find( '.jet-listing-grid__slider' );
1823
1824			if ( $slider.length ) {
1825				$slider.each( function() {
1826					JetEngine.initSlider( $( this ) );
1827				} );
1828			}
1829		},
1830
1831		widgetDynamicField: function( $scope ) {
1832
1833			var $slider = $scope.find( '.jet-engine-gallery-slider' );
1834
1835			if ( $slider.length ) {
1836				if ( $.isFunction( $.fn.imagesLoaded ) ) {
1837					$slider.imagesLoaded().always( function( instance ) {
1838
1839						var $eWidget = $slider.closest( '.elementor-widget' );
1840
1841						if ( $slider.hasClass( 'slick-initialized' ) ) {
1842							$slider.slick( 'refresh', true );
1843						} else {
1844							var atts = $slider.data( 'atts' );
1845
1846							atts = JetEngine.ensureJSON( atts );
1847
1848							if ( $eWidget.length ) {
1849								var settings     = JetEngine.getElementorElementSettings( $scope ),
1850									eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints,
1851									responsive   = [];
1852
1853								if ( settings.img_slider_cols || settings.img_slider_cols_widescreen ) {
1854									atts.slidesToShow = settings.img_slider_cols_widescreen ? +settings.img_slider_cols_widescreen : +settings.img_slider_cols;
1855								}
1856
1857								Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) {
1858
1859									if ( settings['img_slider_cols_' + breakpointName] ) {
1860
1861										if ( 'widescreen' === breakpointName ) {
1862
1863											responsive.push( {
1864												breakpoint: eBreakpoints[breakpointName].value,
1865												settings:   {
1866													slidesToShow: +settings['img_slider_cols'],
1867												}
1868											} );
1869
1870										} else {
1871											var breakpointSettings = {
1872												breakpoint: eBreakpoints[breakpointName].value + 1,
1873												settings:   {
1874													slidesToShow: +settings['img_slider_cols_' + breakpointName],
1875												}
1876											};
1877
1878											responsive.push( breakpointSettings );
1879										}
1880									}
1881
1882								} );
1883
1884								atts.responsive = responsive;
1885							}
1886
1887							$slider.slick( atts );
1888						}
1889					} );
1890				}
1891			}
1892
1893			$slider.on('init', function (event, slick) {
1894
1895				const slider = event.target;
1896
1897				if (!slider.classList.contains('jet-engine-gallery-lightbox')) {
1898					return;
1899				}
1900
1901				let lightbox = new PhotoSwipeLightbox({
1902					mainClass: 'brx',
1903					gallery: slider,
1904					children: 'a',
1905					showHideAnimationType: 'none',
1906					zoomAnimationDuration: false,
1907					pswpModule: PhotoSwipe5,
1908				});
1909
1910				lightbox.addFilter('numItems', numItems => slick.slideCount);
1911
1912				lightbox.addFilter('clickedIndex', function (clickedIndex, e) {
1913					const slide = e.target.closest('.slick-slide');
1914
1915					if (!slide) {
1916						return clickedIndex;
1917					}
1918
1919					if (clickedIndex >= slick.slideCount) {
1920						return clickedIndex % slick.slideCount;
1921					}
1922
1923					return clickedIndex;
1924				});
1925
1926				lightbox.addFilter('thumbEl', (thumbnail, itemData, index) => {
1927					return thumbnail;
1928				});
1929
1930				lightbox.addFilter('thumbBounds', (thumbBounds, itemData, index) => {
1931					return thumbBounds;
1932				});
1933
1934				lightbox.init();
1935			});
1936
1937			// Masonry init
1938			var $masonry = $scope.find( '.jet-engine-gallery-grid--masonry' );
1939
1940			if ( $masonry.length ) {
1941				JetEngine.initMasonry( $masonry, {
1942					columnsKey: 'img_columns',
1943					itemSelector: '> .jet-engine-gallery-grid__item',
1944				} );
1945			}
1946
1947		},
1948
1949		calendarCache: {
1950
1951			entries: {},
1952
1953			//introduced because Firefox does not have forEach method for iterators
1954			iterate: function( iterator, callback ) {
1955				if ( typeof iterator?.forEach === 'function' ) {
1956					iterator.forEach( callback );
1957				} else if ( typeof iterator?.next === 'function' ) {
1958					let next;
1959					while ( next = iterator.next(), ! next.done ) {
1960						callback.call( this, next.value );
1961					}
1962				}
1963			},
1964
1965			get: function ( cacheId, month ) {
1966				return JetEngine.calendarCache.entries[ cacheId ]?.get( month ) || false;
1967			},
1968	
1969			set: function ( cacheId, month, content, settings = {}, timestamp = false ) {
1970				if ( ! JetEngine.calendarCache.entries[ cacheId ] ) {
1971					JetEngine.calendarCache.entries[ cacheId ] = new Map();
1972				}
1973	
1974				if ( ! JetEngine.calendarCache.entries[ cacheId ].has( month )
1975					&& JetEngine.calendarCache.entries[ cacheId ].size > ( settings['max_cache'] ?? 12 ) - 1
1976				) {
1977					let deletedKey;
1978	
1979					const mapKeys = JetEngine.calendarCache.entries[ cacheId ].keys();
1980	
1981					if ( settings['__switch_direction'] < 0 ) {
1982						let maxDate = false;
1983	
1984						JetEngine.calendarCache.iterate(
1985							mapKeys,
1986							function ( key ) {
1987								const parsedDate = Date.parse( key );
1988		
1989								if ( ! maxDate || parsedDate > maxDate ) {
1990									maxDate = parsedDate;
1991									deletedKey = key;
1992								}
1993							}
1994						);
1995					} else {
1996						let minDate = false;
1997	
1998						JetEngine.calendarCache.iterate(
1999							mapKeys,
2000							function ( key ) {
2001								const parsedDate = Date.parse( key );
2002		
2003								if ( ! minDate || parsedDate < minDate ) {
2004									minDate = parsedDate;
2005									deletedKey = key;
2006								}
2007							}
2008						);
2009					}
2010	
2011					JetEngine.calendarCache.entries[ cacheId ].delete( deletedKey );
2012				}
2013	
2014				if ( ! timestamp ) {
2015					timestamp = Date.now();
2016				}
2017	
2018				JetEngine.calendarCache.entries[ cacheId ].set( month, [ content, timestamp ] );
2019			},
2020	
2021			update: function ( cacheId, month, content, settings = {} ) {
2022				let cached = JetEngine.calendarCache.get( cacheId, month );
2023				JetEngine.calendarCache.set( cacheId, month, content, settings, cached[1] ?? false );
2024			},
2025	
2026			deleteExpiredEntries: function ( cacheId, cacheTimeout ) {
2027				//delete possible orphaned caches
2028				for ( const cacheId in JetEngine.calendarCache.entries ) {
2029					if ( ! document.querySelector( `.jet-calendar[data-cache-id="${cacheId}"]` ) ) {
2030						delete JetEngine.calendarCache.entries[ cacheId ];
2031					}
2032				}
2033	
2034				if ( ! JetEngine.calendarCache.entries[ cacheId ] ) {
2035					return;
2036				}
2037	
2038				JetEngine.calendarCache.iterate(
2039					JetEngine.calendarCache.entries[ cacheId ].keys(),
2040					function ( month ) {
2041						if ( JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) {
2042							JetEngine.calendarCache.entries[ cacheId ].delete( month );
2043						}
2044					}
2045				);
2046			},
2047	
2048			isExpired: function ( cacheId, month, cacheTimeout ) {
2049				if ( cacheTimeout < 0 ) {
2050					return false;
2051				}
2052	
2053				const cached = JetEngine.calendarCache.get( cacheId, month );
2054	
2055				if ( ! cached || ! Array.isArray( cached ) ) {
2056					return true;
2057				}
2058	
2059				return ! cached[1] || cached[1] < Date.now() - cacheTimeout;
2060			},
2061	
2062			clear: function( e, $calendar ) {
2063				const cacheId = $calendar.data( 'cache-id' ) || false;
2064	
2065				if ( ! cacheId ) {
2066					return;
2067				}
2068	
2069				JetEngine.calendarCache.entries[ cacheId ] = new Map();
2070			},
2071
2072			modifyJetSmartFiltersSetiings: function( $widget, widgetType, monthData ) {
2073				if ( ! window.JetSmartFilterSettings || ! window.JetSmartFilterSettings.settings ) {
2074					return;
2075				}
2076
2077				monthData = monthData.split( ' ' );
2078
2079				const month = monthData[0],
2080				      year = monthData[1];
2081
2082				let widgetId;
2083
2084				switch ( widgetType ) {
2085					case 'block':
2086						widgetId = $widget.closest( '.jet-listing-calendar-block' )[0].id;
2087
2088						if ( ! widgetId ) {
2089							widgetId = 'default';
2090						}
2091
2092						if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ] ) {
2093							window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month;
2094							window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year;
2095						}
2096						
2097						break;
2098					case 'bricks':
2099						widgetId = $widget.data( 'element-id' );
2100
2101						if ( ! widgetId ) {
2102							break;
2103						}
2104
2105						for ( const id in window.JetSmartFilterSettings.settings['jet-engine-calendar'] ) {
2106							if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]._id === widgetId ) {
2107								window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_month'] = month;
2108								window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_year'] = year;
2109								break;
2110							}
2111						}
2112
2113						break;
2114					case 'elementor':
2115						widgetId = $widget.closest( '.elementor-widget-jet-listing-calendar' )[0].id;
2116
2117						if ( ! widgetId ) {
2118							widgetId = 'default';
2119						}
2120
2121						if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ] ) {
2122							window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month;
2123							window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year;
2124						}
2125
2126						break;
2127				}
2128			},
2129		},
2130
2131		selectCalendarMonth: function ( $event ) {
2132			let wrapper = this.closest( '.jet-calendar-caption__dates' );
2133
2134			if ( ! JetEngine.updateDateSelectLabels( wrapper ) ) {
2135				return;
2136			}
2137
2138			JetEngine.switchCalendarMonth.bind( wrapper )()
2139		},
2140
2141		updateDateSelectLabels: function( wrapper ) {
2142			let month = wrapper.querySelector( '.jet-calendar-caption__date-select.select-month' ),
2143			    year = wrapper.querySelector( '.jet-calendar-caption__date-select.select-year' );
2144
2145			if ( ! month || ! year ) {
2146				return false;
2147			}
2148
2149			let monthLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-month' ),
2150				yearLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-year' );
2151
2152			wrapper.setAttribute( 'data-month', month.value + ' ' + year.value );
2153
2154			const monthOption = month.querySelector( `option[value="${month.value}"]` ),
2155			      yearOption = year.querySelector( `option[value="${year.value}"]` );
2156
2157			monthLabel.innerHTML = monthOption.innerHTML;
2158			yearLabel.innerHTML = yearOption.innerHTML;
2159
2160			return true;
2161		},
2162
2163		switchCalendarMonth: function( $event ) {
2164
2165			var $this     = $( this ),
2166				$calendar = $this.closest( '.jet-calendar' ),
2167				$widget   = $calendar.closest( '.elementor-widget-container' ),
2168				settings  = $calendar.data( 'settings' ),
2169				post      = $calendar.data( 'post' ),
2170				month     = $this.data( 'month' );
2171
2172			settings = JetEngine.ensureJSON( settings );
2173
2174			if ( this.classList.contains( 'nav-link-prev' ) ) {
2175				settings['__switch_direction'] = -1;
2176			} else if ( this.classList.contains( 'nav-link-next' ) ) {
2177				settings['__switch_direction'] = 1;
2178			} else {
2179				settings['__switch_direction'] = 0;
2180			}
2181
2182			let widgetType = 'elementor';
2183
2184			// Context Gutenberg
2185			if ( ! $widget.length ) {
2186				$widget = $calendar.closest( '.jet-listing-calendar-block' );
2187				widgetType = 'block';
2188			}
2189
2190			// Context Bricks
2191			if ( ! $widget.length ) {
2192				$widget = $calendar.closest( '.brxe-jet-listing-calendar' )
2193				widgetType = 'bricks';
2194			}
2195
2196			JetEngine.calendarCache.modifyJetSmartFiltersSetiings( $widget, widgetType, month );
2197
2198			const cacheId = $calendar.data( 'cache-id' ) || false,
2199			      cacheTimeout = ( settings['cache_timeout'] ?? 0 ) * 1000;
2200
2201			if ( cacheId && cacheTimeout ) {
2202				
2203				JetEngine.calendarCache.deleteExpiredEntries( cacheId, cacheTimeout );
2204
2205				// Remove the 'listening' and 'brx-open' classes from all matched elements to prevent
2206				// reinitialization issues in the accordion.
2207				if ( window.bricksIsFrontend ) {
2208					$calendar.find('.accordion-item.listening, .brxe-accordion-nested > .listening')
2209						.removeClass('listening brx-open');
2210				}
2211
2212				JetEngine.calendarCache.update( cacheId, settings['prev_month'], $calendar.prop('outerHTML'), settings );
2213
2214				const cached = JetEngine.calendarCache.get( cacheId, month );
2215
2216				if ( cached?.length && cached[0] && ! JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) {
2217					let replacement = $( cached[0] );
2218					replacement.removeClass( 'jet-calendar-loading' );
2219					$calendar.replaceWith( replacement[0] );
2220					JetEngine.initElementsHandlers( $widget );
2221					JetEngine.updateDateSelectLabels( $widget[0] );
2222					// Re-init Bricks scripts
2223					JetEngine.reinitBricksScripts();
2224
2225					$( document ).trigger( 'jet-engine-request-calendar-cached', [ $widget ] );
2226
2227					return;
2228				}
2229			}
2230
2231			$calendar.addClass( 'jet-calendar-loading' );
2232
2233			JetEngine.currentRequest = {
2234				jet_engine_action: 'jet_engine_calendar_get_month',
2235				month: month,
2236				settings: settings,
2237				post: post,
2238			};
2239
2240			$( document ).trigger( 'jet-engine-request-calendar' );
2241
2242			$.ajax({
2243				url: JetEngineSettings.ajaxlisting,
2244				type: 'POST',
2245				dataType: 'json',
2246				data: JetEngine.currentRequest,
2247			}).done( function( response ) {
2248				if ( response.success ) {
2249					$calendar.replaceWith( response.data.content );
2250
2251					if ( cacheId && cacheTimeout ) {
2252						JetEngine.calendarCache.set( cacheId, month, response.data.content, settings );
2253					}
2254
2255					JetEngine.initElementsHandlers( $widget );
2256					// Re-init Bricks scripts
2257					JetEngine.reinitBricksScripts();
2258
2259					$( document ).trigger( 'jet-engine-request-calendar-done', [ $widget ] );
2260				}
2261				$calendar.removeClass( 'jet-calendar-loading' );
2262			} );
2263		},
2264
2265		initElementsHandlers: function( $selector ) {
2266
2267			// Actual init
2268			window.JetPlugins.init( $selector );
2269
2270			// Legacy Elementor-only init
2271			$selector.find( '[data-element_type]' ).each( function() {
2272
2273				var $this       = $( this ),
2274					elementType = $this.data( 'element_type' );
2275
2276				if ( !elementType ) {
2277					return;
2278				}
2279
2280				if ( ! window?.elementorFrontend?.hooks?.doAction ) {
2281					return;
2282				}
2283
2284				if ( 'widget' === elementType ) {
2285					elementType = $this.data( 'widget_type' );
2286					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
2287				}
2288
2289				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
2290				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
2291
2292			} );
2293
2294			if ( window.elementorFrontend ) {
2295				const elementorLazyLoad = new Event( "elementor/lazyload/observe" );
2296				document.dispatchEvent( elementorLazyLoad );
2297			}
2298
2299			if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) {
2300				window.JetPopupFrontend.initAttachedPopups( $selector );
2301			}
2302
2303		},
2304
2305		getElementorElementSettings: function( $scope ) {
2306
2307			if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) {
2308				return JetEngine.getEditorElementSettings( $scope );
2309			}
2310
2311			return $scope.data( 'settings' ) || {};
2312		},
2313
2314		getEditorElementSettings: function( $scope ) {
2315			var modelCID = $scope.data( 'model-cid' ),
2316				elementData;
2317
2318			if ( ! modelCID ) {
2319				return {};
2320			}
2321
2322			if ( ! window.elementorFrontend.hasOwnProperty( 'config' ) ) {
2323				return {};
2324			}
2325
2326			if ( ! window.elementorFrontend.config.hasOwnProperty( 'elements' ) ) {
2327				return {};
2328			}
2329
2330			if ( ! window.elementorFrontend.config.elements.hasOwnProperty( 'data' ) ) {
2331				return {};
2332			}
2333
2334			elementData = window.elementorFrontend.config.elements.data[ modelCID ];
2335
2336			if ( ! elementData ) {
2337				return {};
2338			}
2339
2340			return elementData.toJSON();
2341		},
2342
2343		debounce: function( threshold, callback ) {
2344			var timeout;
2345
2346			return function debounced( $event ) {
2347				function delayed() {
2348					callback.call( this, $event );
2349					timeout = null;
2350				}
2351
2352				if ( timeout ) {
2353					clearTimeout( timeout );
2354				}
2355
2356				timeout = setTimeout( delayed, threshold );
2357			};
2358		},
2359
2360		updateAddedStyles: function() {
2361			if ( window.JetEngineSettings && window.JetEngineSettings.addedPostCSS ) {
2362				$.each( window.JetEngineSettings.addedPostCSS, function( ind, cssID ) {
2363					JetEngine.addedStyles.push( 'elementor-post-' + cssID );
2364					JetEngine.addedPostCSS.push( cssID );
2365				} );
2366			}
2367		},
2368
2369		enqueueAssetsFromResponse: function( response ) {
2370			if ( response.data.scripts ) {
2371				JetEngine.enqueueScripts( response.data.scripts );
2372			}
2373
2374			if ( response.data.styles ) {
2375				JetEngine.enqueueStyles( response.data.styles );
2376			}
2377		},
2378
2379		enqueueScripts: function( scripts ) {
2380			$.each( scripts, function( handle, scriptHtml ) {
2381				JetEngine.enqueueScript( handle, scriptHtml )
2382			} );
2383		},
2384
2385		enqueueStyles: function( styles ) {
2386			$.each( styles, function( handle, styleHtml ) {
2387				JetEngine.enqueueStyle( handle, styleHtml )
2388			} );
2389		},
2390
2391		enqueueScript: function( handle, scriptHtml ) {
2392
2393			if ( -1 !== JetEngine.addedScripts.indexOf( handle ) ) {
2394				return;
2395			}
2396
2397			if ( ! scriptHtml ) {
2398				return;
2399			}
2400
2401			var selector = 'script[id="' + handle + '-js"]';
2402
2403			if ( $( selector ).length ) {
2404				return;
2405			}
2406
2407			//$( 'body' ).append( scriptHtml );
2408
2409			var scriptsTags = scriptHtml.match( /<script[\s\S]*?<\/script>/gm );
2410			
2411			if ( scriptsTags.length ) {
2412
2413				for ( var i = 0; i < scriptsTags.length; i++ ) {
2414
2415					JetEngine.assetsPromises.push(
2416						new Promise( function( resolve, reject ) {
2417
2418							var $tag = $( scriptsTags[i] );
2419
2420							if ( $tag[0].src ) {
2421
2422								var tag = document.createElement( 'script' );
2423
2424								tag.type   = $tag[0].type;
2425								tag.src    = $tag[0].src;
2426								tag.id     = $tag[0].id;
2427								tag.async  = false;
2428								tag.onload = function() {
2429									resolve();
2430								};
2431
2432								document.body.append( tag );
2433							} else {
2434								$( 'body' ).append( scriptsTags[i] );
2435								resolve();
2436							}
2437						} )
2438					);
2439				}
2440			}
2441
2442			JetEngine.addedScripts.push( handle );
2443		},
2444
2445		enqueueStyle: function( handle, styleHtml ) {
2446
2447			if ( -1 !== handle.indexOf( 'google-fonts' ) ) {
2448				JetEngine.enqueueGoogleFonts( handle, styleHtml );
2449				return;
2450			}
2451
2452			if ( -1 !== JetEngine.addedStyles.indexOf( handle ) ) {
2453				return;
2454			}
2455
2456			var selector = 'link[id="' + handle + '-css"],style[id="' + handle + '"]';
2457
2458			if ( $( selector ).length ) {
2459				return;
2460			}
2461
2462			$( 'head' ).append( styleHtml );
2463
2464			JetEngine.addedStyles.push( handle );
2465
2466			if ( -1 !== handle.indexOf( 'elementor-post' ) ) {
2467				var postID = handle.replace( 'elementor-post-', '' );
2468				JetEngine.addedPostCSS.push( postID );
2469			}
2470		},
2471
2472		enqueueGoogleFonts: function( handle, styleHtml ) {
2473
2474			var selector = 'link[id="' + handle + '-css"]';
2475
2476			if ( $( selector ).length ) {}
2477
2478			$( 'head' ).append( styleHtml );
2479		},
2480
2481		isFrontend: function () {
2482			// Check the Elementor
2483			if (typeof window.elementorFrontend !== 'undefined') {
2484				return !window.elementorFrontend.isEditMode();
2485			}
2486
2487			// Check the Bricks
2488			if (typeof window.bricksIsFrontend !== 'undefined') {
2489				return window.bricksIsFrontend;
2490			}
2491
2492			// If no builders are found, we assume it is frontend.
2493			return true;
2494		},
2495
2496		reinitBricksScripts: function() {
2497			if ( window.bricksIsFrontend ) {
2498				document.dispatchEvent(
2499					new CustomEvent("bricks/ajax/query_result/displayed")
2500				);
2501			}
2502		},
2503
2504		filters: ( function() {
2505
2506			var callbacks = {};
2507
2508			return {
2509
2510				addFilter: function( name, callback ) {
2511
2512					if ( ! callbacks.hasOwnProperty( name ) ) {
2513						callbacks[name] = [];
2514					}
2515
2516					callbacks[name].push(callback);
2517
2518				},
2519
2520				applyFilters: function( name, value, args ) {
2521
2522					if ( ! callbacks.hasOwnProperty( name ) ) {
2523						return value;
2524					}
2525
2526					if ( args === undefined ) {
2527						args = [];
2528					}
2529
2530					var container = callbacks[ name ];
2531					var cbLen     = container.length;
2532
2533					for (var i = 0; i < cbLen; i++) {
2534						if (typeof container[i] === 'function') {
2535							value = container[i](value, args);
2536						}
2537					}
2538
2539					return value;
2540				}
2541
2542			};
2543
2544		})()
2545
2546	};
2547
2548	$( window ).on( 'elementor/frontend/init', JetEngine.init );
2549
2550	window.JetEngine = JetEngine;
2551
2552	JetEngine.commonInit();
2553
2554	window.addEventListener( 'DOMContentLoaded', function() {
2555		setTimeout( () => JetEngine.initBlocks() );
2556		JetEngine.initDone = true;
2557	} );
2558
2559	window.jetEngineBricks = function() {
2560		JetEngine.initBricks();
2561	}
2562
2563	$( window ).trigger( 'jet-engine/frontend/loaded' );
2564
2565}( 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.