PageSourceSearch

https://humco.ai/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.3.1

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