PageSourceSearch

https://equiflamoveis.com.br/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.7.9.1

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