PageSourceSearch

https://www.100daysofrealfood.com/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.2.5.2

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