PageSourceSearch

https://urist-anyfriev.ru/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.5.6

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