PageSourceSearch

https://hblab.co.jp/wp-content/plugins/jet-engine/assets/js/frontend.js?ver=3.2.7

js hblab.co.jp collected 2026-10-05 18:06:28 UTC 57,351 bytes, 2,211 lines download raw bytes

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