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