1( function( $, elementor ) { 2 3 'use strict'; 4 5 var JetTricks = { 6 7 init: function() { 8 elementor.hooks.addAction( 'frontend/element_ready/section', JetTricks.elementorSection ); 9 elementor.hooks.addAction( 'frontend/element_ready/section', JetTricks.elementorColumn ); 10 elementor.hooks.addAction( 'frontend/element_ready/container', JetTricks.elementorSection ); 11 elementor.hooks.addAction( 'frontend/element_ready/container', JetTricks.elementorColumn ); 12 elementor.hooks.addAction( 'frontend/element_ready/column', JetTricks.elementorColumn ); 13 elementor.hooks.addAction( 'frontend/element_ready/widget', JetTricks.elementorWidget ); 14 15 var widgets = { 16 'jet-view-more.default' : JetTricks.widgetViewMore, 17 'jet-unfold.default' : JetTricks.widgetUnfold, 18 'jet-hotspots.default' : JetTricks.widgetHotspots 19 }; 20 21 $.each( widgets, function( widget, callback ) { 22 elementor.hooks.addAction( 'frontend/element_ready/' + widget, callback ); 23 }); 24 25 // Re-init widgets in nested tabs 26 window.elementorFrontend.elements.$window.on( 27 'elementor/nested-tabs/activate', 28 ( event, content ) => { 29 30 const $content = $( content ); 31 32 var $button = $content.find( '.jet-unfold__button' ); 33 34 $button.off( 'click.jetUnfold' ); 35 36 JetTricks.initWidgetsHandlers( $content ); 37 JetTricks.elementorSection( $content ); 38 39 } 40 ); 41 42 // Add an action when the Swiper Loop Carousel widget is ready on the frontend 43 var loopCarouselTypes = [ 44 'loop-carousel.post', 45 'loop-carousel.product', 46 'loop-carousel.post_taxonomy', 47 'loop-carousel.product_taxonomy' 48 ]; 49 50 loopCarouselTypes.forEach( function( carouselType ) { 51 elementorFrontend.hooks.addAction( 'frontend/element_ready/' + carouselType, function( $scope, $ ) { 52 53 $( window ).on( 'load', function() { 54 var loopCarousel = $scope.find( '.swiper' ), 55 swiperInstance = loopCarousel.data( 'swiper' ), 56 $button = $scope.find( '.jet-unfold__button' ); 57 58 if ( swiperInstance && $button ) { 59 60 $button.off( 'click.jetUnfold' ); 61 JetTricks.initLoopCarouselHandlers( $scope ); 62 63 swiperInstance.on( 'slideChange', function() { 64 $button.off( 'click.jetUnfold' ); 65 JetTricks.initLoopCarouselHandlers( $scope ); 66 }); 67 } 68 }); 69 }); 70 }); 71 }, 72 73 initLoopCarouselHandlers: function( $selector ) { 74 $selector.find( '.elementor-widget-jet-unfold' ).each( function() { 75 76 var $this = $( this ), 77 78 elementType = $this.data( 'element_type' ); 79 80 if ( !elementType ) { 81 return; 82 } 83 84 if ( 'widget' === elementType ) { 85 elementType = $this.data( 'widget_type' ); 86 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ ); 87 } 88 89 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ ); 90 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ ); 91 92 93 } ); 94 }, 95 96 initWidgetsHandlers: function( $selector ) { 97 98 $selector.find( '[data-element_type]' ).each( function() { 99 100 var excludeWidgets = [ 101 'jet-woo-product-gallery-slider.default', 102 'accordion.default' 103 ]; 104 105 var $this = $( this ), 106 107 elementType = $this.data( 'element_type' ); 108 109 if ( !elementType ) { 110 return; 111 } 112 113 if ( 'widget' === elementType ) { 114 115 elementType = $this.data( 'widget_type' ); 116 117 if ( excludeWidgets.includes( elementType ) ) { 118 return; 119 } 120 121 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ ); 122 } 123 124 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ ); 125 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ ); 126 127 128 } ); 129 }, 130 131 elementorSection: function( $scope ) { 132 var $target = $scope, 133 sectionId = $scope.data( 'id' ), 134 editMode = Boolean( elementor.isEditMode() ), 135 jetListing = $target.parents( '.elementor-widget-jet-listing-grid' ).data( 'id' ), 136 settings = {}; 137 138 if ( window.JetTricksSettings && window.JetTricksSettings.elements_data.sections.hasOwnProperty( sectionId ) ) { 139 settings = window.JetTricksSettings.elements_data.sections[ sectionId ]; 140 } 141 142 if ( editMode ) { 143 settings = JetTricks.sectionEditorSettings( $scope ); 144 } 145 146 if ( ! settings ) { 147 return false;
148 } 149 150 if ( jQuery.isEmptyObject( settings ) ) { 151 return false; 152 } 153 154 if ( 'false' === settings.particles || '' === settings.particles_json ) { 155 return false; 156 } 157 158 // Compatibility jet tricks particles with jet listing 159 160 if ( jetListing && $target.parent().data( 'elementor-type' ) === 'jet-listing-items' ){ 161 sectionId += jetListing + $target.parents( '.jet-listing-grid__item' ).data( 'post-id' ); 162 } 163 164 var particlesId = 'jet-tricks-particles-instance-' + sectionId, 165 particlesJson = JSON.parse( settings.particles_json ); 166 167 $scope.prepend( '<div id="' + particlesId + '" class="jet-tricks-particles-section__instance"></div>' ); 168 169 // Initialize particles based on library version 170 171 if ( typeof tsParticles !== 'undefined' && tsParticles.load && tsParticles.version && tsParticles.version.startsWith('3.') ) { 172 tsParticles.load({ 173 id: particlesId, 174 options: particlesJson 175 }); 176 } else if ( typeof tsParticles !== 'undefined' && tsParticles.load ) { 177 tsParticles.load( particlesId, particlesJson ); 178 } 179 180 }, 181 182 elementorColumn: function( $scope ) { 183 var $target = $scope, 184 $parentSection = $scope.closest( '.elementor-section' ), 185 isLegacyModeActive = !!$target.find( '> .elementor-column-wrap' ).length, 186 $window = $( window ), 187 columnId = $target.data( 'id' ), 188 editMode = Boolean( elementor.isEditMode() ), 189 settings = {}, 190 stickyInstance = null, 191 stickyInstanceOptions = { 192 topSpacing: 50, 193 bottomSpacing: 50, 194 containerSelector: isLegacyModeActive ? '.elementor-row' : '.elementor-container, .e-con-inner', 195 innerWrapperSelector: isLegacyModeActive ? '.elementor-column-wrap' : '.elementor-widget-wrap', 196 }, 197 $observerTarget = $target.find('.elementor-element'); 198 199 if ( ! editMode ) { 200 settings = $target.data( 'jet-settings' ); 201 202 if ( $target.hasClass( 'jet-sticky-column' ) ) { 203 if ( -1 !== settings['stickyOn'].indexOf( elementorFrontend.getCurrentDeviceMode() ) ) { 204 $target.each( function() { 205 var $this = $( this ), 206 elementType = $this.data( 'element_type' ); 207 208 if ( settings['behavior'] === 'fixed' ) { 209 initFixedSticky( $this, settings ); 210 } else if ( elementType !== 'container' && elementType !== 'section' ) { 211 initSidebarSticky( $this, settings, stickyInstanceOptions ); 212 } else if ( settings['behavior'] === 'scroll_until_end' ) { 213 initScrollUntilEndSticky( $this, settings ); 214 } else { 215 initDefaultSticky( $this, settings ); 216 } 217 }); 218 } 219 } 220 } 221 222 function initFixedSticky($element, settings) { 223 var offsetTop = parseInt(settings['topSpacing']) || 0; 224 var bottomSpacing = parseInt(settings['bottomSpacing']) || 0; 225 var $window = $(window); 226 var elementId = $element.data('id'); 227 var originalOffsetTop = $element.offset().top; 228 var originalHeight = $element.outerHeight(); 229 230 var $allStickyElements = $('.jet-sticky-column').filter(function() { 231 var $this = $(this); 232 var elementSettings = $this.data('jet-settings'); 233 234 return elementSettings && elementSettings.stickyOn.indexOf(elementorFrontend.getCurrentDeviceMode()) !== -1; 235 }); 236 237 var currentIndex = $allStickyElements.index($element); 238 var $nextSticky = currentIndex + 1 < $allStickyElements.length ? $allStickyElements.eq(currentIndex + 1) : null; 239 var $stopper = null; 240 if ($nextSticky) { 241 $stopper = $nextSticky.closest('.elementor-top-section, .e-parent'); 242 if (!$stopper.length) { 243 $stopper = $nextSticky; 244 } 245 } 246 247 const $placeholder = $('<div></div>') 248 .addClass('jet-sticky-placeholder') 249 .css({ 250 display: 'none', 251 height: originalHeight, 252 width: $element.outerWidth(), 253 visibility: 'hidden' 254 }); 255 256 $element.before($placeholder); 257 258 function enableSticky() { 259 $placeholder.show(); 260 $element.addClass('jet-sticky-container--stuck'); 261 262 var stopperTop = $stopper?.offset()?.top; 263 var stopPoint = stopperTop ? (stopperTop - $element.outerHeight() - offsetTop - bottomSpacing) : null; 264 var diff = 0; 265 266 if (stopPoint && stopPoint < $window.scrollTop()) { 267 diff = (stopPoint - $window.scrollTop()); 268 } 269 270 $element.css({ 271 position: 'fixed', 272 top: diff + 'px', 273 transform: `translateY(${offsetTop}px)`, 274 left: $placeholder.offset().left + 'px', 275 width: $placeholder.outerWidth() + 'px' 276 }); 277 } 278 279 function disableSticky() { 280 $placeholder.hide(); 281 $element.removeClass('jet-sticky-container--stuck'); 282 283 $element.css({ 284 position: '', 285 top: '', 286 transform: '', 287 left: '', 288 width: '' 289 }); 290 } 291 292 function onScroll() { 293 var scrollTop = $window.scrollTop(); 294 if (scrollTop >= originalOffsetTop) { 295 enableSticky(); 296 } else { 297 disableSticky(); 298 } 299 } 300 301 function onResize() { 302 originalOffsetTop = $placeholder.offset().top; 303 originalHeight = $element.outerHeight(); 304 305 $placeholder.css({ 306 height: originalHeight, 307 width: $element.outerWidth() 308 }); 309 310 onScroll(); 311 } 312 313 let ticking = false;
314 $window.on('scroll.jetStickyHeader-' + elementId, function() { 315 if (!ticking) { 316 requestAnimationFrame(function() { 317 onScroll(); 318 ticking = false; 319 }); 320 ticking = true; 321 } 322 }); 323 324 $window.on('resize.jetStickyHeader-' + elementId, JetTricksTools.debounce(100, onResize)); 325 onScroll(); 326 327 $window.on('resize.jetStickyHeader-' + elementId, JetTricksTools.debounce(100, function() { 328 if (-1 === settings['stickyOn'].indexOf(elementorFrontend.getCurrentDeviceMode())) { 329 cleanupSticky($element, $placeholder, elementId); 330 } 331 })); 332 } 333 334 function cleanupSticky( $element, $placeholder, elementId ) { 335 $placeholder.remove(); 336 $element.css({ 337 position: '', 338 top: '', 339 transform: '', 340 left: '', 341 width: '', 342 zIndex: '', 343 transition: '', 344 willChange: '' 345 }); 346 $element.removeClass('jet-sticky-container--stuck'); 347 $window.off('scroll.jetStickyHeader-' + elementId); 348 $window.off('resize.jetStickyHeader-' + elementId); 349 } 350 351 function initSidebarSticky( $element, settings, options ) { 352 options.topSpacing = settings['topSpacing']; 353 options.bottomSpacing = settings['bottomSpacing']; 354 355 imagesLoaded( $parentSection, function() { 356 $target.data( 'stickyColumnInit', true ); 357 stickyInstance = new StickySidebar( $target[0], options ); 358 }); 359 360 var targetMutation = $target[0], 361 config = { attributes: true, childList: true, subtree: true }; 362 363 var observer = new MutationObserver( function( mutations ) { 364 for( var mutation of mutations ) { 365 if ( 'attributes' === mutation.type ) { 366 $target[0].style.height = 'auto'; 367 } 368 } 369 }); 370 371 observer.observe( targetMutation, config ); 372 373 $window.on( 'resize.JetTricksStickyColumn orientationchange.JetTricksStickyColumn', 374 JetTricksTools.debounce( 50, resizeDebounce ) ); 375 376 var observer = new MutationObserver( function( mutations ) { 377 if ( stickyInstance ) { 378 mutations.forEach( function(mutation){ 379 if (mutation.attributeName === 'class') { 380 setTimeout( function() { 381 stickyInstance.destroy(); 382 stickyInstance = new StickySidebar( $target[0], options ); 383 }, 100 ); 384 } 385 }); 386 } 387 }); 388 389 $observerTarget.each( function(){ 390 observer.observe( $( this )[0], { 391 attributes: true 392 }); 393 }); 394 } 395 396 function initScrollUntilEndSticky( $element, settings ) { 397 const stickyHeight = $element.outerHeight(); 398 const stickyContentBottom = $element.offset().top + stickyHeight; 399 const stickyViewportOffset = $window.height() - stickyHeight - settings['bottomSpacing']; 400 401 $('body').addClass('jet-sticky-container'); 402 403 $window.on( 'scroll.jetSticky', function () { 404 const scrollPosition = $window.scrollTop(); 405 406 if ( scrollPosition + $window.height() >= stickyContentBottom ) { 407 $element.css({ 408 position: 'sticky', 409 top: stickyViewportOffset + 'px', 410 bottom: 'auto', 411 left: 'auto', 412 zIndex: settings['zIndex'], 413 }); 414 } 415 }); 416 417 $observerTarget.on( 'destroy.jetSticky', function () { 418 $window.off( 'scroll.jetSticky' ); 419 $('body').removeClass('jet-sticky-container'); 420 }); 421 } 422 423 function initDefaultSticky( $element, settings ) { 424 $('body').addClass('jet-sticky-container'); 425 $element.addClass( 'jet-sticky-container-sticky' ); 426 $element.css({ 427 'top': settings['topSpacing'], 428 'bottom': settings['bottomSpacing'] 429 }); 430 } 431 432 function resizeDebounce() { 433 var currentDeviceMode = elementorFrontend.getCurrentDeviceMode(), 434 availableDevices = settings['stickyOn'] || [], 435 isInit = $target.data( 'stickyColumnInit' ); 436 437 if ( -1 !== availableDevices.indexOf( currentDeviceMode ) ) { 438 if ( ! isInit ) { 439 $target.data( 'stickyColumnInit', true ); 440 stickyInstance = new StickySidebar( $target[0], stickyInstanceOptions ); 441 stickyInstance.updateSticky(); 442 } 443 } else { 444 $target.data( 'stickyColumnInit', false ); 445 stickyInstance.destroy(); 446 } 447 } 448 }, 449 450 elementorWidget: function( $scope ) { 451 var parallaxInstance = null, 452 satelliteInstance = null, 453 tooltipInstance = null; 454 455 parallaxInstance = new jetWidgetParallax( $scope ); 456 parallaxInstance.init(); 457 458 satelliteInstance = new jetWidgetSatellite( $scope ); 459 satelliteInstance.init(); 460 461 tooltipInstance = new jetWidgetTooltip( $scope ); 462 tooltipInstance.init(); 463 464 }, 465 466 getElementorElementSettings: function( $scope ) { 467 468 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) { 469 return JetTricks.getEditorElementSettings( $scope ); 470 } 471 472 return $scope.data( 'settings' ) || {}; 473 }, 474 475 getEditorElementSettings: function( $scope ) { 476 var modelCID = $scope.data( 'model-cid' ), 477 elementData; 478 479 if ( ! modelCID ) { 480 return {}; 481 } 482 483 if ( ! elementor.hasOwnProperty( 'config' ) ) { 484 return {}; 485 } 486 487 if ( ! elementor.config.hasOwnProperty( 'elements' ) ) { 488 return {}; 489 } 490 491 if ( ! elementor.config.elements.hasOwnProperty( 'data' ) ) { 492 return {}; 493 } 494 495 elementData = elementor.config.elements.data[ modelCID ]; 496 497 if ( ! elementData ) { 498 return {}; 499 } 500 501 return elementData.toJSON(); 502 }, 503 504 widgetViewMore: function( $scope ) { 505 var $target = $scope.find( '.jet-view-more' ), 506 instance = null, 507 settings = $target.data( 'settings' ); 508 509 instance = new jetViewMore( $target, settings ); 510 instance.init(); 511 }, 512 513 widgetUnfold: function( $scope ) { 514 var $target = $scope.find( '.jet-unfold' ), 515 $button = $( '.jet-unfold__button', $target ), 516 $mask = $( '.jet-unfold__mask', $target ), 517 $content = $( '.jet-unfold__content', $target ), 518 $contentInner = $( '.jet-unfold__content-inner', $target), 519 $trigger = $( '.jet-unfold__trigger', $target), 520 $separator = $( '.jet-unfold__separator', $target ), 521 settings = $.extend( {}, $target.data( 'settings' ), JetTricks.getElementorElementSettings( $scope ) ), 522 maskBreakpointsHeights = [], 523 prevBreakpoint = '', 524 unfoldDuration = settings['unfoldDuration'] || settings['unfold_duration'], 525 foldDuration = settings['foldDuration'] || settings['fold_duration'], 526 unfoldEasing = settings['unfoldEasing'] || settings['unfold_easing'], 527 foldEasing = settings['foldEasing'] || settings['fold_easing'], 528 maskHeightAdv = 20, 529 heightCalc = '', 530 autoHide = settings['autoHide'] || false, 531 autoHideTime = settings['autoHideTime'] && 0 != settings['autoHideTime']['size'] ? settings['autoHideTime']['size'] : 5, 532 hideOutsideClick = settings['hideOutsideClick'] || false, 533 autoHideTrigger, 534 activeBreakpoints = elementor.config.responsive.activeBreakpoints, 535 initialLoaded = false;
536 537 maskBreakpointsHeights['desktop'] = []; 538 maskBreakpointsHeights['widescreen'] = []; 539 540 maskBreakpointsHeights['desktop']['maskHeight'] = '' != settings['mask_height']['size'] ? settings['mask_height']['size'] : 50; 541 542 prevBreakpoint = 'desktop'; 543 544 Object.keys( activeBreakpoints ).reverse().forEach( function( breakpointName ) { 545 546 if ( 'widescreen' === breakpointName ) { 547 maskBreakpointsHeights['widescreen']['maskHeight'] = '' != settings['mask_height_widescreen']['size'] ? settings['mask_height_widescreen']['size'] : maskBreakpointsHeights['desktop']['maskHeight']; 548 } else { 549 maskBreakpointsHeights[breakpointName] = []; 550 551 maskBreakpointsHeights[breakpointName]['maskHeight'] = '' != settings['mask_height_' + breakpointName]['size'] ? settings['mask_height_' + breakpointName]['size'] : maskBreakpointsHeights[prevBreakpoint]['maskHeight']; 552 553 prevBreakpoint = breakpointName; 554 } 555 } ); 556 557 onLoaded(); 558 559 if ( 'true' === hideOutsideClick ) { 560 $( window ).on( 'mouseup', function( event ) { 561 let container = $target; 562 if ( !container.is( event.target ) && 0 === container.has( event.target ).length && $target.hasClass( 'jet-unfold-state' ) ) { 563 $button.trigger( 'click' ); 564 } 565 } ) 566 } 567 568 $target.one('transitionend webkitTransitionEnd oTransitionEnd', function() { 569 if ( !initialLoaded ) { 570 onLoaded(); 571 initialLoaded = true; 572 } 573 }); 574 575 function onLoaded() { 576 initialLoaded = true; 577 578 var deviceHeight = getDeviceHeight(); 579 580 heightCalc = +deviceHeight + maskHeightAdv; 581 582 if ( heightCalc < $contentInner.height() ) { 583 584 if ( ! $target.hasClass( 'jet-unfold-state' ) ) { 585 $separator.css( { 586 'opacity': '1' 587 } ); 588 } 589 590 if ( ! $target.hasClass( 'jet-unfold-state' ) ) { 591 $mask.css( { 592 'height': deviceHeight 593 } ); 594 } else { 595 $mask.css( { 596 'height': $contentInner.outerHeight() 597 } ); 598 } 599 $trigger.css( 'display', 'flex' ); 600 } else { 601 $trigger.hide(); 602 $mask.css( { 603 'height': '100%' 604 } ); 605 $content.css( { 606 'max-height': 'none' 607 } ); 608 $separator.css( { 609 'opacity': '0' 610 } ); 611 } 612 } 613 614 $( window ).on( 'resize.jetWidgetUnfold orientationchange.jetWidgetUnfold', JetTricksTools.debounce( 50, function(){ 615 initialLoaded = false; 616 onLoaded(); 617 } ) ); 618 619 $button.keypress( function( e ) { 620 if ( e.which == 13 ) { 621 $button.click(); 622 return false; 623 } 624 } ); 625 626 $button.on( 'click.jetUnfold', function(e) { 627 var $this = $( this ), 628 $buttonText = $( '.jet-unfold__button-text', $this ), 629 unfoldText = $this.data( 'unfold-text' ), 630 foldText = $this.data( 'fold-text' ), 631 $buttonIcon = $( '.jet-unfold__button-icon', $this ), 632 unfoldIcon = $this.data( 'unfold-icon' ), 633 foldIcon = $this.data( 'fold-icon' ), 634 contentHeight = $contentInner.outerHeight(), 635 deviceHeight = getDeviceHeight(); 636 637 e.preventDefault(); 638 639 if ( ! $target.hasClass( 'jet-unfold-state' ) ) { 640 $target.addClass( 'jet-unfold-state' ); 641 642 $separator.css( { 643 'opacity': '0' 644 } ); 645 646 $buttonIcon.html( foldIcon ); 647 $buttonText.html( foldText ); 648 649 anime( { 650 targets: $mask[0], 651 height: contentHeight, 652 duration: unfoldDuration['size'], 653 easing: unfoldEasing, 654 complete: function( anim ) { 655 // Recalculate listing masonry. 656 $( document ).trigger( 'jet-engine/listing/recalculate-masonry' ); 657 } 658 } ); 659 660 if ( 'true' === autoHide ) { 661 autoHideTrigger = setTimeout( function() { 662 $button.trigger( 'click' ); 663 }, autoHideTime * 1000 ); 664 } 665 } else { 666 clearTimeout( autoHideTrigger ); 667 668 $target.removeClass( 'jet-unfold-state' ); 669 670 $separator.css( { 671 'opacity': '1' 672 } ); 673 674 $buttonIcon.html( unfoldIcon ); 675 $buttonText.html( unfoldText ); 676 677 anime( { 678 targets: $mask[0], 679 height: deviceHeight, 680 duration: foldDuration['size'], 681 easing: foldEasing, 682 complete: function( anim ) { 683 if ( 'true' === settings['foldScrolling'] ) { 684 $( 'html, body' ).animate( { 685 scrollTop: $target.offset().top - settings['foldScrollOffset']['size'] 686 }, 'slow' ); 687 } 688 689 // Recalculate listing masonry. 690 $( document ).trigger( 'jet-engine/listing/recalculate-masonry' ); 691 } 692 } ); 693 } 694 } ); 695 696 function getDeviceHeight() { 697 let device = elementorFrontend.getCurrentDeviceMode(); 698 let heightSettings; 699 700 switch ( device ) { 701 702 case 'mobile': 703 heightSettings = settings.mask_height_mobile; 704 break; 705 706 case 'tablet': 707 heightSettings = settings.mask_height_tablet; 708 break; 709 710 default: 711 heightSettings = settings.mask_height; 712 713 } 714 715 if ( ! heightSettings || ! heightSettings.size || ! heightSettings.unit ) { 716 heightSettings = settings.mask_height; 717 } 718
719 switch ( heightSettings.unit ) { 720 721 case 'vh': 722 return ( window.innerHeight * heightSettings.size ) / 100; 723 724 case '%': 725 let parentHeight = $contentInner.parent().height(); 726 return ( parentHeight * heightSettings.size ) / 100; 727 728 default: 729 return heightSettings.size; 730 } 731 } 732 }, 733 734 widgetHotspots: function( $scope ) { 735 var $target = $scope.find( '.jet-hotspots' ), 736 $hotspots = $( '.jet-hotspots__item', $target), 737 settings = $target.data( 'settings' ), 738 editMode = Boolean( elementor.isEditMode() ), 739 itemActiveClass = 'jet-hotspots__item--active'; 740 741 $target.imagesLoaded().progress( function() { 742 $target.addClass( 'image-loaded' ); 743 } ); 744 745 $hotspots.each( function( index ) { 746 var $this = $( this ), 747 horizontal = $this.data( 'horizontal-position' ), 748 vertical = $this.data( 'vertical-position' ), 749 tooltipWidth = $this.data( 'tooltip-width' ) || null, 750 itemSelector = $this[0], 751 options = {}; 752 753 $this.css( { 754 'left': horizontal + '%', 755 'top': vertical + '%' 756 } ); 757 758 if ( itemSelector._tippy ) { 759 itemSelector._tippy.destroy(); 760 } 761 762 options = { 763 content: $this.data('tippy-content'), 764 arrow: settings['tooltipArrow'] ? true : false, 765 placement: settings['tooltipPlacement'], 766 trigger: settings['tooltipTrigger'], 767 appendTo: $target[0], 768 hideOnClick: 'manual' !== settings['tooltipTrigger'], 769 maxWidth: 'none', 770 offset: [0, settings['tooltipDistance']['size']], 771 allowHTML: true, 772 onShow( instance ) { 773 $( itemSelector ).addClass( itemActiveClass ); 774 775 if ( tooltipWidth ) { 776 instance.popper.querySelector( '.tippy-box' ).style.width = tooltipWidth; 777 } 778 779 }, 780 onHidden( instance ) { 781 $( itemSelector ).removeClass( itemActiveClass ); 782 } 783 } 784 785 if ( 'manual' != settings['tooltipTrigger'] ) { 786 options['duration'] = [ settings['tooltipShowDuration']['size'], settings['tooltipHideDuration']['size'] ]; 787 options['animation'] = settings['tooltipAnimation']; 788 options['delay'] = settings['tooltipDelay']; 789 } 790 791 tippy( [ itemSelector ], options ); 792 793 if ( 'manual' === settings['tooltipTrigger'] && itemSelector._tippy ) { 794 itemSelector._tippy.show(); 795 } 796 797 if ( settings['tooltipShowOnInit'] && itemSelector._tippy ) { 798 itemSelector._tippy.show(); 799 } 800 801 } ); 802 }, 803 804 columnEditorSettings: function( columnId ) { 805 var editorElements = null, 806 columnData = {}; 807 808 if ( ! window.elementor.hasOwnProperty( 'elements' ) ) { 809 return false; 810 } 811 812 editorElements = window.elementor.elements; 813 814 if ( ! editorElements.models ) { 815 return false; 816 } 817 818 $.each( editorElements.models, function( index, obj ) { 819 820 $.each( obj.attributes.elements.models, function( index, obj ) { 821 if ( columnId == obj.id ) { 822 columnData = obj.attributes.settings.attributes; 823 } 824 } ); 825 826 } ); 827 828 return { 829 'sticky': columnData['jet_tricks_column_sticky'] || false, 830 'topSpacing': columnData['jet_tricks_top_spacing'] || 50,
831 'bottomSpacing': columnData['jet_tricks_bottom_spacing'] || 50, 832 'stickyOn': columnData['jet_tricks_column_sticky_on'] || [ 'desktop', 'tablet', 'mobile'] 833 } 834 835 }, 836 837 sectionEditorSettings: function( $scope ) { 838 var editorElements = null, 839 sectionData = {}; 840 841 if ( ! window.elementor.hasOwnProperty( 'elements' ) ) { 842 return false; 843 } 844 845 sectionData = JetTricks.getElementorElementSettings( $scope ); 846 847 return { 848 'particles': sectionData['section_jet_tricks_particles'] || 'false', 849 'particles_json': sectionData['section_jet_tricks_particles_json'] || '', 850 } 851 852 } 853 854 }; 855 856 $( window ).on( 'elementor/frontend/init', JetTricks.init ); 857 858 var JetTricksTools = { 859 debounce: function( threshold, callback ) { 860 var timeout; 861 862 return function debounced( $event ) { 863 function delayed() { 864 callback.call( this, $event ); 865 timeout = null; 866 } 867 868 if ( timeout ) { 869 clearTimeout( timeout ); 870 } 871 872 timeout = setTimeout( delayed, threshold ); 873 }; 874 }, 875 876 widgetEditorSettings: function( widgetId ) { 877 var editorElements = null, 878 widgetData = {}; 879 880 if ( !window.elementor.hasOwnProperty( 'elements' ) || !window.elementor.elements.models ) { 881 return false; 882 } 883 884 editorElements = window.elementor.elements; 885 886 function findWidgetById( models, widgetId ) { 887 let foundData = null; 888 889 $.each( models, function( index, obj ) { 890 if ( obj.id === widgetId ) { 891 foundData = obj.attributes.settings.attributes; 892 return false; 893 } 894 if ( obj.attributes.elements && obj.attributes.elements.models ) { 895 foundData = findWidgetById( obj.attributes.elements.models, widgetId ); 896 if ( foundData ) { 897 return false; 898 } 899 } 900 }); 901 902 return foundData; 903 } 904 905 widgetData = findWidgetById( editorElements.models, widgetId ) || {}; 906 907 return { 908 'speed': widgetData['jet_tricks_widget_parallax_speed'] || { 'size': 50, 'unit': '%'}, 909 'parallax': widgetData['jet_tricks_widget_parallax'] || 'false', 910 'invert': widgetData['jet_tricks_widget_parallax_invert'] || 'false', 911 'stickyOn': widgetData['jet_tricks_widget_parallax_on'] || [ 'desktop', 'tablet', 'mobile'], 912 'satellite': widgetData['jet_tricks_widget_satellite'] || 'false', 913 'satelliteType': widgetData['jet_tricks_widget_satellite_type'] || 'text', 914 'satellitePosition': widgetData['jet_tricks_widget_satellite_position'] || 'top-center', 915 'tooltip': widgetData['jet_tricks_widget_tooltip'] || 'false', 916 'tooltipDescription': widgetData['jet_tricks_widget_tooltip_description'] || 'Lorem Ipsum', 917 'tooltipPlacement': widgetData['jet_tricks_widget_tooltip_placement'] || 'top', 918 'tooltipArrow': 'true' === widgetData['jet_tricks_widget_tooltip_arrow'] ? true : false, 919 'xOffset': widgetData['jet_tricks_widget_tooltip_x_offset'] || 0, 920 'yOffset': widgetData['jet_tricks_widget_tooltip_y_offset'] || 0, 921 'tooltipAnimation': widgetData['jet_tricks_widget_tooltip_animation'] || 'shift-toward', 922 'tooltipTrigger': widgetData['jet_tricks_widget_tooltip_trigger'] || 'mouseenter', 923 'customSelector': widgetData['jet_tricks_widget_tooltip_custom_selector'] || '', 924 'zIndex': widgetData['jet_tricks_widget_tooltip_z_index'] || '999', 925 'delay': widgetData['jet_tricks_widget_tooltip_delay'] || '0' 926 } 927 } 928 } 929 930 /** 931 * Jet jetViewMore Class 932 * 933 * @return {void} 934 */ 935 window.jetViewMore = function( $selector, settings ) { 936 var self = this, 937 $window = $( window ), 938 $button = $( '.jet-view-more__button', $selector ), 939 defaultSettings = { 940 sections: {}, 941 effect: 'move-up', 942 showall: false 943 }, 944 settings = $.extend( {}, defaultSettings, settings ), 945 sections = settings['sections'], 946 sectionsData = {}, 947 buttonVisible = true, 948 editMode = Boolean( elementor.isEditMode() ); 949 950 /** 951 * Init 952 */ 953 self.init = function() { 954 self.setSectionsData(); 955 956 if ( editMode ) { 957 return false; 958 } 959 960 // Add Events 961 $button.on( 'click', function() { 962 963 for ( var section in sectionsData ) { 964 var $section = sectionsData[ section ]['selector']; 965 966 if ( ! settings.showall ) { 967 if ( ! sectionsData[ section ]['visible'] ) { 968 sectionsData[ section ]['visible'] = true; 969 $section.css('height', $section[0].scrollHeight + 'px'); 970 $section.addClass( 'view-more-visible' ); 971 $section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' ); 972 973 break; 974 } 975 } else { 976 sectionsData[ section ]['visible'] = true; 977 $section.css('height', $section[0].scrollHeight + 'px'); 978 $section.addClass( 'view-more-visible' ); 979 $section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' ); 980 } 981 982 } 983 984 for ( var section in sectionsData ) { 985 buttonVisible = true; 986 987 if ( sectionsData[ section ]['visible'] ) { 988 buttonVisible = false;
989 } 990 } 991 992 if ( ! buttonVisible ) { 993 $button.css( { 'display': 'none' } ); 994 } 995 996 } ); 997 998 $button.keydown( function( e ) { 999 var $which = e.which || e.keyCode; 1000 1001 if ( $which == 13 || $which == 32 ) { 1002 for ( var section in sectionsData ) { 1003 var $section = sectionsData[ section ]['selector']; 1004 1005 if ( ! settings.showall ) { 1006 if ( ! sectionsData[ section ]['visible'] ) { 1007 sectionsData[ section ]['visible'] = true; 1008 $section.css('height', $section[0].scrollHeight + 'px'); 1009 $section.addClass( 'view-more-visible' ); 1010 $section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' ); 1011 1012 break; 1013 } 1014 } else { 1015 sectionsData[ section ]['visible'] = true; 1016 $section.css('height', $section[0].scrollHeight + 'px'); 1017 $section.addClass( 'view-more-visible' ); 1018 $section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' ); 1019 } 1020 1021 } 1022 1023 for ( var section in sectionsData ) { 1024 buttonVisible = true; 1025 1026 if ( sectionsData[ section ]['visible'] ) { 1027 buttonVisible = false; 1028 } 1029 } 1030 1031 if ( ! buttonVisible ) { 1032 $button.css( { 'display': 'none' } ); 1033 } 1034 } 1035 } ); 1036 }; 1037 1038 self.setSectionsData = function() { 1039 1040 for ( var section in sections ) { 1041 var $selector = $( '#' + sections[ section ] ); 1042 1043 if ( ! editMode ) { 1044 $selector.addClass( 'jet-view-more-section' ); 1045 } else { 1046 $selector.addClass( 'jet-view-more-section-edit-mode' ); 1047 } 1048 1049 sectionsData[ section ] = { 1050 'section_id': sections[ section ], 1051 'selector': $selector, 1052 'visible': false, 1053 } 1054 } 1055 }; 1056 }; 1057 1058 /** 1059 * [jetWidgetParallax description] 1060 * @param {[type]} $scope [description] 1061 * @return {[type]} [description] 1062 */ 1063 window.jetWidgetParallax = function( $scope ) { 1064 var self = this, 1065 $target = $scope, 1066 $section = $scope.closest( '.elementor-top-section' ), 1067 widgetId = $scope.data('id'), 1068 settings = {}, 1069 editMode = Boolean( elementor.isEditMode() ), 1070 $window = $( window ), 1071 isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/), 1072 platform = navigator.platform, 1073 safariClass = isSafari ? 'is-safari' : '', 1074 macClass = 'MacIntel' == platform ? ' is-mac' : ''; 1075 1076 /** 1077 * Init 1078 */ 1079 self.init = function() { 1080 1081 $scope.addClass( macClass ); 1082 1083 if ( ! editMode ) { 1084 settings = $scope.data( 'jet-tricks-settings' ); 1085 } else { 1086 settings = JetTricksTools.widgetEditorSettings( widgetId ); 1087 } 1088 1089 if ( ! settings ) { 1090 return false; 1091 } 1092 1093 if ( 'undefined' === typeof settings ) { 1094 return false; 1095 } 1096 1097 if ( 'false' === settings['parallax'] || 'undefined' === typeof settings['parallax'] ) { 1098 return false; 1099 } 1100 1101 $window.on( 'scroll.jetWidgetParallax resize.jetWidgetParallax', self.scrollHandler ).trigger( 'resize.jetWidgetParallax' ); 1102 }; 1103 1104 self.scrollHandler = function( event ) { 1105 var speed = +settings['speed']['size'] * 0.01, 1106 invert = 'true' == settings['invert'] ? -1 : 1, 1107 winHeight = $window.height(), 1108 winScrollTop = $window.scrollTop(), 1109 offsetTop = $scope.offset().top, 1110 thisHeight = $scope.outerHeight(), 1111 sectionHeight = $section.outerHeight(), 1112 positionDelta = winScrollTop - offsetTop + ( winHeight / 2 ), 1113 abs = positionDelta > 0 ? 1 : -1, 1114 posY = abs * Math.pow( Math.abs( positionDelta ), 0.85 ), 1115 availableDevices = settings['stickyOn'] || [], 1116 currentDeviceMode = elementorFrontend.getCurrentDeviceMode(); 1117 1118 posY = invert * Math.ceil( speed * posY ); 1119 1120 if ( -1 !== availableDevices.indexOf( currentDeviceMode ) ) { 1121 $target.css( { 1122 'transform': 'translateY(' + posY + 'px)' 1123 } ); 1124 } else { 1125 $target.css( { 1126 'transform': 'translateY(0)' 1127 } ); 1128 } 1129 }; 1130 }; 1131 1132 /** 1133 * [jetWidgetSatellite description] 1134 * @param {[type]} $scope [description] 1135 * @return {[type]} [description] 1136 */ 1137 window.jetWidgetSatellite = function( $scope ) { 1138 var self = this, 1139 widgetId = $scope.data('id'), 1140 settings = {}, 1141 editMode = Boolean( elementor.isEditMode() ); 1142 1143 /** 1144 * Init 1145 */ 1146 self.init = function() { 1147 1148 if ( ! editMode ) { 1149 settings = $scope.data( 'jet-tricks-settings' ); 1150 } else { 1151 settings = JetTricksTools.widgetEditorSettings( widgetId ); 1152 } 1153 1154 if ( ! settings ) { 1155 return false;
1156 } 1157 1158 if ( 'undefined' === typeof settings ) { 1159 return false; 1160 } 1161 1162 if ( 'false' === settings['satellite'] || 'undefined' === typeof settings['satellite'] ) { 1163 return false; 1164 } 1165 1166 $scope.addClass( 'jet-satellite-widget' ); 1167 1168 $( '.jet-tricks-satellite', $scope ).addClass( 'jet-tricks-satellite--' + settings['satellitePosition'] ); 1169 }; 1170 }; 1171 1172 /** 1173 * [jetWidgetTooltip description] 1174 * @param {[type]} $scope [description] 1175 * @return {[type]} [description] 1176 */ 1177 window.jetWidgetTooltip = function( $scope ) { 1178 var self = this, 1179 widgetId = $scope.data('id'), 1180 widgetSelector = $scope[0], 1181 tooltipSelector = widgetSelector, 1182 settings = {}, 1183 editMode = Boolean( elementor.isEditMode() ), 1184 delay, 1185 tooltipEvent = editMode ? 'click' : 'mouseenter'; 1186 1187 /** 1188 * Init 1189 */ 1190 self.init = function() { 1191 1192 if ( ! editMode ) { 1193 settings = $scope.data( 'jet-tricks-settings' ); 1194 } else { 1195 settings = JetTricksTools.widgetEditorSettings( widgetId ); 1196 } 1197 1198 if ( widgetSelector._tippy ) { 1199 widgetSelector._tippy.destroy(); 1200 } 1201 1202 if ( ! settings ) { 1203 return false; 1204 } 1205 1206 if ( 'undefined' === typeof settings ) { 1207 return false; 1208 } 1209 1210 if ( 'false' === settings['tooltip'] || 'undefined' === typeof settings['tooltip'] || '' === settings['tooltipDescription'] ) { 1211 return false; 1212 } 1213 1214 $scope.addClass( 'jet-tooltip-widget' ); 1215 1216 if ( settings['customSelector'] ) { 1217 tooltipSelector = $( '.' + settings['customSelector'], $scope )[0]; 1218 } 1219 1220 if ( editMode && ! $( '#jet-tricks-tooltip-content-' + widgetId )[0] ) { 1221 var template = $( '<div>', { 1222 id: 'jet-tricks-tooltip-content-' + widgetId, 1223 class: 'jet-tooltip-widget__content' 1224 } ); 1225 1226 template.html( settings['tooltipDescription'] ); 1227 $scope.append( template ); 1228 } 1229 1230 tippy( 1231 [ tooltipSelector ], 1232 { 1233 content: $scope.find( '.jet-tooltip-widget__content' )[0].innerHTML, 1234 allowHTML: true, 1235 //appendTo: widgetSelector, 1236 appendTo: editMode ? document.body : widgetSelector, 1237 arrow: settings['tooltipArrow'] ? true : false, 1238 placement: settings['tooltipPlacement'], 1239 offset: [ settings['xOffset'], settings['yOffset'] ], 1240 animation: settings['tooltipAnimation'], 1241 trigger: settings['tooltipTrigger'], 1242 interactive: true, 1243 zIndex: settings['zIndex'], 1244 maxWidth: 'none', 1245 delay: settings['delay']['size'] ? settings['delay']['size'] : 0, 1246 onCreate: function (instance) { 1247 if ( editMode ) { 1248 var dataId = tooltipSelector.getAttribute('data-id'); 1249 if ( dataId ) { 1250 instance.popper.classList.add( 'tippy-' + dataId ); 1251 } 1252 } 1253 } 1254 } 1255 ); 1256 1257 if ( editMode && widgetSelector._tippy ) { 1258 widgetSelector._tippy.show(); 1259 } 1260 1261 }; 1262 }; 1263 1264}( jQuery, window.elementorFrontend ) );
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.