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.post__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.post__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 ( $gridItem.length ) { 911 popupData['postId'] = $gridItem.data( 'post-id' ); 912 filterProvider = 'jet-engine'; 913 } else if ( $calendarItem.length ) { 914 popupData['postId'] = $calendarItem.data( 'post-id' ); 915 filterProvider = 'jet-engine-calendar'; 916 } else if ( $itemObject ) { 917 popupData['postId'] = $itemObject.data( 'item-object' ); 918 } else if ( window.elementorFrontendConfig && window.elementorFrontendConfig.post ) { 919 popupData['postId'] = window.elementorFrontendConfig.post.id; 920 } 921 922 if ( window.JetEngineFormsEditor && window.JetEngineFormsEditor.hasEditor ) { 923 popupData['hasEditor'] = true; 924 } 925 926 // Add the filtered query to the popup data 927 if ( window.JetSmartFilters ) { 928 929 switch ( filterProvider ) { 930 case 'jet-engine': 931 var nav = $gridItems.data( 'nav' ); 932 933 if ( nav.widget_settings?._element_id ) { 934 filterQueryId = nav.widget_settings._element_id; 935 } 936 break; 937 938 case 'jet-engine-calendar': 939 var settings = $calendarItem.closest( '.jet-listing-calendar' ).data( 'settings' ); 940 941 if ( settings._element_id ) { 942 filterQueryId = settings._element_id; 943 } 944 break; 945 } 946 947 filterProvider = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterProvider', filterProvider, $scope, widgetData ); 948 filterQueryId = window.JetPlugins.hooks.applyFilters( 'jet-engine.prepareJetPopupData.filterQueryId', filterQueryId, $scope, widgetData ); 949 950 if ( popupData.queryId && filterProvider 951 && window.JetSmartFilters?.filterGroups?.[ filterProvider + '/' + filterQueryId ]?.currentQuery 952 ) { 953 popupData['filtered_query'] = window.JetSmartFilters.filterGroups[ filterProvider + '/' + filterQueryId ].currentQuery; 954 } 955 } 956 957 } 958 959 return popupData; 960 961 }, 962 963 showCalendarEvent: function( event ) { 964 965 var $this = $( this ), 966 $day = $this.closest( '.jet-calendar-week__day' ), 967 $week = $day.closest( '.jet-calendar-week' ), 968 $events = $day.find( '.jet-calendar-week__day-content' ), 969 activeClass = 'calendar-event-active'; 970 971 if ( $day.hasClass( activeClass ) ) { 972 $day.removeClass( activeClass ); 973 JetEngine.activeCalendarDay.remove(); 974 JetEngine.activeCalendarDay = null; 975 return; 976 } 977 978 if ( JetEngine.activeCalendarDay ) { 979 JetEngine.activeCalendarDay.remove(); 980 $( '.' + activeClass ).removeClass( activeClass ); 981 JetEngine.activeCalendarDay = null; 982 } 983 984 $day.addClass( 'calendar-event-active' ); 985 986 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>' ); 987 988 // Need for re-init popup events 989 JetEngine.activeCalendarDay.find( '.jet-popup-attach-event-inited' ).removeClass( 'jet-popup-attach-event-inited' ); 990 JetEngine.initElementsHandlers( JetEngine.activeCalendarDay ); 991 992 JetEngine.activeCalendarDay.insertAfter( $week ); 993 994 }, 995 996 widgetListingGrid: function( $scope ) { 997 998 var widgetID = $scope.closest( '.elementor-widget' ).data( 'id' ),
999 $wrapper = $scope.find( '.jet-listing-grid' ).first(), 1000 hasLazyLoad = $wrapper.hasClass( 'jet-listing-grid--lazy-load' ), 1001 $listing = $scope.find( '.jet-listing-grid__items' ).first(), 1002 $slider = $listing.parent( '.jet-listing-grid__slider' ), 1003 $masonry = $listing.hasClass( 'jet-listing-grid__masonry' ) ? $listing : false, 1004 navSettings = $listing.data( 'nav' ), 1005 masonryGrid = false, 1006 listingType = 'elementor'; 1007 1008 if ( ! widgetID ) { 1009 widgetID = $scope.data( 'element-id' ); 1010 listingType = $scope.data( 'listing-type' ); 1011 } 1012 1013 navSettings = JetEngine.ensureJSON( navSettings ); 1014 1015 if ( hasLazyLoad ) { 1016 1017 var lazyLoadOptions = $wrapper.data( 'lazy-load' ), 1018 $container = $scope.find( '.elementor-widget-container' ), 1019 widgetSettings = false; 1020 1021 if ( ! $container.length ) { 1022 $container = $scope; 1023 } 1024 1025 // Get widget settings from `elementorFrontend` in Editor. 1026 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() 1027 && $wrapper.closest( '.elementor[data-elementor-type]' ).hasClass( 'elementor-edit-mode' ) 1028 ) { 1029 widgetSettings = JetEngine.getEditorElementSettings( $scope.closest( '.elementor-widget' ) ); 1030 widgetID = false; // for avoid get widget settings from document in editor 1031 } 1032 1033 if ( ! widgetSettings ) { 1034 widgetSettings = $scope.data( 'widget-settings' ); 1035 } 1036 1037 JetEngine.lazyLoadListing( { 1038 container: $container, 1039 elementID: widgetID, 1040 postID: lazyLoadOptions.post_id, 1041 queriedID: lazyLoadOptions.queried_id || false, 1042 offset: lazyLoadOptions.offset || '0px', 1043 query: lazyLoadOptions.query || {}, 1044 listingType: listingType, 1045 widgetSettings: widgetSettings, 1046 extraProps: lazyLoadOptions.extra_props || false, 1047 } ); 1048 1049 return; 1050 } 1051 1052 if ( $slider.length ) { 1053 JetEngine.initSlider( $slider ); 1054 } 1055 1056 if ( $masonry && $masonry.length ) { 1057 1058 JetEngine.initMasonry( $masonry ); 1059 1060 /* Keep masonry re-init for Bricks */ 1061 if ( $scope.hasClass( 'brxe-jet-engine-listing-grid' ) ) { 1062 $( window ).on( 'load', function() { 1063 JetEngine.runMasonry( $masonry ); 1064 } ); 1065 } 1066 1067 } 1068 1069 if ( navSettings && navSettings.enabled ) { 1070 1071 JetEngine.loadMoreListing( { 1072 container: $listing, 1073 settings: navSettings, 1074 masonry: $masonry, 1075 slider: $slider, 1076 elementID: widgetID, 1077 } ); 1078 1079 } 1080 1081 // Init elements handlers in editor. 1082 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() 1083 && $wrapper.closest( '.elementor-element-edit-mode' ).length 1084 ) { 1085 JetEngine.initElementsHandlers( $wrapper ); 1086 } 1087 1088 }, 1089 1090 initMasonry: function( $masonry, masonrySettings ) { 1091 imagesLoaded( $masonry, function() { 1092 JetEngine.runMasonry( $masonry, masonrySettings ); 1093 } ); 1094 }, 1095 1096 runMasonry: function( $masonry, masonrySettings ) { 1097 var defaultSettings = { 1098 itemSelector: '> .jet-listing-grid__item', 1099 columnsKey: 'columns', 1100 }; 1101 1102 masonrySettings = masonrySettings || {}; 1103 masonrySettings = $.extend( {}, defaultSettings, masonrySettings ); 1104 1105 var $eWidget = $masonry.closest( '.elementor-widget' ), 1106 $items = $( masonrySettings.itemSelector, $masonry ), 1107 options = $masonry.data( 'masonry-grid-options' ) || {}; 1108 1109 options = JetEngine.ensureJSON( options ); 1110 1111 // Reset masonry 1112 $items.css( { 1113 marginTop: '' 1114 } ); 1115 1116 // Bricks margin 1117 const { gap } = options; 1118 let margin = null; 1119 1120 if ( gap ) { 1121 margin = { 1122 x: +gap.horizontal, 1123 y: +gap.vertical, 1124 }; 1125 } 1126 1127 var args = { 1128 container: $masonry[0], 1129 margin: margin ? margin : 0, 1130 }; 1131 1132 if ( $eWidget.length ) { 1133 var settings = JetEngine.getElementorElementSettings( $eWidget ), 1134 breakpoints = {}, 1135 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints, 1136 columnsKey = masonrySettings.columnsKey; 1137 1138 args.columns = settings[columnsKey + '_widescreen'] ? +settings[columnsKey + '_widescreen'] : +settings[columnsKey]; 1139
1140 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1141 1142 if ( settings[columnsKey + '_' + breakpointName] ) { 1143 if ( 'widescreen' === breakpointName ) { 1144 breakpoints[eBreakpoints[breakpointName].value - 1] = +settings[columnsKey]; 1145 } else { 1146 breakpoints[eBreakpoints[breakpointName].value] = +settings[columnsKey + '_' + breakpointName]; 1147 } 1148 } 1149 1150 } ); 1151 1152 args.breakAt = breakpoints; 1153 1154 } else { 1155 args.columns = options.columns.desktop; 1156 args.breakAt = { 1157 1025: options.columns.tablet, 1158 768: options.columns.mobile, 1159 }; 1160 } 1161 1162 var masonryInstance = Macy( args ); 1163 1164 masonryInstance.runOnImageLoad( function () { 1165 masonryInstance.recalculate( true ); 1166 }, true ); 1167 1168 // Event to recalculate current masonry listings. 1169 $masonry.on( 'jet-engine/listing/recalculate-masonry-listing', function() { 1170 masonryInstance.runOnImageLoad( function () { 1171 masonryInstance.recalculate( true ); 1172 }, true ); 1173 } ); 1174 1175 // Event to recalculate all masonry listings. 1176 $( document ).on( 'jet-engine/listing/recalculate-masonry', function() { 1177 masonryInstance.recalculate( true ); 1178 } ); 1179 1180 }, 1181 1182 ajaxGetListing: function( options, doneCallback, failCallback ) { 1183 1184 var container = options.container || false, 1185 handler = options.handler || false, 1186 masonry = options.masonry || false, 1187 slider = options.slider || false, 1188 append = options.append || false, 1189 query = options.query || {}, 1190 widgetSettings = options.widgetSettings || {}, 1191 postID = options.postID || false, 1192 queriedID = options.queriedID || false, 1193 elementID = options.elementID || false, 1194 page = options.page || 1, 1195 preventCSS = options.preventCSS || false, 1196 listingType = options.listingType || false, 1197 extraProps = options.extraProps || false, 1198 isEditMode = window.elementorFrontend && window.elementorFrontend.isEditMode(); 1199 1200 doneCallback = doneCallback || function( response ) {}; 1201 1202 if ( ! container|| ! handler ) { 1203 return; 1204 } 1205 1206 if ( ! preventCSS ) { 1207 container.css({ 1208 pointerEvents: 'none', 1209 opacity: '0.5', 1210 cursor: 'default', 1211 }); 1212 } 1213 1214 var requestData = { 1215 action: 'jet_engine_ajax', 1216 handler: handler, 1217 query: query, 1218 widget_settings: widgetSettings, 1219 page_settings: { 1220 post_id: postID, 1221 queried_id: queriedID, 1222 element_id: elementID, 1223 page: page, 1224 }, 1225 listing_type: listingType, 1226 isEditMode: isEditMode, 1227 addedPostCSS: JetEngine.addedPostCSS 1228 }; 1229 1230 if ( extraProps ) { 1231 Object.assign( requestData, extraProps ); 1232 } 1233 1234 $.ajax({ 1235 url: JetEngineSettings.ajaxlisting, 1236 type: 'POST', 1237 dataType: 'json', 1238 data: requestData, 1239 }).done( function( response ) { 1240 1241 // container.removeAttr( 'style' ); 1242 1243 // Manual reset container style to prevent removal of masonry styles. 1244 if ( !preventCSS ) { 1245 container.css( { 1246 pointerEvents: '', 1247 opacity: '', 1248 cursor: '', 1249 } ); 1250 } 1251 1252 if ( response.success ) { 1253 1254 JetEngine.enqueueAssetsFromResponse( response ); 1255 1256 container.data( 'page', page ); 1257 1258 var $html = $( response.data.html ); 1259 1260 JetEngine.initFrontStores( $html ); 1261 1262 if ( slider && slider.length ) { 1263 1264 var $slider = slider.find( '> .jet-listing-grid__items' ); 1265 1266 if ( ! $slider.hasClass( 'slick-initialized' ) ) { 1267 1268 if ( append ) { 1269 container.append( $html ); 1270 } else { 1271 container.html( $html ); 1272 } 1273 1274 var itemsCount = container.find( '> .jet-listing-grid__item' ).length; 1275 1276 slider.addClass( 'jet-listing-grid__slider' ); 1277 JetEngine.initSlider( slider, { itemsCount: itemsCount } ); 1278 1279 } else { 1280 $html.each( function( index, el ) { 1281 $slider.slick( 'slickAdd', el ); 1282 }); 1283 } 1284 1285 } else { 1286 1287 if ( append ) { 1288 container.append( $html ); 1289 } else { 1290 container.html( $html ); 1291 } 1292 1293 if ( masonry && masonry.length ) { 1294 //JetEngine.initMasonry( masonry ); 1295 masonry.trigger( 'jet-engine/listing/recalculate-masonry-listing' ); 1296 } 1297 1298 } 1299 1300 // Re-init Bricks scripts 1301 JetEngine.reinitBricksScripts( elementID ); 1302 1303 Promise.all( JetEngine.assetsPromises ).then( function() { 1304 JetEngine.initElementsHandlers( $html ); 1305 JetEngine.assetsPromises = []; 1306 } ); 1307 1308 if ( response.data.fragments ) { 1309 for ( var selector in response.data.fragments ) { 1310 var $selector = $( selector ); 1311 1312 if ( $selector.length ) { 1313 $selector.html( response.data.fragments[ selector ] ); 1314 } 1315 } 1316 } 1317 } 1318 1319 $( document ).trigger( 'jet-engine/listing/ajax-get-listing/done', [ $html, options ] ); 1320 1321 } ).done( doneCallback ).fail( function() { 1322 container.removeAttr( 'style' ); 1323 if ( failCallback ) { 1324 failCallback.call(); 1325 } 1326 1327 } ); 1328 1329 }, 1330 1331 loadMoreListing: function( args ) { 1332 1333 var instance = { 1334 1335 setup: function() { 1336 this.container = args.container; 1337 this.masonry = args.masonry; 1338 this.slider = args.slider; 1339 this.settings = args.settings; 1340 this.elementID = args.elementID; 1341 1342 this.wrapper = this.container.closest( '.jet-listing-grid' ); 1343 1344 this.type = this.settings.type || 'click'; 1345 this.page = parseInt( this.container.data( 'page' ), 10 ) || 0; 1346 this.pages = parseInt( this.container.data( 'pages' ), 10 ) || 0; 1347 this.queriedID = this.container.data( 'queried-id' ) || false; 1348 }, 1349 1350 init: function() { 1351 1352 this.setup(); 1353 1354 switch ( this.type ) { 1355 case 'click': 1356 1357 this.handleMore(); 1358 1359 break; 1360 1361 case 'scroll': 1362 1363 if ( ( ! window.elementorFrontend || ! window.elementorFrontend.isEditMode() ) && ! this.slider.length ) { 1364 this.handleInfiniteScroll(); 1365 } 1366 1367 break; 1368 } 1369 }, 1370 1371 handleMore: function() { 1372 1373 if ( ! this.settings.more_el ) { 1374 return; 1375 } 1376 1377 var self = this, 1378 $button = $( this.settings.more_el ); 1379 1380 if ( ! $button.length ) { 1381 return; 1382 } 1383 1384 if ( ! this.pages || this.page === this.pages && ! window.elementor ) { 1385 $button.css( 'display', 'none' ); 1386 } else { 1387 $button.removeAttr( 'style' ); 1388 } 1389 1390 $( document ) 1391 .off( 'click', this.settings.more_el ) 1392 .on( 'click', this.settings.more_el, function( event ) { 1393 event.preventDefault(); 1394 1395 if ( ! self.pages || self.page >= self.pages) { 1396 $button.css( 'display', 'none' ); 1397 return; 1398 } 1399 1400 $button.css( { 1401 pointerEvents: 'none', 1402 opacity: '0.5', 1403 cursor: 'default', 1404 } ); 1405 1406 self.ajaxGetItems( function( response ) { 1407 $button.removeAttr( 'style' ); 1408 1409 if ( response.success && self.page === self.pages ) { 1410 $button.css( 'display', 'none' ); 1411 } 1412 }, function() { 1413 $button.button.removeAttr( 'style' ); 1414 } 1415 ); 1416 } ); 1417 }, 1418 1419 handleInfiniteScroll: function() { 1420 1421 if ( this.container.hasClass( 'jet-listing-not-found' ) ) { 1422 return; 1423 } 1424 1425 if ( ! this.pages || this.page === this.pages ) { 1426 return; 1427 } 1428 1429 var self = this, 1430 $trigger = this.wrapper.find( '.jet-listing-grid__loader' ), 1431 offset = '0%'; 1432 1433 if ( ! $trigger.length ) { 1434 $trigger = $( '<div>', { 1435 class: 'jet-listing-grid__loading-trigger' 1436 } ); 1437 1438 this.wrapper.append( $trigger ); 1439 } 1440 1441 // Prepare offset value. 1442 if ( this.settings.widget_settings && this.settings.widget_settings.load_more_offset ) { 1443 var offsetValue = this.settings.widget_settings.load_more_offset; 1444 1445 switch ( typeof offsetValue ) { 1446 case 'object': 1447 var size = offsetValue.size ? offsetValue.size : '0', 1448 unit = offsetValue.unit ? offsetValue.unit : 'px'; 1449 1450 offset = size + unit; 1451 break; 1452 1453 case 'number': 1454 case 'string': 1455 offset = offsetValue + 'px'; 1456 break; 1457 } 1458 } 1459 1460 var observer = new IntersectionObserver( 1461 function( entries, observer ) { 1462 1463 if ( entries[0].isIntersecting ) { 1464 1465 self.ajaxGetItems( function() { 1466 1467 // Re-init observer if the last page is not loaded 1468 if ( self.page !== self.pages ) { 1469 setTimeout( function() { 1470 observer.observe( entries[0].target ); 1471 }, 250 ); 1472 } 1473 1474 } ); 1475 1476 // Detach observer 1477 observer.unobserve( entries[0].target ); 1478 } 1479 }, 1480 { 1481 rootMargin: '0% 0% ' + offset + ' 0%', 1482 } 1483 ); 1484 1485 observer.observe( $trigger[0] ); 1486 }, 1487 1488 ajaxGetItems: function( doneCallback, failCallback ) { 1489 var self = this; 1490 1491 this.page++; 1492 1493 this.wrapper.addClass( 'jet-listing-grid-loading' ); 1494 1495 JetEngine.ajaxGetListing( { 1496 handler: 'listing_load_more', 1497 container: this.container, 1498 masonry: this.masonry, 1499 slider: this.slider, 1500 append: true, 1501 query: this.settings.query, 1502 widgetSettings: this.settings.widget_settings, 1503 page: this.page, 1504 elementID: this.elementID, 1505 queriedID: this.queriedID, 1506 preventCSS: !! this.wrapper.find( '.jet-listing-grid__loader' ).length, // Prevent CSS if listing has the loader. 1507 }, function( response ) { 1508 1509 JetEngine.lazyLoading = false;
1510 self.wrapper.removeClass( 'jet-listing-grid-loading' ); 1511 1512 if ( doneCallback ) { 1513 doneCallback( response ); 1514 } 1515 1516 $( document ).trigger( 'jet-engine/listing-grid/after-load-more', [args, response] ); 1517 1518 }, function() { 1519 1520 JetEngine.lazyLoading = false; 1521 self.wrapper.removeClass( 'jet-listing-grid-loading' ); 1522 1523 if ( failCallback ) { 1524 failCallback(); 1525 } 1526 1527 } ); 1528 }, 1529 }; 1530 1531 instance.init(); 1532 }, 1533 1534 lazyLoadListing: function( args ) { 1535 1536 var $wrapper = args.container.find( '.jet-listing-grid' ), 1537 observer = new IntersectionObserver( 1538 function( entries, observer ) { 1539 1540 if ( entries[0].isIntersecting ) { 1541 1542 JetEngine.lazyLoading = true; 1543 1544 if ( ! $wrapper.length ) { 1545 $wrapper = args.container; 1546 } 1547 1548 $wrapper.addClass( 'jet-listing-grid-loading' ); 1549 1550 JetEngine.ajaxGetListing( { 1551 handler: 'get_listing', 1552 container: args.container, 1553 masonry: false, 1554 slider: false, 1555 append: false, 1556 elementID: args.elementID, 1557 postID: args.postID, 1558 queriedID: args.queriedID, 1559 query: args.query, 1560 widgetSettings: args.widgetSettings, 1561 listingType: args.listingType, 1562 preventCSS: true, 1563 extraProps: args.extraProps, 1564 }, function( response ) { 1565 1566 $wrapper.removeClass( 'jet-listing-grid-loading' ); 1567 1568 var $widget = args.container.closest( '.elementor-widget' ); 1569 1570 if ( ! $widget.length ) { 1571 $widget = args.container.closest( '.jet-listing-grid--blocks' ); 1572 } 1573 1574 if ( ! $widget.length ) { 1575 $widget = args.container; 1576 } 1577 1578 if ( $widget.length ) { 1579 $widget.find( '.jet-listing-grid' ).first().removeClass( 'jet-listing-grid--lazy-load' ); 1580 } 1581 1582 JetEngine.widgetListingGrid( $widget ); 1583 JetEngine.loadFrontStoresItems( $widget ); 1584 JetEngine.lazyLoading = false; 1585 1586 let needReInitFilters = false; 1587 let isFrontend = JetEngine.isFrontend(); 1588 1589 if ( isFrontend && window.JetSmartFilterSettings ) { 1590 1591 if ( response.data.filters_data ) { 1592 $.each( response.data.filters_data, function( param, data ) { 1593 if ( 'extra_props' === param ) { 1594 window.JetSmartFilterSettings[ param ] = $.extend( 1595 {}, 1596 window.JetSmartFilterSettings[ param ], 1597 data 1598 ); 1599 } else { 1600 if ( window.JetSmartFilterSettings[ param ]['jet-engine'] ) { 1601 window.JetSmartFilterSettings[ param ]['jet-engine'] = $.extend( 1602 {}, 1603 window.JetSmartFilterSettings[ param ]['jet-engine'], 1604 data 1605 ); 1606 } else { 1607 window.JetSmartFilterSettings[ param ]['jet-engine'] = data; 1608 } 1609 } 1610 }); 1611 1612 needReInitFilters = true; 1613 } 1614 1615 if ( response.data.indexer_data ) { 1616 const { 1617 provider = false, 1618 query = {} 1619 } = response.data.indexer_data; 1620 1621 window.JetSmartFilters.setIndexedData( provider, query ); 1622 } 1623 } 1624 1625 // ReInit filters 1626 if ( needReInitFilters && window.JetSmartFilters ) { 1627 window.JetSmartFilters.reinitFilters(); 1628 } 1629 1630 $( document ).trigger( 'jet-engine/listing-grid/after-lazy-load', [ args, response ] ); 1631 1632 }, function() { 1633 JetEngine.lazyLoading = false; 1634 1635 if ( ! $wrapper.length ) { 1636 $wrapper = args.container; 1637 } 1638 1639 $wrapper.removeClass( 'jet-listing-grid-loading' ); 1640 } ); 1641 1642 // Detach observer after the first load the listing 1643 observer.unobserve( entries[0].target ); 1644 } 1645 }, 1646 { 1647 rootMargin: '0% 0% ' + args.offset + ' 0%' 1648 } 1649 ); 1650 1651 observer.observe( args.container[0] ); 1652 }, 1653 1654 ensureJSON: function( maybeJSON ) { 1655 1656 if ( ! maybeJSON ) { 1657 return maybeJSON; 1658 } 1659 1660 if ( 'string' === typeof maybeJSON ) { 1661 console.log( maybeJSON ); 1662 //maybeJSON = JSON.parse( maybeJSON ); 1663 } 1664 1665 return maybeJSON; 1666 1667 }, 1668 1669 initSlider: function( $slider, customOptions ) { 1670 var $eWidget = $slider.closest( '.elementor-widget' ), 1671 options = $slider.data( 'slider_options' ), 1672 windowWidth = $( window ).width(), 1673 tabletBP = 1025, 1674 mobileBP = 768, 1675 tabletSlides, mobileSlides, defaultOptions, slickOptions; 1676 1677 options = JetEngine.ensureJSON( options ); 1678 1679 customOptions = customOptions || {}; 1680 1681 options = $.extend( {}, options, customOptions ); 1682 1683 if ( $eWidget.length ) { 1684 1685 var settings = JetEngine.getElementorElementSettings( $eWidget ), 1686 responsive = [], 1687 deviceMode = elementorFrontend.getCurrentDeviceMode(), 1688 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints; 1689 1690 options.slidesToShow = settings.columns_widescreen ? +settings.columns_widescreen : +settings.columns; 1691
1692 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1693 1694 if ( settings['columns_' + breakpointName] ) { 1695 1696 if ( 'widescreen' === breakpointName ) { 1697 1698 responsive.push( { 1699 breakpoint: eBreakpoints[breakpointName].value, 1700 settings: { 1701 slidesToShow: +settings['columns'], 1702 } 1703 } ); 1704 1705 } else { 1706 var breakpointSettings = { 1707 breakpoint: eBreakpoints[breakpointName].value + 1, 1708 settings: { 1709 slidesToShow: +settings['columns_' + breakpointName], 1710 } 1711 }; 1712 1713 if ( options.slidesToScroll > breakpointSettings.settings.slidesToShow ) { 1714 breakpointSettings.settings.slidesToScroll = breakpointSettings.settings.slidesToShow; 1715 } 1716 1717 // if ( 'mobile' === breakpointName ) { 1718 // breakpointSettings.settings.slidesToScroll = 1; 1719 // } 1720 1721 responsive.push( breakpointSettings ); 1722 } 1723 } 1724 1725 } ); 1726 1727 options.responsive = responsive; 1728 1729 } else { 1730 1731 // Ensure we have at least some options to avoid errors 1732 if ( ! options.slidesToShow ) { 1733 options.slidesToShow = { 1734 desktop: 3, 1735 tablet: 1, 1736 mobile: 1, 1737 } 1738 } 1739 1740 if ( options.itemsCount <= options.slidesToShow.desktop && windowWidth >= tabletBP ) { // 1025 - ... 1741 $slider.removeClass( 'jet-listing-grid__slider' ); 1742 return; 1743 } else if ( options.itemsCount <= options.slidesToShow.tablet && tabletBP > windowWidth && windowWidth >= mobileBP ) { // 768 - 1024 1744 $slider.removeClass( 'jet-listing-grid__slider' ); 1745 return; 1746 } else if ( options.itemsCount <= options.slidesToShow.mobile && windowWidth < mobileBP ) { // 0 - 767 1747 $slider.removeClass( 'jet-listing-grid__slider' ); 1748 return; 1749 } 1750 1751 if ( options.slidesToShow.tablet ) { 1752 tabletSlides = options.slidesToShow.tablet; 1753 } else { 1754 tabletSlides = 1 === options.slidesToShow.desktop ? 1 : 2; 1755 } 1756 1757 if ( options.slidesToShow.mobile ) { 1758 mobileSlides = options.slidesToShow.mobile; 1759 } else { 1760 mobileSlides = 1; 1761 } 1762 1763 options.slidesToShow = options.slidesToShow.desktop; 1764 1765 options.responsive = [ 1766 { 1767 breakpoint: 1025, 1768 settings: { 1769 slidesToShow: tabletSlides, 1770 slidesToScroll: options.slidesToScroll > tabletSlides ? tabletSlides : options.slidesToScroll 1771 } 1772 }, 1773 { 1774 breakpoint: 768, 1775 settings: { 1776 slidesToShow: mobileSlides, 1777 slidesToScroll: 1 1778 } 1779 } 1780 ]; 1781 } 1782 1783 defaultOptions = { 1784 customPaging: function( slider, i ) { 1785 return $( '<span />' ).text( i + 1 ).attr( 'role', 'tab' ); 1786 }, 1787 slide: '.jet-listing-grid__item', 1788 dotsClass: 'jet-slick-dots', 1789 }; 1790 1791 slickOptions = $.extend( {}, defaultOptions, options ); 1792 1793 var $sliderItems = $slider.find( '> .jet-listing-grid__items' ); 1794 1795 if ( slickOptions.infinite ) { 1796 $sliderItems.on( 'init', function() { 1797 var $items = $( this ), 1798 $clonedSlides = $( '> .slick-list > .slick-track > .slick-cloned.jet-listing-grid__item', $items ); 1799 1800 if ( !$clonedSlides.length ) { 1801 return; 1802 } 1803 1804 JetEngine.initElementsHandlers( $clonedSlides ); 1805 1806 if ( $slider.find('.bricks-lazy-hidden').length ) { 1807 bricksLazyLoad(); 1808 } 1809 } ); 1810 } 1811 1812 // Temporary solution issue with Lazy Load images + RTL on Chrome. 1813 // Remove after fix in Chrome. 1814 // See: https://github.com/Crocoblock/issues-tracker/issues/7552 1815 if ( slickOptions.rtl ) { 1816 $sliderItems.on( 'init', function() { 1817 var $items = $( this ), 1818 $lazyImages = $( 'img[loading=lazy]', $items ), 1819 lazyImageObserver = new IntersectionObserver( 1820 function( entries, observer ) { 1821 entries.forEach( function( entry ) { 1822 if ( entry.isIntersecting ) { 1823 // If an image does not load, need to remove the `loading` attribute. 1824 if ( ! entry.target.complete ) { 1825 entry.target.removeAttribute( 'loading' ); 1826 } 1827 1828 // Detach observer 1829 observer.unobserve( entry.target ); 1830 } 1831 } ); 1832 } 1833 ); 1834 1835 $lazyImages.each( function() { 1836 const $img = $( this ); 1837 lazyImageObserver.observe( $img[0] ); 1838 } ); 1839 } ); 1840 } 1841 1842 if ( $sliderItems.hasClass( 'slick-initialized' ) ) { 1843 $sliderItems.slick( 'refresh', true ); 1844 return; 1845 } 1846 1847 if ( slickOptions.variableWidth ) { 1848 slickOptions.slidesToShow = 1; 1849 slickOptions.slidesToScroll = 1; 1850 slickOptions.responsive = null; 1851 } 1852 1853 $sliderItems.slick( slickOptions ); 1854 }, 1855 1856 maybeReinitSlider: function( event, $scope ) { 1857 var $slider = $scope.find( '.jet-listing-grid__slider' ); 1858 1859 if ( $slider.length ) { 1860 $slider.each( function() { 1861 JetEngine.initSlider( $( this ) ); 1862 } ); 1863 } 1864 }, 1865 1866 widgetDynamicField: function( $scope ) { 1867 1868 var $slider = $scope.find( '.jet-engine-gallery-slider' ); 1869 1870 if ( $slider.length ) { 1871 if ( $.isFunction( $.fn.imagesLoaded ) ) {
1872 $slider.imagesLoaded().always( function( instance ) { 1873 1874 var $eWidget = $slider.closest( '.elementor-widget' ); 1875 1876 if ( $slider.hasClass( 'slick-initialized' ) ) { 1877 $slider.slick( 'refresh', true ); 1878 } else { 1879 var atts = $slider.data( 'atts' ); 1880 1881 atts = JetEngine.ensureJSON( atts ); 1882 1883 if ( $eWidget.length ) { 1884 var settings = JetEngine.getElementorElementSettings( $scope ), 1885 eBreakpoints = window.elementorFrontend.config.responsive.activeBreakpoints, 1886 responsive = []; 1887 1888 if ( settings.img_slider_cols || settings.img_slider_cols_widescreen ) { 1889 atts.slidesToShow = settings.img_slider_cols_widescreen ? +settings.img_slider_cols_widescreen : +settings.img_slider_cols; 1890 } 1891 1892 Object.keys( eBreakpoints ).reverse().forEach( function( breakpointName ) { 1893 1894 if ( settings['img_slider_cols_' + breakpointName] ) { 1895 1896 if ( 'widescreen' === breakpointName ) { 1897 1898 responsive.push( { 1899 breakpoint: eBreakpoints[breakpointName].value, 1900 settings: { 1901 slidesToShow: +settings['img_slider_cols'], 1902 } 1903 } ); 1904 1905 } else { 1906 var breakpointSettings = { 1907 breakpoint: eBreakpoints[breakpointName].value + 1, 1908 settings: { 1909 slidesToShow: +settings['img_slider_cols_' + breakpointName], 1910 } 1911 }; 1912 1913 responsive.push( breakpointSettings ); 1914 } 1915 } 1916 1917 } ); 1918 1919 atts.responsive = responsive; 1920 } 1921 1922 $slider.slick( atts ); 1923 } 1924 } ); 1925 } 1926 } 1927 1928 $slider.on('init', function (event, slick) { 1929 1930 const slider = event.target; 1931 1932 if (!slider.classList.contains('jet-engine-gallery-lightbox') || ! window?.PhotoSwipeLightbox) { 1933 return; 1934 } 1935 1936 let lightbox = new PhotoSwipeLightbox({ 1937 mainClass: 'brx', 1938 gallery: slider, 1939 children: 'a', 1940 showHideAnimationType: 'none', 1941 zoomAnimationDuration: false, 1942 pswpModule: PhotoSwipe5, 1943 }); 1944 1945 lightbox.addFilter('numItems', numItems => slick.slideCount); 1946 1947 lightbox.addFilter('clickedIndex', function (clickedIndex, e) { 1948 const slide = e.target.closest('.slick-slide'); 1949 1950 if (!slide) { 1951 return clickedIndex; 1952 } 1953 1954 if (clickedIndex >= slick.slideCount) { 1955 return clickedIndex % slick.slideCount; 1956 } 1957 1958 return clickedIndex; 1959 }); 1960 1961 lightbox.addFilter('thumbEl', (thumbnail, itemData, index) => { 1962 return thumbnail; 1963 }); 1964 1965 lightbox.addFilter('thumbBounds', (thumbBounds, itemData, index) => { 1966 return thumbBounds; 1967 }); 1968 1969 lightbox.init(); 1970 }); 1971 1972 // Masonry init 1973 var $masonry = $scope.find( '.jet-engine-gallery-grid--masonry' ); 1974 1975 if ( $masonry.length ) { 1976 JetEngine.initMasonry( $masonry, { 1977 columnsKey: 'img_columns', 1978 itemSelector: '> .jet-engine-gallery-grid__item', 1979 } ); 1980 } 1981 1982 }, 1983 1984 calendarCache: { 1985 1986 entries: {}, 1987 1988 //introduced because Firefox does not have forEach method for iterators 1989 iterate: function( iterator, callback ) { 1990 if ( typeof iterator?.forEach === 'function' ) { 1991 iterator.forEach( callback ); 1992 } else if ( typeof iterator?.next === 'function' ) { 1993 let next; 1994 while ( next = iterator.next(), ! next.done ) { 1995 callback.call( this, next.value ); 1996 } 1997 } 1998 }, 1999 2000 get: function ( cacheId, month ) { 2001 return JetEngine.calendarCache.entries[ cacheId ]?.get( month ) || false; 2002 }, 2003 2004 set: function ( cacheId, month, content, settings = {}, timestamp = false ) { 2005 if ( ! JetEngine.calendarCache.entries[ cacheId ] ) { 2006 JetEngine.calendarCache.entries[ cacheId ] = new Map(); 2007 } 2008 2009 if ( ! JetEngine.calendarCache.entries[ cacheId ].has( month ) 2010 && JetEngine.calendarCache.entries[ cacheId ].size > ( settings['max_cache'] ?? 12 ) - 1 2011 ) { 2012 let deletedKey; 2013 2014 const mapKeys = JetEngine.calendarCache.entries[ cacheId ].keys(); 2015 2016 if ( settings['__switch_direction'] < 0 ) { 2017 let maxDate = false; 2018 2019 JetEngine.calendarCache.iterate( 2020 mapKeys, 2021 function ( key ) { 2022 const parsedDate = Date.parse( key ); 2023 2024 if ( ! maxDate || parsedDate > maxDate ) { 2025 maxDate = parsedDate; 2026 deletedKey = key; 2027 } 2028 } 2029 ); 2030 } else { 2031 let minDate = false;
2032 2033 JetEngine.calendarCache.iterate( 2034 mapKeys, 2035 function ( key ) { 2036 const parsedDate = Date.parse( key ); 2037 2038 if ( ! minDate || parsedDate < minDate ) { 2039 minDate = parsedDate; 2040 deletedKey = key; 2041 } 2042 } 2043 ); 2044 } 2045 2046 JetEngine.calendarCache.entries[ cacheId ].delete( deletedKey ); 2047 } 2048 2049 if ( ! timestamp ) { 2050 timestamp = Date.now(); 2051 } 2052 2053 JetEngine.calendarCache.entries[ cacheId ].set( month, [ content, timestamp ] ); 2054 }, 2055 2056 update: function ( cacheId, month, content, settings = {} ) { 2057 let cached = JetEngine.calendarCache.get( cacheId, month ); 2058 JetEngine.calendarCache.set( cacheId, month, content, settings, cached[1] ?? false ); 2059 }, 2060 2061 deleteExpiredEntries: function ( cacheId, cacheTimeout ) { 2062 //delete possible orphaned caches 2063 for ( const cacheId in JetEngine.calendarCache.entries ) { 2064 if ( ! document.querySelector( `.jet-calendar[data-cache-id="${cacheId}"]` ) ) { 2065 delete JetEngine.calendarCache.entries[ cacheId ]; 2066 } 2067 } 2068 2069 if ( ! JetEngine.calendarCache.entries[ cacheId ] ) { 2070 return; 2071 } 2072 2073 JetEngine.calendarCache.iterate( 2074 JetEngine.calendarCache.entries[ cacheId ].keys(), 2075 function ( month ) { 2076 if ( JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) { 2077 JetEngine.calendarCache.entries[ cacheId ].delete( month ); 2078 } 2079 } 2080 ); 2081 }, 2082 2083 isExpired: function ( cacheId, month, cacheTimeout ) { 2084 if ( cacheTimeout < 0 ) { 2085 return false; 2086 } 2087 2088 const cached = JetEngine.calendarCache.get( cacheId, month ); 2089 2090 if ( ! cached || ! Array.isArray( cached ) ) { 2091 return true; 2092 } 2093 2094 return ! cached[1] || cached[1] < Date.now() - cacheTimeout; 2095 }, 2096 2097 clear: function( e, $calendar ) { 2098 const cacheId = $calendar.data( 'cache-id' ) || false; 2099 2100 if ( ! cacheId ) { 2101 return; 2102 } 2103 2104 JetEngine.calendarCache.entries[ cacheId ] = new Map(); 2105 }, 2106 2107 modifyJetSmartFiltersSetiings: function( $widget, widgetType, monthData ) { 2108 if ( ! window.JetSmartFilterSettings || ! window.JetSmartFilterSettings.settings ) { 2109 return; 2110 } 2111 2112 if ( ! window.JetSmartFilterSettings.settings['jet-engine-calendar'] ) { 2113 return; 2114 } 2115 2116 monthData = monthData.split( ' ' ); 2117
2118 const month = monthData[0], 2119 year = monthData[1]; 2120 2121 let widgetId; 2122 2123 switch ( widgetType ) { 2124 case 'block': 2125 widgetId = $widget.closest( '.jet-listing-calendar-block' )[0].id; 2126 2127 if ( ! widgetId ) { 2128 widgetId = 'default'; 2129 } 2130 2131 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ] ) { 2132 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month; 2133 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year; 2134 } 2135 2136 break; 2137 case 'bricks': 2138 widgetId = $widget.data( 'element-id' ); 2139 2140 if ( ! widgetId ) { 2141 break; 2142 } 2143 2144 for ( const id in window.JetSmartFilterSettings.settings['jet-engine-calendar'] ) { 2145 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]?._id === widgetId ) { 2146 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_month'] = month; 2147 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ id ]['start_from_year'] = year; 2148 break; 2149 } 2150 } 2151 2152 break; 2153 case 'elementor': 2154 widgetId = $widget.closest( '.elementor-widget-jet-listing-calendar' )[0].id; 2155 2156 if ( ! widgetId ) { 2157 widgetId = 'default'; 2158 } 2159 2160 if ( window.JetSmartFilterSettings.settings['jet-engine-calendar']?.[ widgetId ] ) { 2161 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_month'] = month; 2162 window.JetSmartFilterSettings.settings['jet-engine-calendar'][ widgetId ]['start_from_year'] = year; 2163 } 2164 2165 break; 2166 } 2167 }, 2168 }, 2169 2170 selectCalendarMonth: function ( $event ) { 2171 let wrapper = this.closest( '.jet-calendar-caption__dates' ); 2172 2173 if ( ! JetEngine.updateDateSelectLabels( wrapper ) ) { 2174 return; 2175 } 2176 2177 JetEngine.switchCalendarMonth.bind( wrapper )() 2178 }, 2179 2180 updateDateSelectLabels: function( wrapper ) { 2181 let month = wrapper.querySelector( '.jet-calendar-caption__date-select.select-month' ), 2182 year = wrapper.querySelector( '.jet-calendar-caption__date-select.select-year' ); 2183 2184 if ( ! month || ! year ) { 2185 return false; 2186 } 2187 2188 let monthLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-month' ), 2189 yearLabel = wrapper.querySelector( '.jet-calendar-caption__date-select-label.select-year' ); 2190 2191 wrapper.setAttribute( 'data-month', month.value + ' ' + year.value ); 2192 2193 const monthOption = month.querySelector( `option[value="${month.value}"]` ), 2194 yearOption = year.querySelector( `option[value="${year.value}"]` ); 2195 2196 monthLabel.innerHTML = monthOption.innerHTML; 2197 yearLabel.innerHTML = yearOption.innerHTML; 2198 2199 return true; 2200 }, 2201 2202 switchCalendarMonth: function( $event ) { 2203 2204 var $this = $( this ), 2205 $calendar = $this.closest( '.jet-calendar' ), 2206 $widget = $this.closest( '.elementor-widget-jet-listing-calendar' ), 2207 widgetID = $widget.closest( '.elementor-widget' ).data( 'id' ), 2208 settings = $calendar.data( 'settings' ), 2209 post = $calendar.data( 'post' ), 2210 month = $this.data( 'month' ); 2211 2212 settings = JetEngine.ensureJSON( settings ); 2213 2214 if ( this.classList.contains( 'nav-link-prev' ) ) { 2215 settings['__switch_direction'] = -1; 2216 } else if ( this.classList.contains( 'nav-link-next' ) ) { 2217 settings['__switch_direction'] = 1; 2218 } else { 2219 settings['__switch_direction'] = 0; 2220 } 2221 2222 let widgetType = 'elementor'; 2223 2224 // Context Gutenberg 2225 if ( ! $widget.length ) { 2226 $widget = $calendar.closest( '.jet-listing-calendar-block' ); 2227 widgetType = 'block'; 2228 } 2229 2230 // Context Bricks 2231 if ( ! $widget.length ) { 2232 $widget = $calendar.closest( '.brxe-jet-listing-calendar' ); 2233 widgetID = $widget.data( 'element-id' ); 2234 widgetType = 'bricks'; 2235 } 2236 2237 JetEngine.calendarCache.modifyJetSmartFiltersSetiings( $widget, widgetType, month ); 2238 2239 const cacheId = $calendar.data( 'cache-id' ) || false, 2240 cacheTimeout = ( settings['cache_timeout'] ?? 0 ) * 1000; 2241 2242 if ( cacheId && cacheTimeout ) { 2243 2244 JetEngine.calendarCache.deleteExpiredEntries( cacheId, cacheTimeout ); 2245 2246 // Remove the 'listening' and 'brx-open' classes from all matched elements to prevent 2247 // reinitialization issues in the accordion. 2248 if ( window.bricksIsFrontend ) { 2249 $calendar.find('.accordion-item.listening, .brxe-accordion-nested > .listening') 2250 .removeClass('listening brx-open'); 2251 } 2252 2253 JetEngine.calendarCache.update( cacheId, settings['prev_month'], $calendar.prop('outerHTML'), settings ); 2254 2255 const cached = JetEngine.calendarCache.get( cacheId, month ); 2256 2257 if ( cached?.length && cached[0] && ! JetEngine.calendarCache.isExpired( cacheId, month, cacheTimeout ) ) { 2258 let replacement = $( cached[0] ); 2259 replacement.removeClass( 'jet-calendar-loading' ); 2260 $calendar.replaceWith( replacement[0] ); 2261 JetEngine.initElementsHandlers( $widget ); 2262 JetEngine.updateDateSelectLabels( $widget[0] ); 2263 // Re-init Bricks scripts 2264 JetEngine.reinitBricksScripts( widgetID ); 2265 2266 $( document ).trigger( 'jet-engine-request-calendar-cached', [ $widget ] ); 2267 2268 return; 2269 } 2270 } 2271 2272 $calendar.addClass( 'jet-calendar-loading' ); 2273 2274 JetEngine.currentRequest = { 2275 jet_engine_action: 'jet_engine_calendar_get_month', 2276 month: month, 2277 settings: settings, 2278 post: post, 2279 }; 2280 2281 $( document ).trigger( 'jet-engine-request-calendar' ); 2282 2283 $.ajax({ 2284 url: JetEngineSettings.ajaxlisting, 2285 type: 'POST', 2286 dataType: 'json', 2287 data: JetEngine.currentRequest, 2288 }).done( function( response ) { 2289 if ( response.success ) { 2290 $calendar.replaceWith( response.data.content ); 2291 2292 if ( cacheId && cacheTimeout ) { 2293 JetEngine.calendarCache.set( cacheId, month, response.data.content, settings ); 2294 } 2295 2296 JetEngine.initElementsHandlers( $widget ); 2297 // Re-init Bricks scripts 2298 JetEngine.reinitBricksScripts( widgetID ); 2299 2300 $( document ).trigger( 'jet-engine-request-calendar-done', [ $widget ] ); 2301 } 2302 $calendar.removeClass( 'jet-calendar-loading' ); 2303 } ); 2304 }, 2305 2306 initElementsHandlers: function( $selector ) { 2307 2308 // Actual init 2309 window.JetPlugins.init( $selector ); 2310 2311 // Legacy Elementor-only init 2312 $selector.find( '[data-element_type]' ).each( function() { 2313 2314 var $this = $( this ), 2315 elementType = $this.data( 'element_type' ); 2316 2317 if ( !elementType ) { 2318 return; 2319 } 2320 2321 if ( ! window?.elementorFrontend?.hooks?.doAction ) { 2322 return; 2323 } 2324 2325 if ( 'widget' === elementType ) { 2326 elementType = $this.data( 'widget_type' ); 2327 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ ); 2328 } 2329 2330 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ ); 2331 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ ); 2332 2333 } ); 2334 2335 if ( window.elementorFrontend ) { 2336 const elementorLazyLoad = new Event( "elementor/lazyload/observe" ); 2337 document.dispatchEvent( elementorLazyLoad ); 2338 } 2339 2340 if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) { 2341 $selector.find( '.jet-popup-attach-event-inited' ).removeClass( 'jet-popup-attach-event-inited' ); 2342 window.JetPopupFrontend.initAttachedPopups( $selector ); 2343 } 2344 2345 }, 2346 2347 getElementorElementSettings: function( $scope ) { 2348 2349 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) { 2350 return JetEngine.getEditorElementSettings( $scope ); 2351 } 2352 2353 return $scope.data( 'settings' ) || {}; 2354 }, 2355 2356 getEditorElementSettings: function( $scope ) { 2357 var modelCID = $scope.data( 'model-cid' ), 2358 elementData; 2359 2360 if ( ! modelCID ) { 2361 return {}; 2362 } 2363 2364 if ( ! window.elementorFrontend.hasOwnProperty( 'config' ) ) { 2365 return {}; 2366 } 2367 2368 if ( ! window.elementorFrontend.config.hasOwnProperty( 'elements' ) ) { 2369 return {}; 2370 } 2371 2372 if ( ! window.elementorFrontend.config.elements.hasOwnProperty( 'data' ) ) { 2373 return {}; 2374 } 2375 2376 elementData = window.elementorFrontend.config.elements.data[ modelCID ]; 2377 2378 if ( ! elementData ) { 2379 return {}; 2380 } 2381 2382 return elementData.toJSON(); 2383 }, 2384 2385 debounce: function( threshold, callback ) { 2386 var timeout; 2387 2388 return function debounced( $event ) { 2389 function delayed() { 2390 callback.call( this, $event ); 2391 timeout = null; 2392 } 2393 2394 if ( timeout ) { 2395 clearTimeout( timeout ); 2396 } 2397 2398 timeout = setTimeout( delayed, threshold ); 2399 }; 2400 }, 2401 2402 updateAddedStyles: function() { 2403 if ( window.JetEngineSettings && window.JetEngineSettings.addedPostCSS ) { 2404 $.each( window.JetEngineSettings.addedPostCSS, function( ind, cssID ) {
2405 JetEngine.addedStyles.push( 'elementor-post-' + cssID ); 2406 JetEngine.addedPostCSS.push( cssID ); 2407 } ); 2408 } 2409 }, 2410 2411 enqueueAssetsFromResponse: function( response ) { 2412 if ( response.data.scripts ) { 2413 JetEngine.enqueueScripts( response.data.scripts ); 2414 } 2415 2416 if ( response.data.styles ) { 2417 JetEngine.enqueueStyles( response.data.styles ); 2418 } 2419 }, 2420 2421 enqueueScripts: function( scripts ) { 2422 $.each( scripts, function( handle, scriptHtml ) { 2423 JetEngine.enqueueScript( handle, scriptHtml ) 2424 } ); 2425 }, 2426 2427 enqueueStyles: function( styles ) { 2428 $.each( styles, function( handle, styleHtml ) { 2429 JetEngine.enqueueStyle( handle, styleHtml ) 2430 } ); 2431 }, 2432 2433 enqueueScript: function( handle, scriptHtml ) { 2434 2435 if ( -1 !== JetEngine.addedScripts.indexOf( handle ) ) { 2436 return; 2437 } 2438 2439 if ( ! scriptHtml ) { 2440 return; 2441 } 2442 2443 var selector = 'script[id="' + handle + '-js"]'; 2444 2445 if ( $( selector ).length ) { 2446 return; 2447 } 2448 2449 //$( 'body' ).append( scriptHtml ); 2450 2451 var scriptsTags = scriptHtml.match( /<script[\s\S]*?<\/script>/gm ); 2452 2453 if ( scriptsTags.length ) { 2454 2455 for ( var i = 0; i < scriptsTags.length; i++ ) { 2456 2457 JetEngine.assetsPromises.push( 2458 new Promise( function( resolve, reject ) { 2459 2460 var $tag = $( scriptsTags[i] ); 2461 2462 if ( $tag[0].src ) { 2463 2464 var tag = document.createElement( 'script' ); 2465 2466 tag.type = $tag[0].type; 2467 tag.src = $tag[0].src; 2468 tag.id = $tag[0].id; 2469 tag.async = false; 2470 tag.onload = function() { 2471 resolve(); 2472 }; 2473 2474 document.body.append( tag ); 2475 } else { 2476 $( 'body' ).append( scriptsTags[i] ); 2477 resolve(); 2478 } 2479 } ) 2480 ); 2481 } 2482 } 2483 2484 JetEngine.addedScripts.push( handle ); 2485 }, 2486 2487 enqueueStyle: function( handle, styleHtml ) { 2488 2489 if ( -1 !== handle.indexOf( 'google-fonts' ) ) { 2490 JetEngine.enqueueGoogleFonts( handle, styleHtml ); 2491 return; 2492 } 2493 2494 if ( -1 !== JetEngine.addedStyles.indexOf( handle ) ) { 2495 return; 2496 } 2497 2498 var selector = 'link[id="' + handle + '-css"],style[id="' + handle + '"]'; 2499 2500 if ( $( selector ).length ) { 2501 return; 2502 } 2503 2504 $( 'head' ).append( styleHtml ); 2505 2506 JetEngine.addedStyles.push( handle ); 2507 2508 if ( -1 !== handle.indexOf( 'elementor-post' ) ) { 2509 var postID = handle.replace( 'elementor-post-', '' ); 2510 JetEngine.addedPostCSS.push( postID ); 2511 } 2512 }, 2513 2514 enqueueGoogleFonts: function( handle, styleHtml ) { 2515 2516 var selector = 'link[id="' + handle + '-css"]'; 2517 2518 if ( $( selector ).length ) {} 2519 2520 $( 'head' ).append( styleHtml ); 2521 }, 2522 2523 isFrontend: function () { 2524 // Check the Elementor 2525 if (typeof window.elementorFrontend !== 'undefined') { 2526 return !window.elementorFrontend.isEditMode(); 2527 } 2528 2529 // Check the Bricks 2530 if (typeof window.bricksIsFrontend !== 'undefined') { 2531 return window.bricksIsFrontend; 2532 } 2533 2534 // If no builders are found, we assume it is frontend. 2535 return true; 2536 }, 2537 2538 reinitBricksScripts: function (elementId) { 2539 if (!window.bricksIsFrontend) { 2540 return; 2541 } 2542 2543 document.dispatchEvent( 2544 new CustomEvent("bricks/ajax/query_result/displayed", { 2545 detail: { 2546 queryId: elementId || null 2547 } 2548 }) 2549 ); 2550 }, 2551 2552 filters: ( function() { 2553 2554 var callbacks = {}; 2555 2556 return { 2557 2558 addFilter: function( name, callback ) { 2559 2560 if ( ! callbacks.hasOwnProperty( name ) ) { 2561 callbacks[name] = []; 2562 } 2563 2564 callbacks[name].push(callback); 2565 2566 }, 2567 2568 applyFilters: function( name, value, args ) { 2569 2570 if ( ! callbacks.hasOwnProperty( name ) ) { 2571 return value; 2572 } 2573 2574 if ( args === undefined ) { 2575 args = []; 2576 } 2577 2578 var container = callbacks[ name ]; 2579 var cbLen = container.length; 2580 2581 for (var i = 0; i < cbLen; i++) { 2582 if (typeof container[i] === 'function') { 2583 value = container[i](value, args); 2584 } 2585 } 2586 2587 return value; 2588 } 2589 2590 }; 2591 2592 })() 2593 2594 }; 2595 2596 $( window ).on( 'elementor/frontend/init', JetEngine.init ); 2597 2598 window.JetEngine = JetEngine; 2599 2600 document.addEventListener( 'jet-smart-filters/inited', function() { 2601 window.JetSmartFilters.events.subscribe( 'ajaxFilters/updated', function( provider, queryId ) { 2602 window.JetEngine.initFrontStores( window.JetSmartFilters?.filterGroups?.[ provider + '/' + queryId ]?.$provider); 2603 } ); 2604 } ); 2605 2606 JetEngine.commonInit(); 2607 2608 window.addEventListener( 'DOMContentLoaded', function() { 2609 setTimeout( () => JetEngine.initBlocks() ); 2610 JetEngine.initDone = true; 2611 } ); 2612 2613 window.jetEngineBricks = function() { 2614 JetEngine.initBricks(); 2615 } 2616 2617 $( window ).trigger( 'jet-engine/frontend/loaded' ); 2618 2619}( 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.