PageSourceSearch

https://www.wohnref-muenchen.de/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.6.7.1

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