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