PageSourceSearch

https://surekhaexports.com/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.1.4

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