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