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 JetEngine.commonEvents(); 24 25 $( window ).on( 'jet-popup/render-content/ajax/success', JetEngine.initStores ); 26 27 window.JetPlugins.hooks.addFilter( 28 'jet-popup.show-popup.data', 29 'JetEngine.popupData', 30 ( popupData, $popup, $triggeredBy ) => { 31 32 if ( ! $triggeredBy ) { 33 return popupData; 34 } 35 36 if ( $triggeredBy.data( 'popupIsJetEngine' ) ) { 37 popupData = JetEngine.prepareJetPopup( popupData, { 'is-jet-engine': true }, $triggeredBy ); 38 } 39 40 return popupData; 41 } 42 ); 43 44 JetEngine.initStores(); 45 JetEngine.customUrlActions.init(); 46 47 }, 48 49 commonEvents: function( $scope ) { 50 $scope = $scope || $( document ); 51 52 $scope 53 .on( 'jet-filter-content-rendered', JetEngine.calendarCache.clear ) 54 .on( 'change.JetEngine', '.jet-calendar-caption__date-select', JetEngine.selectCalendarMonth ) 55 .on( 'click.JetEngine', '.jet-calendar-nav__link', JetEngine.switchCalendarMonth ) 56 .on( 'click.JetEngine', '.jet-calendar-week__day-mobile-overlay', JetEngine.showCalendarEvent ) 57 .on( 'click.JetEngine', '.jet-listing-dynamic-link__link[data-delete-link="1"]', JetEngine.showConfirmDeleteDialog ) 58 .on( 'jet-filter-content-rendered', JetEngine.maybeReinitSlider ) 59 .on( 'click.JetEngine', '.jet-add-to-store', JetEngine.addToStore ) 60 .on( 'click.JetEngine', '.jet-remove-from-store', JetEngine.removeFromStore ) 61 .on( 'click.JetEngine', '.jet-engine-listing-overlay-wrap:not([data-url*="event=hover"])', JetEngine.handleListingItemClick ) 62 .on( 'jet-filter-content-rendered', JetEngine.filtersCompatibility ) 63 .on( 'click.JetEngine', '.jet-container[data-url]', JetEngine.handleContainerURL ) 64 .on( 'change.JetEngine', '.jet-listing-dynamic-link .qty', JetEngine.handleProductQuantityChange ); 65 }, 66 67 handleProductQuantityChange: function ( event ) { 68 event.preventDefault(); 69 event.stopPropagation(); 70 71 const $this = $( this ); 72 73 $this.closest( ".jet-listing-dynamic-link" ).find( ".jet-woo-add-to-cart" ).data( "quantity", $this.val() ).attr( "data-quantity", $this.val() ); 74 }, 75 76 handleContainerURL: function() { 77 var $this = $( this ), 78 url = $this.data( 'url' ), 79 target = $this.data( 'target' ); 80 81 if ( ! target ) { 82 window.location = url; 83 } else { 84 window.open( url, '_blank' ).focus(); 85 } 86 87 }, 88 89 filtersCompatibility: function( event, $provider, filtersInstance, providerType ) { 90 91 let providers = { 92 'jet-engine': true, 93 'jet-engine-calendar': true, 94 'jet-data-table': true, 95 }; 96 97 if ( ! providers[ providerType ] ) { 98 return; 99 } 100 101 /* 102 No need anymore to manually re-init the block. 103 JetSmartFilters automatically re-init blocks. 104 105 var $blocksListing = $provider.closest( '.jet-listing-grid--blocks' ); 106 107 if ( $blocksListing.length ) { 108 JetEngine.widgetListingGrid( $blocksListing ); 109 } 110 */ 111 112 if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) { 113 window.JetPopupFrontend.initAttachedPopups( $provider ); 114 } 115 }, 116 117 init: function() { 118 119 var widgets = { 120 'jet-listing-dynamic-field.default' : JetEngine.widgetDynamicField, 121 'jet-listing-grid.default': JetEngine.widgetListingGrid, 122 }; 123 124 $.each( widgets, function( widget, callback ) { 125 window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback ); 126 }); 127 128 // Re-init sliders in nested tabs 129 window.elementorFrontend.elements.$window.on( 130 'elementor/nested-tabs/activate', 131 ( event, content ) => { 132 const $content = $( content ); 133 134 setTimeout( () => { 135 JetEngine.maybeReinitSlider( event, $content ); 136 JetEngine.widgetDynamicField( $content ); 137 } ); 138 } 139 ); 140 141 window.elementorFrontend.hooks.addFilter( 142 'jet-popup/widget-extensions/popup-data', 143 JetEngine.prepareJetPopup 144 ); 145 146 window.JetPlugins.hooks.addFilter( 147 'jet-popup.show-popup.data', 148 'JetEngine.popupData', 149 ( popupData, $popup, $triggeredBy ) => { 150 151 if ( ! $triggeredBy ) { 152 return popupData; 153 } 154 155 if ( $triggeredBy.data( 'popupIsJetEngine' ) ) { 156 popupData = JetEngine.prepareJetPopup( popupData, { 'is-jet-engine': true }, $triggeredBy ); 157 } 158 159 return popupData; 160 } 161 ); 162 163 JetEngine.updateAddedStyles(); 164 }, 165 166 initBricks: function( $scope ) { 167 168 if ( window.bricksIsFrontend ) { 169 return; 170 } 171 172 $scope = $scope || $( 'body' ); 173 JetEngine.initBlocks( $scope ); 174 175 }, 176 177 initBlocks: function( $scope ) { 178 179 $scope = $scope || $( 'body' ); 180 181 window.JetPlugins.init( $scope, [ 182 { 183 block: 'jet-engine/listing-grid', 184 callback: JetEngine.widgetListingGrid 185 }, 186 { 187 block: 'jet-engine/dynamic-field', 188 callback: JetEngine.widgetDynamicField 189 } 190 ] ); 191
192 document.addEventListener('bricks/tabs/changed', (event) => { 193 const tabActivePane = event.detail?.activePane; 194 195 if (tabActivePane) { 196 const $content = jQuery(tabActivePane); 197 198 setTimeout(() => { 199 JetEngine.maybeReinitSlider(event, $content); 200 JetEngine.widgetDynamicField($content); 201 }, 50); 202 } 203 }); 204 }, 205 206 initFrontStores: function( $scope ) { 207 208 $scope = $scope || $( 'body' ); 209 210 $( '.jet-add-to-store.is-front-store', $scope ).each( function() { 211 212 var $this = $( this ), 213 args = $this.data( 'args' ), 214 store = JetEngineStores[ args.store.type ], 215 count = 0; 216 217 args = JetEngine.ensureJSON( args ); 218 219 if ( ! store ) { 220 return; 221 } 222 223 if ( store.inStore( args.store.slug, '' + args.post_id ) ) { 224 JetEngine.switchDataStoreStatus( $this ); 225 } 226 227 } ); 228 229 $( '.jet-remove-from-store.is-front-store', $scope ).each( function() { 230 231 var $this = $( this ), 232 args = $this.data( 'args' ), 233 store = JetEngineStores[ args.store.type ], 234 count = 0; 235 236 args = JetEngine.ensureJSON( args ); 237 238 if ( ! store ) { 239 return; 240 } 241 242 if ( ! store.inStore( args.store.slug, '' + args.post_id ) ) { 243 $this.addClass( 'is-hidden' ); 244 } else { 245 $this.removeClass( 'is-hidden' ); 246 } 247 248 } ); 249 250 }, 251 252 initStores: function() { 253 254 JetEngine.initFrontStores(); 255 256 $.each( JetEngineRegisteredStores, function( storeSlug, storeType ) { 257 258 var store = JetEngineStores[ storeType ], 259 storeData = null, 260 count = 0; 261 262 if ( ! store ) { 263 return; 264 } 265 266 storeData = store.getStore( storeSlug ); 267 268 if ( storeData && storeData.length ) { 269 count = storeData.length; 270 } 271 272 $( 'span.jet-engine-data-store-count[data-store="' + storeSlug + '"]' ).text( count ); 273 274 } ); 275 276 JetEngine.loadFrontStoresItems(); 277 278 }, 279 280 loadFrontStoresItems: function( $scope ) { 281 282 $scope = $scope || $( 'body' ); 283 284 $( '.jet-listing-not-found.jet-listing-grid__items', $scope ).each( function() { 285 286 var $this = $( this ), 287 nav = $this.data( 'nav' ), 288 isStore = $this.data( 'is-store-listing' ), 289 query = nav.query || {}; 290 291 nav = JetEngine.ensureJSON( nav ); 292 293 if ( query && query.post__in && query.post__in.length && 0 >= query.post__in.indexOf( 'is-front' ) ) { 294 295 var storeType = query.post__in[1], 296 storeSlug = query.post__in[2], 297 store = JetEngineStores[ storeType ], 298 posts = [], 299 $container = $this.closest( '.jet-listing-grid' ); 300 301 if ( ! store ) { 302 return; 303 } 304 305 //Context Gutenberg 306 if ( ! $container.length ) { 307 $container = $this.closest( '.jet-listing-grid--blocks' ); 308 } 309 310 // Context Bricks 311 if ( ! $container.length ) { 312 $container = $this.closest( '.brxe-jet-engine-listing-grid' ) 313 } 314 315 posts = store.getStore( storeSlug ); 316 317 if ( ! posts.length ) { 318 return; 319 } 320 321 query.front_store__in = posts; 322 query.is_front_store = true; 323 324 JetEngine.ajaxGetListing( { 325 handler: 'get_listing', 326 container: $container, 327 masonry: false, 328 slider: false, 329 append: false, 330 query: query, 331 widgetSettings: nav.widget_settings, 332 }, function( response ) { 333 JetEngine.widgetListingGrid( $container ); 334 } ); 335 336 } else if ( isStore ) { 337 $( document ).trigger( 'jet-listing-grid-init-store', $this ); 338 } 339 340 } ); 341 }, 342 343 dataStores: { 344 queues: {}, 345 getQueue: function( store ) { 346 if ( ! ( this.queues?.[ store ] instanceof Promise ) ) { 347 this.queues[ store ] = Promise.resolve(); 348 } 349 350 return this.queues[ store ]; 351 }, 352 addToQueue: function( store, callback ) { 353 this.queues[ store ] = this.getQueue( store ).then( callback ); 354 }, 355 }, 356 357 removeFromStore: function( event ) { 358 359 event.preventDefault(); 360 event.stopPropagation(); 361 362 var $this = $( this ), 363 args = $this.data( 'args' ), 364 isDataStoreBtn = $this.hasClass( 'jet-data-store-link' ); 365 366 args = JetEngine.ensureJSON( args ); 367 368 if ( args.store.is_front ) { 369 370 var store = JetEngineStores[ args.store.type ], 371 count = 0; 372 373 if ( ! store ) { 374 return; 375 } 376 377 if ( ! store.inStore( args.store.slug, '' + args.post_id ) ) { 378 var storePosts = store.getStore( args.store.slug ); 379 count = storePosts.length; 380 } else { 381 count = store.remove( args.store.slug, args.post_id ); 382 } 383 384 $( '.jet-add-to-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() { 385 JetEngine.switchDataStoreStatus( $( this ), true ); 386 } ); 387 388 $( '.jet-data-store-link.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() { 389 JetEngine.switchDataStoreStatus( $( this ), true ); 390 } ); 391 392 $( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( count ); 393 394 if ( args.remove_from_listing ) { 395 $this.closest( '.jet-listing-dynamic-post-' + args.post_id ).remove(); 396 } 397 398 JetEngine.dataStoreSyncListings( args ); 399 400 $( document ).trigger( 'jet-engine-data-stores-on-remove', args ); 401 402 return; 403 404 } 405 406 if ( $this.hasClass( 'jet-store-processing' ) ) { 407 return; 408 } 409 410 $this.css( 'opacity', 0.3 ); 411 $this.addClass( 'jet-store-processing' ); 412 413 JetEngine.dataStores.addToQueue( args.store.slug, () => { 414 return $.ajax({ 415 url: JetEngineSettings.ajaxurl, 416 type: 'POST', 417 dataType: 'json', 418 data: { 419 action: 'jet_engine_remove_from_store_' + args.store.slug, 420 store: args.store.slug, 421 post_id: args.post_id, 422 }, 423 }).done( function( response ) { 424 425 $this.css( 'opacity', 1 ); 426 $this.removeClass( 'jet-store-processing' ); 427 428 if ( response.success ) { 429 430 if ( ! isDataStoreBtn ) { 431 $this.addClass( 'is-hidden' ); 432 } 433 434 $( '.jet-add-to-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() { 435 JetEngine.switchDataStoreStatus( $( this ), true ); 436 } ); 437 438 $( '.jet-data-store-link.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).each( function() { 439 JetEngine.switchDataStoreStatus( $( this ), true ); 440 } ); 441 442 JetEngine.dataStoreSyncListings( args ); 443 444 if ( args.remove_from_listing ) { 445 $this.closest( '.jet-listing-grid__item[data-post="' + args.post_id + '"]' ).remove(); 446 } 447 448 if ( response.data.fragments ) { 449 $.each( response.data.fragments, function( selector, value ) { 450 $( selector ).html( value ); 451 } ); 452 } 453 454 $( document ).trigger( 'jet-engine-data-stores-on-remove', args ); 455 456 } else { 457 alert( response.data.message ); 458 } 459 460 return response; 461 462 } ).done( function( response ) { 463 464 if ( args.remove_from_listing ) { 465 $this.closest( '.jet-listing-grid__item' ).remove(); 466 } 467 468 if ( response.success ) { 469 $( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( response.data.count ); 470 } 471 472 } ).fail( function( jqXHR, textStatus, errorThrown ) { 473 $this.css( 'opacity', 1 ); 474 $this.removeClass( 'jet-store-processing' ); 475 alert( errorThrown ); 476 } ); 477 } ); 478 479 }, 480 481 triggerPopup: function( popupID, isJetEngine, postID ) { 482 483 if ( ! popupID ) { 484 return; 485 } 486 487 var popupData = { 488 popupId: 'jet-popup-' + popupID, 489 }; 490 491 if ( isJetEngine ) { 492 popupData.isJetEngine = true; 493 popupData.postId = postID; 494 } 495 496 $( window ).trigger( { 497 type: 'jet-popup-open-trigger', 498 popupData: popupData 499 } ); 500 501 }, 502 503 dataStoreSyncListings: function( args ) { 504 if ( ! args.synch_id || typeof args.synch_id !== 'string' ) { 505 return; 506 } 507 508 const ids = args.synch_id.split( /[\s,]+/ ).map( ( id ) => id.replace( /\s/, '' ) ).filter( ( id ) => !! id ); 509 510 ids.forEach( function ( id ) { 511 let $container = $( '#' + id ), 512 $elemContainer = $container.find( '> .elementor-widget-container' ); 513 514 if ( ! $container.length ) { 515 return; 516 } 517 518 let $items = $container.find( '.jet-listing-grid__items' ), 519 posts = [], 520 nav = $items.data( 'nav' ) || {}, 521 query = nav.query || {}, 522 postID = window.elementorFrontendConfig?.post?.id || 0; 523 524 nav = JetEngine.ensureJSON( nav ); 525 526 // Context Bricks 527 if ( $container.hasClass( 'brxe-jet-engine-listing-grid' ) ) { 528 postID = window.bricksData.postId; 529 } 530 531 // Context Gutenberg 532 if ( $container.hasClass( 'jet-listing-grid--blocks' )) { 533 postID = JetEngineSettings.post_id; 534 } 535 536 if ( args?.store?.is_front && Object.keys( query ).length ) { 537 let store = JetEngineStores[ args.store.type ]; 538 539 posts = store.getStore( args.store.slug ); 540 541 if ( ! posts.length ) { 542 posts = [ 'is-front', args.store.type, args.store.slug ]; 543 } 544 545 query.front_store__in = posts; 546 query.is_front_store = true; 547 } 548 549 let options = { 550 handler: 'get_listing', 551 container: $elemContainer.length ? $elemContainer : $container, 552 masonry: false, 553 slider: false, 554 append: false, 555 query: query, 556 widgetSettings: nav.widget_settings, 557 postID: postID, 558 elementID: $container.data( 'id' ),
559 }; 560 561 JetEngine.ajaxGetListing( options, function( response ) { 562 JetEngine.widgetListingGrid( $container ); 563 } ); 564 } ); 565 }, 566 567 addToStore: function( event ) { 568 569 event.preventDefault(); 570 event.stopPropagation(); 571 572 var $this = $( this ), 573 args = $this.data( 'args' ); 574 575 args = JetEngine.ensureJSON( args ); 576 577 if ( $this.hasClass( 'in-store' ) ) { 578 if ( args.popup ) { 579 JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id ); 580 } else if ( '_blank' === $this.attr( 'target' ) ) { 581 window.open( $this.attr( 'href' ) ); 582 } else { 583 window.location = $this.attr( 'href' ); 584 } 585 return; 586 } 587 588 if ( args.store.is_front ) { 589 590 var store = JetEngineStores[ args.store.type ], 591 count = 0; 592 593 if ( ! store ) { 594 return; 595 } 596 597 if ( store.inStore( args.store.slug, '' + args.post_id ) ) { 598 var storePosts = store.getStore( args.store.slug ); 599 count = storePosts.length; 600 } else { 601 602 count = store.addToStore( args.store.slug, args.post_id, args.store.size ); 603 604 if ( false === count ) { 605 return; 606 } 607 608 } 609 610 if ( args.popup ) { 611 JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id ); 612 } 613 614 JetEngine.switchDataStoreStatus( $this ); 615 $( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( count ); 616 $( '.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).removeClass( 'is-hidden' ); 617 618 JetEngine.dataStoreSyncListings( args ); 619 620 $( document ).trigger( 'jet-engine-data-stores-on-add', args ); 621 622 return; 623 } 624 625 if ( $this.hasClass( 'jet-store-processing' ) ) { 626 return; 627 } 628 629 $this.css( 'opacity', 0.3 ); 630 $this.addClass( 'jet-store-processing' ); 631 632 $( document ).trigger( 'jet-engine-on-add-to-store', [ $this, args ] ); 633 634 JetEngine.dataStores.addToQueue( args.store.slug, () => { 635 return $.ajax({ 636 url: JetEngineSettings.ajaxurl, 637 type: 'POST', 638 dataType: 'json', 639 data: { 640 action: 'jet_engine_add_to_store_' + args.store.slug, 641 store: args.store.slug, 642 post_id: args.post_id, 643 }, 644 }).done( function( response ) { 645 646 $this.css( 'opacity', 1 ); 647 $this.removeClass( 'jet-store-processing' ); 648 649 if ( response.success ) { 650 651 JetEngine.switchDataStoreStatus( $this ); 652 $( '.jet-remove-from-store[data-store="' + args.store.slug + '"][data-post="' + args.post_id + '"]' ).removeClass( 'is-hidden' ); 653 654 if ( response.data.fragments ) { 655 $.each( response.data.fragments, function( selector, value ) { 656 $( selector ).html( value ); 657 } ); 658 } 659 660 JetEngine.dataStoreSyncListings( args ); 661 662 if ( args.popup ) { 663 JetEngine.triggerPopup( args.popup, args.isJetEngine, args.post_id ); 664 } 665 666 } else { 667 alert( response.data.message ); 668 } 669 670 $( document ).trigger( 'jet-engine-data-stores-on-add', args ); 671 672 return response; 673 674 } ).done( function( response ) { 675 676 if ( response.success ) { 677 $( 'span.jet-engine-data-store-count[data-store="' + args.store.slug + '"]' ).text( response.data.count ); 678 } 679 680 } ).fail( function( jqXHR, textStatus, errorThrown ) { 681 $this.css( 'opacity', 1 ); 682 $this.removeClass( 'jet-store-processing' ); 683 alert( errorThrown ); 684 } ); 685 } ); 686 687 }, 688 689 switchDataStoreStatus: function( $item, toInitial ) { 690 691 var isDataStoreLink = $item.hasClass( 'jet-data-store-link' ), 692 $label = $item.find( '.jet-listing-dynamic-link__label, .jet-data-store-link__label' ), 693 $icon = $item.find( '.jet-listing-dynamic-link__icon, .jet-data-store-link__icon' ), 694 args = $item.data( 'args' ), 695 replaceLabel, 696 replaceURL, 697 replaceIcon; 698 699 args = JetEngine.ensureJSON( args ); 700 701 toInitial = toInitial || false; 702 703 if ( isDataStoreLink ) { 704 705 switch ( args.action_after_added ) { 706 case 'remove_from_store': 707 708 if ( toInitial ) { 709 $item.addClass( 'jet-add-to-store' ); 710 $item.removeClass( 'jet-remove-from-store' ); 711 712 $item.removeClass( 'in-store' ); 713 } else { 714 $item.addClass( 'jet-remove-from-store' ); 715 $item.removeClass( 'jet-add-to-store' ); 716 717 $item.addClass( 'in-store' ); 718 719 } 720 721 break; 722 723 case 'hide': 724 725 if ( toInitial ) { 726 $item.removeClass( 'is-hidden' ); 727 } else { 728 $item.addClass( 'is-hidden' ); 729 } 730 731 return; 732 } 733 734 } 735 736 if ( toInitial ) { 737 replaceLabel = args.label; 738 replaceIcon = args.icon; 739 replaceURL = '#'; 740 } else { 741 replaceLabel = args.added_label; 742 replaceIcon = args.added_icon; 743 replaceURL = args.added_url; 744 } 745 746 if ( $label.length ) { 747 $label.replaceWith( replaceLabel ); 748 } else { 749 $item.append( replaceLabel ); 750 } 751 752 if ( $icon.length ) { 753 $icon.replaceWith( replaceIcon ); 754 } else { 755 $item.prepend( replaceIcon ); 756 } 757 758 if ( isDataStoreLink && 'remove_from_store' === args.action_after_added ) { 759 return; 760 } 761 762 $item.attr( 'href', replaceURL ); 763 764 if ( toInitial ) { 765 $item.removeClass( 'in-store' ); 766 } else if ( ! $item.hasClass( 'in-store' ) ) { 767 $item.addClass( 'in-store' ); 768 } 769 770 771 }, 772 773 showConfirmDeleteDialog: function( event ) { 774 event.preventDefault(); 775 event.stopPropagation(); 776 777 var $this = $( this ); 778 779 if ( window.confirm( $this.data( 'delete-message' ) ) ) { 780 window.location = $this.attr( 'href' ); 781 } 782 783 }, 784 785 handleListingItemClick: function( event ) { 786 787 var url = $( this ).data( 'url' ), 788 target = $( this ).data( 'target' ) || false; 789 790 if ( url ) { 791 792 event.preventDefault(); 793 794 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() ) { 795 return; 796 } 797 798 if ( -1 !== url.indexOf( '#jet-engine-action' ) ) { 799 800 JetEngine.customUrlActions.runAction( url ); 801 802 } else { 803 804 if ( '_blank' === target ) { 805 window.open( url ); 806 return; 807 } 808 809 window.location = url; 810 } 811 } 812 813 }, 814 815 customUrlActions: { 816 selectorOnClick: 'a[href^="#jet-engine-action"][href*="event=click"]', 817 selectorOnHover: 'a[href^="#jet-engine-action"][href*="event=hover"], [data-url^="#jet-engine-action"][data-url*="event=hover"]', 818 819 init: function() { 820 var timeout = null; 821 822 $( document ).on( 'click.JetEngine', this.selectorOnClick, function( event ) { 823 event.preventDefault(); 824 JetEngine.customUrlActions.actionHandler( event ) 825 } ); 826 827 $( document ).on( 'click.JetEngine', this.selectorOnHover, function( event ) { 828 if ( 'A' === event.currentTarget.nodeName ) { 829 event.preventDefault(); 830 } 831 } ); 832 833 $( document ).on( { 834 'mouseenter.JetEngine': function( event ) { 835 836 if ( timeout ) { 837 clearTimeout( timeout ); 838 } 839 840 timeout = setTimeout( function() { 841 JetEngine.customUrlActions.actionHandler( event ) 842 }, window.JetEngineSettings.hoverActionTimeout ); 843 }, 844 'mouseleave.JetEngine': function() { 845 if ( timeout ) { 846 clearTimeout( timeout ); 847 timeout = null; 848 } 849 }, 850 }, this.selectorOnHover ); 851 }, 852 853 actions: {}, 854 855 addAction: function( name, callback ) { 856 this.actions[ name ] = callback; 857 }, 858 859 actionHandler: function( event ) { 860 var url = $( event.currentTarget ).attr( 'href' ) || $( event.currentTarget ).attr( 'data-url' ); 861 862 this.runAction( url ); 863 }, 864 865 runAction: function( url ) { 866 var queryParts = url.split( '&' ), 867 settings = {}; 868
869 queryParts.forEach( function( item ) { 870 if ( -1 !== item.indexOf( '=' ) ) { 871 var pair = item.split( '=' ); 872 873 settings[ pair[0] ] = decodeURIComponent( pair[1] ); 874 } 875 } ); 876 877 if ( ! settings.action ) { 878 return; 879 } 880 881 var actionCb = this.actions[ settings.action ]; 882 883 if ( ! actionCb ) { 884 return; 885 } 886 887 actionCb( settings ); 888 } 889 }, 890 891 prepareJetPopup: function( popupData, widgetData, $scope ) { 892 893 var postId = null; 894 895 if ( widgetData['is-jet-engine'] ) { 896 popupData['isJetEngine'] = true; 897 898 var $gridItems = $scope.closest( '.jet-listing-grid__items' ), 899 $gridItem = $scope.closest( '.jet-listing-grid__item' ), 900 $calendarItem = $scope.closest( '.jet-calendar-week__day-event' ), 901 $itemObject = $scope.closest( '[data-item-object]' ), 902 filterProvider = false, 903 filterQueryId = 'default'; 904 905 if ( $gridItems.length ) { 906 popupData['listingSource'] = $gridItems.data( 'listing-source' ); 907 popupData['listingId'] = $gridItems.data( 'listing-id' ); 908 popupData['queryId'] = $gridItems.data( 'query-id' ); 909 } else { 910 911 var $queryItems = $scope.closest( '[data-query-id]' ), 912 $listingSource = $scope.closest( '[data-listing-source]' ); 913 914 if ( $queryItems.length ) { 915 popupData['queryId'] = $queryItems.data( 'query-id' ); 916 } 917 918 if ( $listingSource.length ) { 919 popupData['listingSource'] = $listingSource.data( 'listing-source' ); 920 } 921 } 922 923 if ( $itemObject?.length ) { 924 popupData['postId'] = $itemObject.data( 'item-object' ); 925 926 filterProvider = $itemObject.data( 'render-type' ); 927 928 if ( ! filterProvider && $itemObject.hasClass( 'jet-dynamic-table__row' ) ) { 929 filterProvider = 'jet-data-table'; 930 } 931 } else if ( $gridItem.length ) { 932 popupData['postId'] = $gridItem.data( 'post-id' ); 933 filterProvider = 'jet-engine'; 934 } else if ( $calendarItem.length ) { 935 popupData['postId'] = $calendarItem.data( 'post-id' ); 936 filterProvider = 'jet-engine-calendar'; 937 } else if ( window.elementorFrontendConfig && window.elementorFrontendConfig.post ) { 938 popupData['postId'] = window.elementorFrontendConfig.post.id; 939 } 940 941 if ( window.JetEngineFormsEditor && window.JetEngineFormsEditor.hasEditor ) { 942 popupData['hasEditor'] = true; 943 } 944 945 // Add the filtered query to the popup data 946 if ( window.JetSmartFilters ) { 947 948 switch ( filterProvider ) { 949 case 'jet-engine': 950 var nav = $gridItems.data( 'nav' ); 951 952 if ( nav.widget_settings?._element_id ) { 953 filterQueryId = nav.widget_settings._element_id; 954 } 955 break; 956 957 case 'jet-engine-calendar': 958 var settings = $calendarItem.closest( '.jet-listing-calendar' ).data( 'settings' ); 959 960 if ( settings._element_id ) { 961 filterQueryId = settings._element_id; 962 } 963 break; 964 965 case 'jet-data-table': 966 const table = $scope.closest( '.jet-dynamic-table' ); 967 const queryId = table[0].dataset.queryId; 968 const customIds = JetEngineSettings.query_builder.custom_ids; 969 970 if ( customIds.length !== 0 && customIds?.[ queryId ] ) { 971 filterQueryId = customIds[ queryId ]; 972 } 973 break; 974 } 975 976 filterProvider = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterProvider', filterProvider, $scope, widgetData ); 977 filterQueryId = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterQueryId', filterQueryId, $scope, widgetData ); 978 979 if ( popupData.queryId && filterProvider 980 && window.JetSmartFilters?.filterGroups?.[ filterProvider + '/' + filterQueryId ]?.currentQuery 981 ) { 982 popupData['filtered_query'] = window.JetSmartFilters.filterGroups[ filterProvider + '/' + filterQueryId ].currentQuery; 983 } 984 } 985 986 } 987 988 return popupData; 989 990 }, 991 992 showCalendarEvent: function( event ) { 993 994 var $this = $( this ), 995 $day = $this.closest( '.jet-calendar-week__day' ), 996 $week = $day.closest( '.jet-calendar-week' ), 997 $events = $day.find( '.jet-calendar-week__day-content' ), 998 activeClass = 'calendar-event-active'; 999 1000 if ( $day.hasClass( activeClass ) ) { 1001 $day.removeClass( activeClass ); 1002 JetEngine.activeCalendarDay.remove(); 1003 JetEngine.activeCalendarDay = null; 1004 return; 1005 } 1006 1007 if ( JetEngine.activeCalendarDay ) { 1008 JetEngine.activeCalendarDay.remove(); 1009 $( '.' + activeClass ).removeClass( activeClass ); 1010 JetEngine.activeCalendarDay = null; 1011 } 1012 1013 $day.addClass( 'calendar-event-active' ); 1014 1015 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>' ); 1016 1017 // Need for re-init popup events 1018 JetEngine.activeCalendarDay.find( '.jet-popup-attach-event-inited' ).removeClass( 'jet-popup-attach-event-inited' ); 1019 JetEngine.initElementsHandlers( JetEngine.activeCalendarDay ); 1020 1021 JetEngine.activeCalendarDay.insertAfter( $week ); 1022 1023 }, 1024 1025 widgetListingGrid: function( $scope ) { 1026 1027 var widgetID = $scope.closest( '.elementor-widget' ).data( 'id' ),
1028 $wrapper = $scope.find( '.jet-listing-grid' ).first(), 1029 hasLazyLoad = $wrapper.hasClass( 'jet-listing-grid--lazy-load' ), 1030 $listing = $scope.find( '.jet-listing-grid__items' ).first(), 1031 $slider = $listing.parent( '.jet-listing-grid__slider' ), 1032 $masonry = $listing.hasClass( 'jet-listing-grid__masonry' ) ? $listing : false, 1033 navSettings = $listing.data( 'nav' ), 1034 masonryGrid = false, 1035 listingType = 'elementor'; 1036 1037 if ( ! widgetID ) { 1038 widgetID = $scope.data( 'element-id' ); 1039 listingType = $scope.data( 'listing-type' ); 1040 } 1041 1042 navSettings = JetEngine.ensureJSON( navSettings ); 1043 1044 if ( hasLazyLoad ) { 1045 1046 var lazyLoadOptions = $wrapper.data( 'lazy-load' ), 1047 $container = $scope.find( '.elementor-widget-container' ), 1048 widgetSettings = false; 1049 1050 if ( ! $container.length ) { 1051 $container = $scope; 1052 } 1053 1054 // Get widget settings from `elementorFrontend` in Editor. 1055 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() 1056 && $wrapper.closest( '.elementor[data-elementor-type]' ).hasClass( 'elementor-edit-mode' ) 1057 ) { 1058 widgetSettings = JetEngine.getEditorElementSettings( $scope.closest( '.elementor-widget' ) ); 1059 widgetID = false; // for avoid get widget settings from document in editor 1060 } 1061 1062 if ( ! widgetSettings ) { 1063 widgetSettings = $scope.data( 'widget-settings' ); 1064 } 1065 1066 JetEngine.lazyLoadListing( { 1067 container: $container, 1068 elementID: widgetID, 1069 postID: lazyLoadOptions.post_id, 1070 queriedID: lazyLoadOptions.queried_id || false, 1071 offset: lazyLoadOptions.offset || '0px', 1072 query: lazyLoadOptions.query || {}, 1073 listingType: listingType, 1074 widgetSettings: widgetSettings, 1075 extraProps: lazyLoadOptions.extra_props || false, 1076 } ); 1077 1078 return; 1079 } 1080 1081 if ( $slider.length ) { 1082 JetEngine.initSlider( $slider ); 1083 } 1084 1085 if ( $masonry && $masonry.length ) { 1086 1087 JetEngine.initMasonry( $masonry ); 1088 1089 /* Keep masonry re-init for Bricks */ 1090 if ( $scope.hasClass( 'brxe-jet-engine-listing-grid' ) ) { 1091 $( window ).on( 'load', function() { 1092 JetEngine.runMasonry( $masonry ); 1093 } ); 1094 } 1095 1096 } 1097 1098 if ( navSettings && navSettings.enabled ) { 1099 1100 JetEngine.loadMoreListing( { 1101 container: $listing, 1102 settings: navSettings, 1103 masonry: $masonry, 1104 slider: $slider, 1105 elementID: widgetID, 1106 } ); 1107 1108 } 1109 1110 // Init elements handlers in editor. 1111 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() 1112 && $wrapper.closest( '.elementor-element-edit-mode' ).length 1113 ) { 1114 JetEngine.initElementsHandlers( $wrapper ); 1115 } 1116 1117 }, 1118 1119 initMasonry: function( $masonry, masonrySettings ) { 1120 imagesLoaded( $masonry, function() { 1121 JetEngine.runMasonry( $masonry, masonrySettings ); 1122 } ); 1123 }, 1124 1125 runMasonry: function( $masonry, masonrySettings ) { 1126 var defaultSettings = { 1127 itemSelector: '> .jet-listing-grid__item', 1128 columnsKey: 'columns', 1129 }; 1130 1131 masonrySettings = masonrySettings || {}; 1132 masonrySettings = $.extend( {}, defaultSettings, masonrySettings ); 1133 1134 var $eWidget = $masonry.closest( '.elementor-widget' ), 1135 $items = $( masonrySettings.itemSelector, $masonry ), 1136 options = $masonry.data( 'masonry-grid-options' ) || {}; 1137 1138 options = JetEngine.ensureJSON( options ); 1139 1140 // Reset masonry 1141 $items.css( { 1142 marginTop: '' 1143 } ); 1144 1145 // Bricks margin 1146 const { gap } = options; 1147 let margin = null; 1148 1149 if ( gap ) { 1150 margin = { 1151 x: +gap.horizontal, 1152 y: +gap.vertical, 1153 }; 1154 } 1155 1156 var args = { 1157 container: $masonry[0], 1158 margin: margin ? margin : 0, 1159 }; 1160 1161 if ( $eWidget.length ) { 1162 var settings = JetEngine.getElementorElementSettings( $eWidget ), 1163 breakpoints = {}, 1164 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints, 1165 columnsKey = masonrySettings.columnsKey; 1166 1167 args.columns = settings[columnsKey + '_widescreen'] ? +settings[columnsKey + '_widescreen'] : +settings[columnsKey]; 1168
1169 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1170 1171 if ( settings[columnsKey + '_' + breakpointName] ) { 1172 if ( 'widescreen' === breakpointName ) { 1173 breakpoints[eBreakpoints[breakpointName].value - 1] = +settings[columnsKey]; 1174 } else { 1175 breakpoints[eBreakpoints[breakpointName].value] = +settings[columnsKey + '_' + breakpointName]; 1176 } 1177 } 1178 1179 } ); 1180 1181 args.breakAt = breakpoints; 1182 1183 } else { 1184 args.columns = options.columns.desktop; 1185 args.breakAt = { 1186 1025: options.columns.tablet, 1187 768: options.columns.mobile, 1188 }; 1189 } 1190 1191 var masonryInstance = Macy( args ); 1192 1193 masonryInstance.runOnImageLoad( function () { 1194 masonryInstance.recalculate( true ); 1195 }, true ); 1196 1197 // Event to recalculate current masonry listings. 1198 $masonry.on( 'jet-engine/listing/recalculate-masonry-listing', function() { 1199 masonryInstance.runOnImageLoad( function () { 1200 masonryInstance.recalculate( true ); 1201 }, true ); 1202 } ); 1203 1204 // Event to recalculate all masonry listings. 1205 $( document ).on( 'jet-engine/listing/recalculate-masonry', function() { 1206 masonryInstance.recalculate( true ); 1207 } ); 1208 1209 }, 1210 1211 ajaxGetListing: function( options, doneCallback, failCallback ) { 1212 1213 var container = options.container || false, 1214 handler = options.handler || false, 1215 masonry = options.masonry || false, 1216 slider = options.slider || false, 1217 append = options.append || false, 1218 query = options.query || {}, 1219 widgetSettings = options.widgetSettings || {}, 1220 postID = options.postID || false, 1221 queriedID = options.queriedID || false, 1222 elementID = options.elementID || false, 1223 page = options.page || 1, 1224 preventCSS = options.preventCSS || false, 1225 listingType = options.listingType || false, 1226 extraProps = options.extraProps || false, 1227 isEditMode = window.elementorFrontend && window.elementorFrontend.isEditMode(); 1228 1229 doneCallback = doneCallback || function( response ) {}; 1230 1231 if ( ! container|| ! handler ) { 1232 return; 1233 } 1234 1235 if ( ! preventCSS ) { 1236 container.css({ 1237 pointerEvents: 'none', 1238 opacity: '0.5', 1239 cursor: 'default', 1240 }); 1241 } 1242 1243 var requestData = { 1244 action: 'jet_engine_ajax', 1245 handler: handler, 1246 query: query, 1247 widget_settings: widgetSettings, 1248 page_settings: { 1249 post_id: postID, 1250 queried_id: queriedID, 1251 element_id: elementID, 1252 page: page, 1253 }, 1254 listing_type: listingType, 1255 isEditMode: isEditMode, 1256 addedPostCSS: JetEngine.addedPostCSS 1257 }; 1258 1259 if ( extraProps ) { 1260 Object.assign( requestData, extraProps ); 1261 } 1262 1263 $.ajax({ 1264 url: JetEngineSettings.ajaxlisting, 1265 type: 'POST', 1266 dataType: 'json', 1267 data: requestData, 1268 }).done( function( response ) { 1269 1270 // container.removeAttr( 'style' ); 1271 1272 // Manual reset container style to prevent removal of masonry styles. 1273 if ( !preventCSS ) { 1274 container.css( { 1275 pointerEvents: '', 1276 opacity: '', 1277 cursor: '', 1278 } ); 1279 } 1280 1281 if ( response.success ) { 1282 1283 JetEngine.enqueueAssetsFromResponse( response ); 1284 1285 container.data( 'page', page ); 1286 1287 var $html = $( response.data.html ); 1288 1289 JetEngine.initFrontStores( $html ); 1290 1291 if ( slider && slider.length ) { 1292 1293 var $slider = slider.find( '> .jet-listing-grid__items' ); 1294 1295 if ( ! $slider.hasClass( 'slick-initialized' ) ) { 1296 1297 if ( append ) { 1298 container.append( $html ); 1299 } else { 1300 container.html( $html ); 1301 } 1302 1303 var itemsCount = container.find( '> .jet-listing-grid__item' ).length; 1304 1305 slider.addClass( 'jet-listing-grid__slider' ); 1306 JetEngine.initSlider( slider, { itemsCount: itemsCount } ); 1307 1308 } else { 1309 $html.each( function( index, el ) { 1310 $slider.slick( 'slickAdd', el ); 1311 }); 1312 } 1313 1314 } else { 1315 1316 if ( append ) { 1317 container.append( $html ); 1318 } else { 1319 container.html( $html ); 1320 } 1321 1322 if ( masonry && masonry.length ) { 1323 //JetEngine.initMasonry( masonry ); 1324 masonry.trigger( 'jet-engine/listing/recalculate-masonry-listing' ); 1325 } 1326 1327 } 1328 1329 // Re-init Bricks scripts 1330 JetEngine.reinitBricksScripts( elementID ); 1331 1332 Promise.all( JetEngine.assetsPromises ).then( function() { 1333 JetEngine.initElementsHandlers( $html ); 1334 JetEngine.assetsPromises = []; 1335 } ); 1336 1337 if ( response.data.fragments ) { 1338 for ( var selector in response.data.fragments ) { 1339 var $selector = $( selector ); 1340 1341 if ( $selector.length ) { 1342 $selector.html( response.data.fragments[ selector ] ); 1343 } 1344 } 1345 } 1346 } 1347 1348 $( document ).trigger( 'jet-engine/listing/ajax-get-listing/done', [ $html, options ] ); 1349 1350 } ).done( doneCallback ).fail( function() { 1351 container.removeAttr( 'style' ); 1352 if ( failCallback ) { 1353 failCallback.call(); 1354 } 1355 1356 } ); 1357 1358 }, 1359 1360 loadMoreListing: function( args ) { 1361 1362 var instance = { 1363 1364 setup: function() { 1365 this.container = args.container; 1366 this.masonry = args.masonry; 1367 this.slider = args.slider; 1368 this.settings = args.settings; 1369 this.elementID = args.elementID; 1370 1371 this.wrapper = this.container.closest( '.jet-listing-grid' ); 1372 1373 this.type = this.settings.type || 'click'; 1374 this.page = parseInt( this.container.data( 'page' ), 10 ) || 0; 1375 this.pages = parseInt( this.container.data( 'pages' ), 10 ) || 0; 1376 this.queriedID = this.container.data( 'queried-id' ) || false; 1377 }, 1378 1379 init: function() { 1380 1381 this.setup(); 1382 1383 switch ( this.type ) { 1384 case 'click': 1385 1386 this.handleMore(); 1387 1388 break; 1389 1390 case 'scroll': 1391 1392 if ( ( ! window.elementorFrontend || ! window.elementorFrontend.isEditMode() ) && ! this.slider.length ) { 1393 this.handleInfiniteScroll(); 1394 } 1395 1396 break; 1397 } 1398 }, 1399 1400 handleMore: function() { 1401 1402 if ( ! this.settings.more_el ) { 1403 return; 1404 } 1405 1406 var self = this, 1407 $button = $( this.settings.more_el ); 1408 1409 if ( ! $button.length ) { 1410 return; 1411 } 1412 1413 if ( ! this.pages || this.page === this.pages && ! window.elementor ) { 1414 $button.css( 'display', 'none' ); 1415 } else { 1416 $button.removeAttr( 'style' ); 1417 } 1418 1419 $( document ) 1420 .off( 'click', this.settings.more_el ) 1421 .on( 'click', this.settings.more_el, function( event ) { 1422 event.preventDefault(); 1423 1424 if ( ! self.pages || self.page >= self.pages) { 1425 $button.css( 'display', 'none' ); 1426 return; 1427 } 1428 1429 $button.css( { 1430 pointerEvents: 'none', 1431 opacity: '0.5', 1432 cursor: 'default', 1433 } ); 1434 1435 self.ajaxGetItems( function( response ) { 1436 $button.removeAttr( 'style' ); 1437 1438 if ( response.success && self.page === self.pages ) { 1439 $button.css( 'display', 'none' ); 1440 } 1441 }, function() { 1442 $button.button.removeAttr( 'style' ); 1443 } 1444 ); 1445 } ); 1446 }, 1447 1448 handleInfiniteScroll: function() { 1449 1450 if ( this.container.hasClass( 'jet-listing-not-found' ) ) { 1451 return; 1452 } 1453 1454 if ( ! this.pages || this.page === this.pages ) { 1455 return; 1456 } 1457 1458 var self = this, 1459 $trigger = this.wrapper.find( '.jet-listing-grid__loader' ), 1460 offset = '0%'; 1461 1462 if ( ! $trigger.length ) { 1463 $trigger = $( '<div>', { 1464 class: 'jet-listing-grid__loading-trigger' 1465 } ); 1466 1467 this.wrapper.append( $trigger ); 1468 } 1469 1470 // Prepare offset value. 1471 if ( this.settings.widget_settings && this.settings.widget_settings.load_more_offset ) { 1472 var offsetValue = this.settings.widget_settings.load_more_offset; 1473 1474 switch ( typeof offsetValue ) { 1475 case 'object': 1476 var size = offsetValue.size ? offsetValue.size : '0', 1477 unit = offsetValue.unit ? offsetValue.unit : 'px'; 1478 1479 offset = size + unit; 1480 break; 1481 1482 case 'number': 1483 case 'string': 1484 offset = offsetValue + 'px'; 1485 break; 1486 } 1487 } 1488 1489 var observer = new IntersectionObserver( 1490 function( entries, observer ) { 1491 1492 if ( entries[0].isIntersecting ) { 1493 1494 self.ajaxGetItems( function() { 1495 1496 // Re-init observer if the last page is not loaded 1497 if ( self.page !== self.pages ) { 1498 setTimeout( function() { 1499 observer.observe( entries[0].target ); 1500 }, 250 ); 1501 } 1502 1503 } ); 1504 1505 // Detach observer 1506 observer.unobserve( entries[0].target ); 1507 } 1508 }, 1509 { 1510 rootMargin: '0% 0% ' + offset + ' 0%', 1511 } 1512 ); 1513 1514 observer.observe( $trigger[0] ); 1515 }, 1516 1517 ajaxGetItems: function( doneCallback, failCallback ) { 1518 var self = this; 1519 1520 this.page++; 1521 1522 this.wrapper.addClass( 'jet-listing-grid-loading' ); 1523 1524 JetEngine.ajaxGetListing( { 1525 handler: 'listing_load_more', 1526 container: this.container, 1527 masonry: this.masonry, 1528 slider: this.slider, 1529 append: true, 1530 query: this.settings.query, 1531 widgetSettings: this.settings.widget_settings, 1532 page: this.page, 1533 elementID: this.elementID, 1534 queriedID: this.queriedID, 1535 preventCSS: !! this.wrapper.find( '.jet-listing-grid__loader' ).length, // Prevent CSS if listing has the loader. 1536 }, function( response ) { 1537 1538 JetEngine.lazyLoading = false;
1539 self.wrapper.removeClass( 'jet-listing-grid-loading' ); 1540 1541 if ( doneCallback ) { 1542 doneCallback( response ); 1543 } 1544 1545 $( document ).trigger( 'jet-engine/listing-grid/after-load-more', [args, response] ); 1546 1547 }, function() { 1548 1549 JetEngine.lazyLoading = false; 1550 self.wrapper.removeClass( 'jet-listing-grid-loading' ); 1551 1552 if ( failCallback ) { 1553 failCallback(); 1554 } 1555 1556 } ); 1557 }, 1558 }; 1559 1560 instance.init(); 1561 }, 1562 1563 lazyLoadListing: function( args ) { 1564 1565 var $wrapper = args.container.find( '.jet-listing-grid' ), 1566 observer = new IntersectionObserver( 1567 function( entries, observer ) { 1568 1569 if ( entries[0].isIntersecting ) { 1570 1571 JetEngine.lazyLoading = true; 1572 1573 if ( ! $wrapper.length ) { 1574 $wrapper = args.container; 1575 } 1576 1577 $wrapper.addClass( 'jet-listing-grid-loading' ); 1578 1579 JetEngine.ajaxGetListing( { 1580 handler: 'get_listing', 1581 container: args.container, 1582 masonry: false, 1583 slider: false, 1584 append: false, 1585 elementID: args.elementID, 1586 postID: args.postID, 1587 queriedID: args.queriedID, 1588 query: args.query, 1589 widgetSettings: args.widgetSettings, 1590 listingType: args.listingType, 1591 preventCSS: true, 1592 extraProps: args.extraProps, 1593 }, function( response ) { 1594 1595 $wrapper.removeClass( 'jet-listing-grid-loading' ); 1596 1597 var $widget = args.container.closest( '.elementor-widget' ); 1598 1599 if ( ! $widget.length ) { 1600 $widget = args.container.closest( '.jet-listing-grid--blocks' ); 1601 } 1602 1603 if ( ! $widget.length ) { 1604 $widget = args.container; 1605 } 1606 1607 if ( $widget.length ) { 1608 $widget.find( '.jet-listing-grid' ).first().removeClass( 'jet-listing-grid--lazy-load' ); 1609 $widget.find( '.jet-listing-grid' ).first().addClass( 'jet-listing-grid--lazy-load-completed' ); 1610 } 1611 1612 JetEngine.widgetListingGrid( $widget ); 1613 JetEngine.loadFrontStoresItems( $widget ); 1614 JetEngine.lazyLoading = false; 1615 1616 let needReInitFilters = false; 1617 let isFrontend = JetEngine.isFrontend(); 1618 1619 if ( isFrontend && window.JetSmartFilterSettings ) { 1620 1621 if ( response.data.filters_data ) { 1622 $.each( response.data.filters_data, function( param, data ) { 1623 if ( 'extra_props' === param ) { 1624 window.JetSmartFilterSettings[ param ] = $.extend( 1625 {}, 1626 window.JetSmartFilterSettings[ param ], 1627 data 1628 ); 1629 } else { 1630 if ( window.JetSmartFilterSettings[ param ]['jet-engine'] ) { 1631 window.JetSmartFilterSettings[ param ]['jet-engine'] = $.extend( 1632 {}, 1633 window.JetSmartFilterSettings[ param ]['jet-engine'], 1634 data 1635 ); 1636 } else { 1637 window.JetSmartFilterSettings[ param ]['jet-engine'] = data; 1638 } 1639 } 1640 }); 1641 1642 needReInitFilters = true; 1643 } 1644 1645 if ( response.data.indexer_data ) { 1646 const { 1647 provider = false, 1648 query = {} 1649 } = response.data.indexer_data; 1650 1651 window.JetSmartFilters.setIndexedData( provider, query ); 1652 } 1653 } 1654 1655 // ReInit filters 1656 if ( needReInitFilters && window.JetSmartFilters ) { 1657 window.JetSmartFilters.reinitFilters(); 1658 } 1659 1660 $( document ).trigger( 'jet-engine/listing-grid/after-lazy-load', [ args, response ] ); 1661 1662 }, function() { 1663 JetEngine.lazyLoading = false; 1664 1665 if ( ! $wrapper.length ) { 1666 $wrapper = args.container; 1667 } 1668 1669 $wrapper.removeClass( 'jet-listing-grid-loading' ); 1670 } ); 1671 1672 // Detach observer after the first load the listing 1673 observer.unobserve( entries[0].target ); 1674 } 1675 }, 1676 { 1677 rootMargin: '0% 0% ' + args.offset + ' 0%' 1678 } 1679 ); 1680 1681 observer.observe( args.container[0] ); 1682 }, 1683 1684 ensureJSON: function( maybeJSON ) { 1685 1686 if ( ! maybeJSON ) { 1687 return maybeJSON; 1688 } 1689 1690 if ( 'string' === typeof maybeJSON ) { 1691 console.log( maybeJSON ); 1692 //maybeJSON = JSON.parse( maybeJSON ); 1693 } 1694 1695 return maybeJSON; 1696 1697 }, 1698 1699 initSlider: function( $slider, customOptions ) { 1700 var $eWidget = $slider.closest( '.elementor-widget' ), 1701 options = $slider.data( 'slider_options' ), 1702 windowWidth = $( window ).width(), 1703 tabletBP = 1025, 1704 mobileBP = 768, 1705 tabletSlides, mobileSlides, defaultOptions, slickOptions; 1706 1707 options = JetEngine.ensureJSON( options ); 1708 1709 customOptions = customOptions || {}; 1710 1711 options = $.extend( {}, options, customOptions ); 1712 1713 if ( $eWidget.length ) { 1714 1715 var settings = JetEngine.getElementorElementSettings( $eWidget ), 1716 responsive = [], 1717 deviceMode = elementorFrontend.getCurrentDeviceMode(), 1718 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints; 1719 1720 options.slidesToShow = settings.columns_widescreen ? +settings.columns_widescreen : +settings.columns; 1721
1722 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1723 1724 if ( settings['columns_' + breakpointName] ) { 1725 1726 if ( 'widescreen' === breakpointName ) { 1727 1728 responsive.push( { 1729 breakpoint: eBreakpoints[breakpointName].value, 1730 settings: { 1731 slidesToShow: +settings['columns'], 1732 } 1733 } ); 1734 1735 } else { 1736 var breakpointSettings = { 1737 breakpoint: eBreakpoints[breakpointName].value + 1, 1738 settings: { 1739 slidesToShow: +settings['columns_' + breakpointName], 1740 } 1741 }; 1742 1743 if ( options.slidesToScroll > breakpointSettings.settings.slidesToShow ) { 1744 breakpointSettings.settings.slidesToScroll = breakpointSettings.settings.slidesToShow; 1745 } 1746 1747 // if ( 'mobile' === breakpointName ) { 1748 // breakpointSettings.settings.slidesToScroll = 1; 1749 // } 1750 1751 responsive.push( breakpointSettings ); 1752 } 1753 } 1754 1755 } ); 1756 1757 options.responsive = responsive; 1758 1759 } else { 1760 1761 // Ensure we have at least some options to avoid errors 1762 if ( ! options.slidesToShow ) { 1763 options.slidesToShow = { 1764 desktop: 3, 1765 tablet: 1, 1766 mobile: 1, 1767 } 1768 } 1769 1770 if ( options.itemsCount <= options.slidesToShow.desktop && windowWidth >= tabletBP ) { // 1025 - ... 1771 $slider.removeClass( 'jet-listing-grid__slider' ); 1772 return; 1773 } else if ( options.itemsCount <= options.slidesToShow.tablet && tabletBP > windowWidth && windowWidth >= mobileBP ) { // 768 - 1024 1774 $slider.removeClass( 'jet-listing-grid__slider' ); 1775 return; 1776 } else if ( options.itemsCount <= options.slidesToShow.mobile && windowWidth < mobileBP ) { // 0 - 767 1777 $slider.removeClass( 'jet-listing-grid__slider' ); 1778 return; 1779 } 1780 1781 if ( options.slidesToShow.tablet ) { 1782 tabletSlides = options.slidesToShow.tablet; 1783 } else { 1784 tabletSlides = 1 === options.slidesToShow.desktop ? 1 : 2; 1785 } 1786 1787 if ( options.slidesToShow.mobile ) { 1788 mobileSlides = options.slidesToShow.mobile; 1789 } else { 1790 mobileSlides = 1; 1791 } 1792 1793 options.slidesToShow = options.slidesToShow.desktop; 1794 1795 options.responsive = [ 1796 { 1797 breakpoint: 1025, 1798 settings: { 1799 slidesToShow: tabletSlides, 1800 slidesToScroll: options.slidesToScroll > tabletSlides ? tabletSlides : options.slidesToScroll 1801 } 1802 }, 1803 { 1804 breakpoint: 768, 1805 settings: { 1806 slidesToShow: mobileSlides, 1807 slidesToScroll: 1 1808 } 1809 } 1810 ]; 1811 } 1812 1813 defaultOptions = { 1814 customPaging: function( slider, i ) { 1815 return $( '<span />' ).text( i + 1 ).attr( 'role', 'tab' ); 1816 }, 1817 slide: '.jet-listing-grid__item', 1818 dotsClass: 'jet-slick-dots', 1819 }; 1820 1821 slickOptions = $.extend( {}, defaultOptions, options ); 1822 1823 var $sliderItems = $slider.find( '> .jet-listing-grid__items' ); 1824 1825 if ( slickOptions.infinite ) { 1826 $sliderItems.on( 'init', function() { 1827 var $items = $( this ), 1828 $clonedSlides = $( '> .slick-list > .slick-track > .slick-cloned.jet-listing-grid__item', $items ); 1829 1830 if ( !$clonedSlides.length ) { 1831 return; 1832 } 1833 1834 JetEngine.initElementsHandlers( $clonedSlides ); 1835 1836 if ( $slider.find('.bricks-lazy-hidden').length ) { 1837 bricksLazyLoad(); 1838 } 1839 } ); 1840 } 1841 1842 // Temporary solution issue with Lazy Load images + RTL on Chrome. 1843 // Remove after fix in Chrome. 1844 // See: https://github.com/Crocoblock/issues-tracker/issues/7552 1845 if ( slickOptions.rtl ) { 1846 $sliderItems.on( 'init', function() { 1847 var $items = $( this ), 1848 $lazyImages = $( 'img[loading=lazy]', $items ), 1849 lazyImageObserver = new IntersectionObserver( 1850 function( entries, observer ) { 1851 entries.forEach( function( entry ) { 1852 if ( entry.isIntersecting ) { 1853 // If an image does not load, need to remove the `loading` attribute. 1854 if ( ! entry.target.complete ) { 1855 entry.target.removeAttribute( 'loading' ); 1856 } 1857 1858 // Detach observer 1859 observer.unobserve( entry.target ); 1860 } 1861 } ); 1862 } 1863 ); 1864 1865 $lazyImages.each( function() { 1866 const $img = $( this ); 1867 lazyImageObserver.observe( $img[0] ); 1868 } ); 1869 } ); 1870 } 1871 1872 if ( $sliderItems.hasClass( 'slick-initialized' ) ) { 1873 $sliderItems.slick( 'refresh', true ); 1874 return; 1875 } 1876 1877 if ( slickOptions.variableWidth ) { 1878 slickOptions.slidesToShow = 1; 1879 slickOptions.slidesToScroll = 1; 1880 slickOptions.responsive = null; 1881 } 1882 1883 $sliderItems.on( 1884 'init.JetEngine', 1885 () => { 1886 $sliderItems.find( '.slick-active' ).each( 1887 ( i, el ) => { 1888 JetEngine.rerunElementorAnimation( $( el ) ); 1889 } 1890 ); 1891 } 1892 ); 1893 1894 $sliderItems.on( 1895 'afterChange.JetEngine', 1896 () => { 1897 $sliderItems.find( '.slick-active' ).each( 1898 ( i, el ) => { 1899 JetEngine.rerunElementorAnimation( $( el ) ); 1900 } 1901 ); 1902 } 1903 ); 1904 1905 $sliderItems.slick( slickOptions ); 1906 1907 if ( $sliderItems.closest( '.jet-listing-grid--lazy-load-completed' ).length ) { 1908 $sliderItems.slick( 'refresh', true ); 1909 } 1910 1911 $sliderItems.off( 'init.JetEngine' ); 1912 }, 1913 1914 maybeReinitSlider: function( event, $scope ) { 1915 var $slider = $scope.find( '.jet-listing-grid__slider' ); 1916 1917 if ( $slider.length ) { 1918 $slider.each( function() { 1919 JetEngine.initSlider( $( this ) ); 1920 } ); 1921 1922 } 1923 }, 1924 1925 rerunElementorAnimation: function( $scope, forceRerun = false ) { 1926 let selector = '.elementor-element[data-settings*="_animation"]'; 1927 1928 if ( ! forceRerun ) { 1929 selector += ':is( .elementor-invisible, :not(.jet-engine-animation-rerun) )'; 1930 } 1931 1932 $scope.find( selector ).each( 1933 ( i, el ) => { 1934 const settings = JSON.parse( el.dataset.settings || '{}' ); 1935 const $el = $( el ); 1936 1937 if ( settings._animation ) { 1938 const classes = `animated ${settings._animation}`; 1939 $el.removeClass( classes ); 1940 1941 setTimeout( 1942 () => { 1943 $el.removeClass( 'elementor-invisible' ).addClass( classes ); 1944 $el.addClass( 'jet-engine-animation-rerun' ); 1945 }, 1946 settings._animation_delay 1947 ); 1948 1949 } 1950 } 1951 ); 1952 }, 1953 1954 widgetDynamicField: function( $scope ) { 1955 1956 var $slider = $scope.find( '.jet-engine-gallery-slider' ); 1957 1958 if ( $slider.length ) { 1959 if ( $.isFunction( $.fn.imagesLoaded ) ) {
1960 $slider.imagesLoaded().always( function( instance ) { 1961 1962 var $eWidget = $slider.closest( '.elementor-widget' ); 1963 1964 if ( $slider.hasClass( 'slick-initialized' ) ) { 1965 $slider.slick( 'refresh', true ); 1966 } else { 1967 var atts = $slider.data( 'atts' ); 1968 1969 atts = JetEngine.ensureJSON( atts ); 1970 1971 if ( $eWidget.length ) { 1972 var settings = JetEngine.getElementorElementSettings( $scope ), 1973 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints, 1974 responsive = []; 1975 1976 if ( settings.img_slider_cols || settings.img_slider_cols_widescreen ) { 1977 atts.slidesToShow = settings.img_slider_cols_widescreen ? +settings.img_slider_cols_widescreen : +settings.img_slider_cols; 1978 } 1979 1980 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1981 1982 if ( settings['img_slider_cols_' + breakpointName] ) { 1983 1984 if ( 'widescreen' === breakpointName ) { 1985 1986 responsive.push( { 1987 breakpoint: eBreakpoints[breakpointName].value, 1988 settings: { 1989 slidesToShow: +settings['img_slider_cols'], 1990 } 1991 } ); 1992 1993 } else { 1994 var breakpointSettings = { 1995 breakpoint: eBreakpoints[breakpointName].value + 1, 1996 settings: { 1997 slidesToShow: +settings['img_slider_cols_' + breakpointName], 1998 } 1999 }; 2000 2001 responsive.push( breakpointSettings ); 2002 } 2003 } 2004 2005 } ); 2006 2007 atts.responsive = responsive; 2008 } 2009 2010 $slider.slick( atts ); 2011 } 2012 } ); 2013 } 2014 } 2015 2016 $slider.on('init', function (event, slick) { 2017 2018 const slider = event.target; 2019 2020 if (!slider.classList.contains('jet-engine-gallery-lightbox') || ! window?.PhotoSwipeLightbox) { 2021 return; 2022 } 2023 2024 let lightbox = new PhotoSwipeLightbox({ 2025 mainClass: 'brx', 2026 gallery: slider, 2027 children: 'a', 2028 showHideAnimationType: 'none', 2029 zoomAnimationDuration: false, 2030 pswpModule: PhotoSwipe5, 2031 }); 2032 2033 lightbox.addFilter('numItems', numItems => slick.slideCount); 2034 2035 lightbox.addFilter('clickedIndex', function (clickedIndex, e) { 2036 const slide = e.target.closest('.slick-slide'); 2037 2038 if (!slide) { 2039 return clickedIndex; 2040 } 2041 2042 if (clickedIndex >= slick.slideCount) { 2043 return clickedIndex % slick.slideCount; 2044 } 2045 2046 return clickedIndex; 2047 }); 2048 2049 lightbox.addFilter('thumbEl', (thumbnail, itemData, index) => { 2050 return thumbnail; 2051 }); 2052 2053 lightbox.addFilter('thumbBounds', (thumbBounds, itemData, index) => { 2054 return thumbBounds; 2055 }); 2056 2057 lightbox.init(); 2058 }); 2059 2060 // Masonry init 2061 var $masonry = $scope.find( '.jet-engine-gallery-grid--masonry' ); 2062 2063 if ( $masonry.length ) { 2064 JetEngine.initMasonry( $masonry, { 2065 columnsKey: 'img_columns', 2066 itemSelector: '> .jet-engine-gallery-grid__item', 2067 } ); 2068 } 2069 2070 }, 2071 2072 calendarCache: { 2073 2074 entries: {}, 2075 2076 //introduced because Firefox does not have forEach method for iterators 2077 iterate: function( iterator, callback ) { 2078 if ( typeof iterator?.forEach === 'function' ) { 2079 iterator.forEach( callback ); 2080 } else if ( typeof iterator?.next === 'function' ) { 2081 let next; 2082 while ( next = iterator.next(), ! next.done ) { 2083 callback.call( this, next.value ); 2084 } 2085 } 2086 }, 2087 2088 get: function ( cacheId, month ) { 2089 return JetEngine.calendarCache.entries[ cacheId ]?.get( month ) || false; 2090 }, 2091 2092 set: function ( cacheId, month, content, settings = {}, timestamp = false ) { 2093 if ( ! JetEngine.calendarCache.entries[ cacheId ] ) { 2094 JetEngine.calendarCache.entries[ cacheId ] = new Map(); 2095 } 2096 2097 if ( ! JetEngine.calendarCache.entries[ cacheId ].has( month ) 2098 && JetEngine.calendarCache.entries[ cacheId ].size > ( settings['max_cache'] ?? 12 ) - 1 2099 ) { 2100 let deletedKey; 2101 2102 const mapKeys = JetEngine.calendarCache.entries[ cacheId ].keys(); 2103 2104 if ( settings['__switch_direction'] < 0 ) { 2105 let maxDate = false; 2106 2107 JetEngine.calendarCache.iterate( 2108 mapKeys, 2109 function ( key ) { 2110 const parsedDate = Date.parse( key ); 2111 2112 if ( ! maxDate || parsedDate > maxDate ) { 2113 maxDate = parsedDate; 2114 deletedKey = key; 2115 } 2116 } 2117 ); 2118 } else { 2119 let minDate = false;
2120 2121 JetEngine.calendarCache.iterate( 2122 mapKeys, 2123 function ( key ) { 2124 const parsedDate = Date.parse( key ); 2125 2126 if ( ! minDate || parsedDate < minDate ) { 2127 minDate = parsedDate; 2128 deletedKey = key; 2129 } 2130 } 2131 ); 2132 } 2133 2134 JetEngine.calendarCache.entries[ cacheId ].delete( deletedKey ); 2135 } 2136 2137 if ( ! timestamp ) { 2138 timestamp = Date.now(); 2139 } 2140 2141 JetEngine.calendarCache.entries[ cacheId ].set( month, [ content, timestamp ] ); 2142 }, 2143 2144 update: function ( cacheId, month, content, settings = {} ) { 2145 let cached = JetEngine.calendarCache.get( cacheId, month ); 2146 JetEngine.calendarCache.set( cacheId, month, content, settings, cached[1] ?? false ); 2147 }, 2148 2149 deleteExpiredEntries: function ( cacheId, cacheTimeout ) { 2150 //delete possible orphaned caches 2151 for ( const cacheId in JetEngine.calendarCache.entries ) { 2152 if ( ! document.querySelector( `.jet-calendar[data-cache-id="${cacheId}"]` ) ) { 2153 delete JetEngine.calendarCache.entries[ cacheId ]; 2154 } 2155 } 2156 2157 if ( ! JetEngine.calendarCache.entries[ cacheId ] ) { 2158 return; 2159 } 2160 2161 JetEngine.calendarCache.iterate( 2162 JetEngine.calendarCache.entries[ cacheId ].keys(), 2163 function ( month ) { 2164 if ( JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) { 2165 JetEngine.calendarCache.entries[ cacheId ].delete( month ); 2166 } 2167 } 2168 ); 2169 }, 2170 2171 isExpired: function ( cacheId, month, cacheTimeout ) { 2172 if ( cacheTimeout < 0 ) { 2173 return false; 2174 } 2175 2176 const cached = JetEngine.calendarCache.get( cacheId, month ); 2177 2178 if ( ! cached || ! Array.isArray( cached ) ) { 2179 return true; 2180 } 2181 2182 return ! cached[1] || cached[1] < Date.now() - cacheTimeout; 2183 }, 2184 2185 clear: function( e, $calendar ) { 2186 const cacheId = $calendar.data( 'cache-id' ) || false; 2187 2188 if ( ! cacheId ) { 2189 return; 2190 } 2191 2192 JetEngine.calendarCache.entries[ cacheId ] = new Map(); 2193 }, 2194 2195 modifyJetSmartFiltersSetiings: function( $widget, widgetType, monthData ) { 2196 if ( ! window.JetSmartFilterSettings || ! window.JetSmartFilterSettings.settings ) { 2197 return; 2198 } 2199 2200 if ( ! window.JetSmartFilterSettings.settings['jet-engine-calendar'] ) { 2201 return; 2202 } 2203 2204 monthData = monthData.split( ' ' ); 2205
2206 const month = monthData[0], 2207 year = monthData[1]; 2208 2209 let widgetId; 2210 2211 switch ( widgetType ) { 2212 case 'block': 2213 widgetId = $widget.closest( '.jet-listing-calendar-block' )[0].id; 2214 2215 if ( ! widgetId ) { 2216 widgetId = 'default'; 2217 } 2218 2219 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ] ) { 2220 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month; 2221 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year; 2222 } 2223 2224 break; 2225 case 'bricks': 2226 widgetId = $widget.data( 'element-id' ); 2227 2228 if ( ! widgetId ) { 2229 break; 2230 } 2231 2232 for ( const id in window.JetSmartFilterSettings.settings['jet-engine-calendar'] ) { 2233 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]?._id === widgetId ) { 2234 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_month'] = month; 2235 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_year'] = year; 2236 break; 2237 } 2238 } 2239 2240 break; 2241 case 'elementor': 2242 widgetId = $widget.closest( '.elementor-widget-jet-listing-calendar' )[0].id; 2243 2244 if ( ! widgetId ) { 2245 widgetId = 'default'; 2246 } 2247 2248 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar']?.[ widgetId ] ) { 2249 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month; 2250 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year; 2251 } 2252 2253 break; 2254 } 2255 }, 2256 }, 2257 2258 selectCalendarMonth: function ( $event ) { 2259 let wrapper = this.closest( '.jet-calendar-caption__dates' ); 2260 2261 if ( ! JetEngine.updateDateSelectLabels( wrapper ) ) { 2262 return; 2263 } 2264 2265 JetEngine.switchCalendarMonth.bind( wrapper )() 2266 }, 2267 2268 updateDateSelectLabels: function( wrapper ) { 2269 let month = wrapper.querySelector( '.jet-calendar-caption__date-select.select-month' ), 2270 year = wrapper.querySelector( '.jet-calendar-caption__date-select.select-year' ); 2271 2272 if ( ! month || ! year ) { 2273 return false; 2274 } 2275 2276 let monthLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-month' ), 2277 yearLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-year' ); 2278 2279 wrapper.setAttribute( 'data-month', month.value + ' ' + year.value ); 2280 2281 const monthOption = month.querySelector( `option[value="${month.value}"]` ), 2282 yearOption = year.querySelector( `option[value="${year.value}"]` ); 2283 2284 monthLabel.innerHTML = monthOption.innerHTML; 2285 yearLabel.innerHTML = yearOption.innerHTML; 2286 2287 return true; 2288 }, 2289 2290 switchCalendarMonth: function( $event ) { 2291 2292 var $this = $( this ), 2293 $calendar = $this.closest( '.jet-calendar' ), 2294 $widget = $this.closest( '.elementor-widget-jet-listing-calendar' ), 2295 widgetID = $widget.closest( '.elementor-widget' ).data( 'id' ), 2296 settings = $calendar.data( 'settings' ), 2297 post = $calendar.data( 'post' ), 2298 month = $this.data( 'month' ); 2299 2300 settings = JetEngine.ensureJSON( settings ); 2301 2302 if ( this.classList.contains( 'nav-link-prev' ) ) { 2303 settings['__switch_direction'] = -1; 2304 } else if ( this.classList.contains( 'nav-link-next' ) ) { 2305 settings['__switch_direction'] = 1; 2306 } else { 2307 settings['__switch_direction'] = 0; 2308 } 2309 2310 let widgetType = 'elementor'; 2311 2312 // Context Gutenberg 2313 if ( ! $widget.length ) { 2314 $widget = $calendar.closest( '.jet-listing-calendar-block' ); 2315 widgetType = 'block'; 2316 } 2317 2318 // Context Bricks 2319 if ( ! $widget.length ) { 2320 $widget = $calendar.closest( '.brxe-jet-listing-calendar' ); 2321 widgetID = $widget.data( 'element-id' ); 2322 widgetType = 'bricks'; 2323 } 2324 2325 JetEngine.calendarCache.modifyJetSmartFiltersSetiings( $widget, widgetType, month ); 2326 2327 const cacheId = $calendar.data( 'cache-id' ) || false, 2328 cacheTimeout = ( settings['cache_timeout'] ?? 0 ) * 1000; 2329 2330 if ( cacheId && cacheTimeout ) { 2331 2332 JetEngine.calendarCache.deleteExpiredEntries( cacheId, cacheTimeout ); 2333 2334 // Remove the 'listening' and 'brx-open' classes from all matched elements to prevent 2335 // reinitialization issues in the accordion. 2336 if ( window.bricksIsFrontend ) { 2337 $calendar.find('.accordion-item.listening, .brxe-accordion-nested > .listening') 2338 .removeClass('listening brx-open'); 2339 } 2340 2341 JetEngine.calendarCache.update( cacheId, settings['prev_month'], $calendar.prop('outerHTML'), settings ); 2342 2343 const cached = JetEngine.calendarCache.get( cacheId, month ); 2344 2345 if ( cached?.length && cached[0] && ! JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) { 2346 let replacement = $( cached[0] ); 2347 replacement.removeClass( 'jet-calendar-loading' ); 2348 $calendar.replaceWith( replacement[0] ); 2349 JetEngine.initElementsHandlers( $widget ); 2350 JetEngine.updateDateSelectLabels( $widget[0] ); 2351 // Re-init Bricks scripts 2352 JetEngine.reinitBricksScripts( widgetID ); 2353 2354 $( document ).trigger( 'jet-engine-request-calendar-cached', [ $widget ] ); 2355 2356 return; 2357 } 2358 } 2359 2360 $calendar.addClass( 'jet-calendar-loading' ); 2361 2362 JetEngine.currentRequest = { 2363 jet_engine_action: 'jet_engine_calendar_get_month', 2364 month: month, 2365 settings: settings, 2366 post: post, 2367 }; 2368 2369 $( document ).trigger( 'jet-engine-request-calendar' ); 2370 2371 $.ajax({ 2372 url: JetEngineSettings.ajaxlisting, 2373 type: 'POST', 2374 dataType: 'json', 2375 data: JetEngine.currentRequest, 2376 }).done( function( response ) { 2377 if ( response.success ) { 2378 $calendar.replaceWith( response.data.content ); 2379 2380 if ( cacheId && cacheTimeout ) { 2381 JetEngine.calendarCache.set( cacheId, month, response.data.content, settings ); 2382 } 2383 2384 JetEngine.initElementsHandlers( $widget ); 2385 // Re-init Bricks scripts 2386 JetEngine.reinitBricksScripts( widgetID ); 2387 2388 $( document ).trigger( 'jet-engine-request-calendar-done', [ $widget ] ); 2389 } 2390 $calendar.removeClass( 'jet-calendar-loading' ); 2391 } ); 2392 }, 2393 2394 initElementsHandlers: function( $selector ) { 2395 2396 // Actual init 2397 window.JetPlugins.init( $selector ); 2398 2399 // Legacy Elementor-only init 2400 $selector.find( '[data-element_type]' ).each( function() { 2401 2402 var $this = $( this ), 2403 elementType = $this.data( 'element_type' ); 2404 2405 if ( !elementType ) { 2406 return; 2407 } 2408 2409 if ( ! window?.elementorFrontend?.hooks?.doAction ) { 2410 return; 2411 } 2412 2413 if ( 'widget' === elementType ) { 2414 elementType = $this.data( 'widget_type' ); 2415 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ ); 2416 } 2417 2418 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ ); 2419 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ ); 2420 2421 } ); 2422 2423 if ( window.elementorFrontend ) { 2424 const elementorLazyLoad = new Event( "elementor/lazyload/observe" ); 2425 document.dispatchEvent( elementorLazyLoad ); 2426 } 2427 2428 if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) { 2429 $selector.find( '.jet-popup-attach-event-inited' ).removeClass( 'jet-popup-attach-event-inited' ); 2430 window.JetPopupFrontend.initAttachedPopups( $selector ); 2431 } 2432 2433 }, 2434 2435 getElementorElementSettings: function( $scope ) { 2436 2437 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) { 2438 return JetEngine.getEditorElementSettings( $scope ); 2439 } 2440 2441 return $scope.data( 'settings' ) || {}; 2442 }, 2443 2444 getEditorElementSettings: function( $scope ) { 2445 var modelCID = $scope.data( 'model-cid' ), 2446 elementData; 2447 2448 if ( ! modelCID ) { 2449 return {}; 2450 } 2451 2452 if ( ! window.elementorFrontend.hasOwnProperty( 'config' ) ) { 2453 return {}; 2454 } 2455 2456 if ( ! window.elementorFrontend.config.hasOwnProperty( 'elements' ) ) { 2457 return {}; 2458 } 2459 2460 if ( ! window.elementorFrontend.config.elements.hasOwnProperty( 'data' ) ) { 2461 return {}; 2462 } 2463 2464 elementData = window.elementorFrontend.config.elements.data[ modelCID ]; 2465 2466 if ( ! elementData ) { 2467 return {}; 2468 } 2469 2470 return elementData.toJSON(); 2471 }, 2472 2473 debounce: function( threshold, callback ) { 2474 var timeout; 2475 2476 return function debounced( $event ) { 2477 function delayed() { 2478 callback.call( this, $event ); 2479 timeout = null; 2480 } 2481 2482 if ( timeout ) { 2483 clearTimeout( timeout ); 2484 } 2485 2486 timeout = setTimeout( delayed, threshold ); 2487 }; 2488 }, 2489 2490 updateAddedStyles: function() { 2491 if ( window.JetEngineSettings && window.JetEngineSettings.addedPostCSS ) { 2492 $.each( window.JetEngineSettings.addedPostCSS, function( ind, cssID ) {
2493 JetEngine.addedStyles.push( 'elementor-post-' + cssID ); 2494 JetEngine.addedPostCSS.push( cssID ); 2495 } ); 2496 } 2497 }, 2498 2499 enqueueAssetsFromResponse: function( response ) { 2500 if ( response.data.scripts ) { 2501 JetEngine.enqueueScripts( response.data.scripts ); 2502 } 2503 2504 if ( response.data.styles ) { 2505 JetEngine.enqueueStyles( response.data.styles ); 2506 } 2507 }, 2508 2509 enqueueScripts: function( scripts ) { 2510 $.each( scripts, function( handle, scriptHtml ) { 2511 JetEngine.enqueueScript( handle, scriptHtml ) 2512 } ); 2513 }, 2514 2515 enqueueStyles: function( styles ) { 2516 $.each( styles, function( handle, styleHtml ) { 2517 JetEngine.enqueueStyle( handle, styleHtml ) 2518 } ); 2519 }, 2520 2521 enqueueScript: function( handle, scriptHtml ) { 2522 2523 if ( -1 !== JetEngine.addedScripts.indexOf( handle ) ) { 2524 return; 2525 } 2526 2527 if ( ! scriptHtml ) { 2528 return; 2529 } 2530 2531 var selector = 'script[id="' + handle + '-js"]'; 2532 2533 if ( $( selector ).length ) { 2534 return; 2535 } 2536 2537 //$( 'body' ).append( scriptHtml ); 2538 2539 var scriptsTags = scriptHtml.match( /<script[\s\S]*?<\/script>/gm ); 2540 2541 if ( scriptsTags.length ) { 2542 2543 for ( var i = 0; i < scriptsTags.length; i++ ) { 2544 2545 JetEngine.assetsPromises.push( 2546 new Promise( function( resolve, reject ) { 2547 2548 var $tag = $( scriptsTags[i] ); 2549 2550 if ( $tag[0].src ) { 2551 2552 var tag = document.createElement( 'script' ); 2553 2554 tag.type = $tag[0].type; 2555 tag.src = $tag[0].src; 2556 tag.id = $tag[0].id; 2557 tag.async = false; 2558 tag.onload = function() { 2559 resolve(); 2560 }; 2561 2562 document.body.append( tag ); 2563 } else { 2564 $( 'body' ).append( scriptsTags[i] ); 2565 resolve(); 2566 } 2567 } ) 2568 ); 2569 } 2570 } 2571 2572 JetEngine.addedScripts.push( handle ); 2573 }, 2574 2575 enqueueStyle: function( handle, styleHtml ) { 2576 2577 if ( -1 !== handle.indexOf( 'google-fonts' ) ) { 2578 JetEngine.enqueueGoogleFonts( handle, styleHtml ); 2579 return; 2580 } 2581 2582 if ( -1 !== JetEngine.addedStyles.indexOf( handle ) ) { 2583 return; 2584 } 2585 2586 var selector = 'link[id="' + handle + '-css"],style[id="' + handle + '"]'; 2587 2588 if ( $( selector ).length ) { 2589 return; 2590 } 2591 2592 $( 'head' ).append( styleHtml ); 2593 2594 JetEngine.addedStyles.push( handle ); 2595 2596 if ( -1 !== handle.indexOf( 'elementor-post' ) ) { 2597 var postID = handle.replace( 'elementor-post-', '' ); 2598 JetEngine.addedPostCSS.push( postID ); 2599 } 2600 }, 2601 2602 enqueueGoogleFonts: function( handle, styleHtml ) { 2603 2604 var selector = 'link[id="' + handle + '-css"]'; 2605 2606 if ( $( selector ).length ) {} 2607 2608 $( 'head' ).append( styleHtml ); 2609 }, 2610 2611 isFrontend: function () { 2612 // Check the Elementor 2613 if (typeof window.elementorFrontend !== 'undefined') { 2614 return !window.elementorFrontend.isEditMode(); 2615 } 2616 2617 // Check the Bricks 2618 if (typeof window.bricksIsFrontend !== 'undefined') { 2619 return window.bricksIsFrontend; 2620 } 2621 2622 // If no builders are found, we assume it is frontend. 2623 return true; 2624 }, 2625 2626 reinitBricksScripts: function (elementId) { 2627 if (!window.bricksIsFrontend) { 2628 return; 2629 } 2630 2631 document.dispatchEvent( 2632 new CustomEvent("bricks/ajax/query_result/displayed", { 2633 detail: { 2634 queryId: elementId || null 2635 } 2636 }) 2637 ); 2638 }, 2639 2640 filters: ( function() { 2641 2642 var callbacks = {}; 2643 2644 return { 2645 2646 addFilter: function( name, callback ) { 2647 2648 if ( ! callbacks.hasOwnProperty( name ) ) { 2649 callbacks[name] = []; 2650 } 2651 2652 callbacks[name].push(callback); 2653 2654 }, 2655 2656 applyFilters: function( name, value, args ) { 2657 2658 if ( ! callbacks.hasOwnProperty( name ) ) { 2659 return value; 2660 } 2661 2662 if ( args === undefined ) { 2663 args = []; 2664 } 2665 2666 var container = callbacks[ name ]; 2667 var cbLen = container.length; 2668 2669 for (var i = 0; i < cbLen; i++) { 2670 if (typeof container[i] === 'function') { 2671 value = container[i](value, args); 2672 } 2673 } 2674 2675 return value; 2676 } 2677 2678 }; 2679 2680 })() 2681 2682 }; 2683 2684 $( window ).on( 'elementor/frontend/init', JetEngine.init ); 2685 2686 window.JetEngine = JetEngine; 2687 2688 document.addEventListener( 'jet-smart-filters/inited', function() { 2689 window.JetSmartFilters.events.subscribe( 'ajaxFilters/updated', function( provider, queryId ) { 2690 window.JetEngine.initFrontStores( window.JetSmartFilters?.filterGroups?.[ provider + '/' + queryId ]?.$provider); 2691 } ); 2692 } ); 2693 2694 JetEngine.commonInit(); 2695 2696 window.addEventListener( 'DOMContentLoaded', function() { 2697 setTimeout( () => JetEngine.initBlocks() ); 2698 JetEngine.initDone = true; 2699 } ); 2700 2701 window.jetEngineBricks = function() { 2702 JetEngine.initBricks(); 2703 } 2704 2705 $( window ).trigger( 'jet-engine/frontend/loaded' ); 2706 2707 const initFilterConflictHandler = function() { 2708 const conflictHandler = class FilterConflictHandler { 2709 2710 isResolving = false;
2711 2712 constructor() { 2713 this.init(); 2714 } 2715 2716 init( e ) { 2717 JetSmartFilters.events.subscribe( 'fiter/change', ( filter ) => { 2718 if ( this.isResolving || filter?.filterConflictHandlerBlocked ) { 2719 return; 2720 } 2721 2722 this.isResolving = true; 2723 2724 if ( ! [ 'map-sync', 'user-geolocation', 'location-distance' ].includes( filter?.name ) ) { 2725 return; 2726 } 2727 2728 let conflictingTypes = []; 2729 2730 switch ( filter.name ) { 2731 case 'map-sync': 2732 conflictingTypes = [ 'user-geolocation', 'location-distance' ]; 2733 break; 2734 case 'location-distance': 2735 conflictingTypes = [ 'map-sync', 'user-geolocation' ]; 2736 break; 2737 default: 2738 conflictingTypes = [ 'map-sync' ]; 2739 } 2740 2741 this.resetConflictingFilters( filter, conflictingTypes ); 2742 } ); 2743 } 2744 2745 resetConflictingFilters( filter, conflictingTypes ) { 2746 for ( const conflictingFilter of this.getFilters( filter, conflictingTypes ) ) { 2747 conflictingFilter.reset(); 2748 conflictingFilter.dataValue = false; 2749 conflictingFilter.wasChanged ? conflictingFilter.wasChanged() : conflictingFilter.wasСhanged(); 2750 } 2751 2752 this.isResolving = false; 2753 } 2754 2755 getFilters( filter, types ) { 2756 if ( ! types.length ) { 2757 return []; 2758 } 2759 2760 let filters = []; 2761 2762 filter.filterGroup.filters.forEach( 2763 ( f ) => { 2764 if ( ! types.includes( f.name ) ) { 2765 return; 2766 } 2767 2768 filters.push( f ); 2769 } 2770 ); 2771 2772 return filters; 2773 } 2774 2775 }; 2776 2777 new conflictHandler(); 2778 2779 } 2780 2781 document.addEventListener( 'jet-smart-filters/inited', initFilterConflictHandler ); 2782 2783}( 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.