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