PageSourceSearch

https://hotelmissblanche.nl/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.4.0

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