PageSourceSearch

https://dentistforlife.net/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.1.0

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