PageSourceSearch

https://www.herculepro.com/wp-content/plugins/jet-engine/assets/js/frontend.js

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