1(function ($) { 2 3'use strict'; 4 5/*!========================================================================== 6 * ========================================================================== 7 * ========================================================================== 8 * 9 * Kinsey â AJAX Agency WordPress Theme 10 * 11 * [Table of Contents] 12 * 13 * 1. Arts Hover 14 * 2. Button Circles 15 * 3. Form 16 * 4. Scroll Down 17 * 5. Mobile Bar Height 18 * 6. Debounce 19 * 7. Get Color Values 20 * 8. Run On High Performance GPU 21 * 9. Sanitize Selector 22 * 10. Header 23 * 11. Load Slider Menu 24 * 12. Preloader 25 * 13. Section Content 26 * 14. Section Masthead 27 * 28 * ========================================================================== 29 * ========================================================================== 30 * ========================================================================== 31 */ 32 33/** 34 * Try to use high performance GPU on dual-GPU systems 35 */ 36runOnHighPerformanceGPU(); 37 38/** 39 * GSAP: turn off console warnings 40 * and include plugins 41 */ 42gsap.config({ 43 nullTargetWarn: false 44}); 45gsap.registerPlugin(DrawSVGPlugin); 46gsap.registerPlugin(ScrollTrigger); 47 48/** 49 * Global Vars 50 */ 51window.$document = $(document); 52window.$window = $(window); 53window.$body = $('body'); 54window.$html = $('html'); 55window.$pageHeader = $('#page-header'); 56window.$pagePreloader = $('#js-preloader'); 57window.$pageWrapper = $('#page-wrapper'); 58window.$pageContent = $('.page-wrapper__content'); 59window.$transitionCurtain = $('#js-page-transition-curtain'); 60window.$blockingCurtain = $('#js-page-blocking-curtain'); 61window.$barbaWrapper = $('[data-barba="wrapper"]'); 62window.$cursor = $('#js-arts-cursor'); 63window.$spinner = $('#js-spinner'); 64window.$adminBar = $('#wpadminbar'); 65 66/** 67 * Don't save scroll position 68 * after AJAX transition 69 */ 70if ('scrollRestoration' in history) { 71 history.scrollRestoration = 'manual'; 72} 73 74/** 75 * Default Template Options 76 */ 77if (typeof window.theme === 'undefined') { 78 window.theme = { 79 ajax: { 80 isRunning: false, 81 enabled: true, 82 customJS: '', 83 preventRules: '', // jQuery selectors of the elements to exclude them from AJAX transitions 84 evalInlineContainerScripts: true, 85 loadMissingScripts: true, 86 loadMissingStyles: true, 87 updateScriptNodes: '', 88 updateHeadNodes: '' 89 }, 90 animations: { 91 triggerHook: 0.15, 92 timeScale: { // slow down or speed up the animations 93 onScrollReveal: 1.0, 94 overlayMenuOpen: 1.0, 95 overlayMenuClose: 1.5, 96 preloader: 1.0, 97 ajaxFlyingImageTransition: 1.0, 98 ajaxCurtainTransition: 1.0 99 } 100 }, 101 cursorFollower: { 102 enabled: true, 103 highlight: { 104 scale: 1.5 105 }, 106 arrows: { 107 distance: 45 108 }, 109 trailing: 8, 110 animationDuration: 0.25 111 }, 112 mobileBarFix: { 113 enabled: true, 114 update: true 115 }, 116 isFirstLoad: true, 117 isSliderMenuLoaded: false, 118 isCustomizerPreview: false 119 } 120} 121/* Start Preloader */ 122window.kinsey.loading = new Preloader(); 123window.kinsey.loading.start(); 124 125/** 126 * Page Load Strategy 127 */ 128if (window.theme.elementor.isEditor) { 129 window.$window.on('elementor/frontend/init', function () { 130 new window.kinsey.components.Animations(); 131 132 initComponentsOnce({ 133 scope: elementor.$previewContents, 134 scrollToHashElement: false 135 }); 136 137 initComponents({ 138 scope: elementor.$previewContents, 139 scrollToHashElement: false 140 }); 141 }); 142} else { 143 144 document.addEventListener('DOMContentLoaded', (e) => { 145 new window.kinsey.components.Animations(); 146 147 // init on each AJAX transition 148 if (e.detail) { 149 150 initComponents(e.detail); 151 152 } else { // init only on initial page load 153 initComponentsOnce({ 154 scope: window.$document 155 }); 156 157 initComponents({ 158 scope: window.$document 159 }); 160 161 window.kinsey.loading.finish(); 162 } 163 }); 164 165} 166 167/** 168 * Init Template Components 169 * You can init your custom scripts here 170 * in that function 171 */ 172function initComponents({ 173 scope = window.$document, 174 container = window.$pageWrapper, 175 scrollToHashElement = true 176}) { 177 178 const 179 isElementorBuiltPage = window.$body.hasClass('elementor-built'), 180 $sectionMasthead = scope.find('.section-masthead:not(.d-none):not(.js-cancel-init)'), 181 $ajaxCommentsArea = scope.find('.js-ajax-comments-area'), 182 $sectionFixedReveal = scope.find('[data-arts-fixed-reveal]:not(.section-nav-projects)'), 183 $sectionContent = scope.find('.section-content'), 184 $buttonCircles = scope.find('.js-button-circles'), 185 $sectionGrid = scope.find('.section-grid'), 186 $scrollDown = scope.find('[data-arts-scroll-down]'), 187 $unitedGalleries = scope.find('.js-gallery-united'); 188 189 if ($sectionMasthead.length && !isElementorBuiltPage) { 190 $sectionMasthead.each(function () { 191 new window.kinsey.components.SectionMasthead({ 192 target: $(this), 193 scope 194 }); 195 }); 196 } 197 198 // // mobile bottom bar height fix 199 if (window.theme.mobileBarFix.enabled) { 200 new MobileBarHeight({ 201 target: $('.mobile-bar-height'), 202 scope 203 }); 204 } 205 206 if ($sectionGrid.length && !isElementorBuiltPage) { 207 window.kinsey.components.AssetsManager 208 .loadSectionGrid() 209 .then(() => { 210 $sectionGrid.each(function () { 211 new window.kinsey.components.SectionGrid({ 212 target: $(this), 213 scope 214 }); 215 }); 216 }); 217 } 218 219 if ($sectionFixedReveal.length) { 220 window.kinsey.components.AssetsManager 221 .loadSectionFixedReveal() 222 .then(() => { 223 $sectionFixedReveal.each(function () { 224 new window.kinsey.components.SectionFixedReveal({ 225 target: $(this), 226 scope 227 }); 228 }); 229 }); 230 } 231 232 if ($buttonCircles.length) { 233 $buttonCircles.each(function () { 234 new window.kinsey.components.ButtonCircles({ 235 target: $(this), 236 scope 237 }); 238 }); 239 } 240 241 if ($ajaxCommentsArea.length) { 242 window.kinsey.components.AssetsManager 243 .load(window.theme.assets['comments-js']) 244 .then(() => { 245 $ajaxCommentsArea.each(function () { 246 new window.kinsey.components.Comments({ 247 target: $(this), 248 scope 249 }); 250 }); 251 }); 252 } 253 254 if ($sectionContent.length && !isElementorBuiltPage) { 255 $sectionContent.each(function () { 256 new window.kinsey.components.SectionContent({ 257 target: $(this), 258 scope 259 }); 260 }); 261 } 262 263 if (!window.theme.elementor.isEditor && $unitedGalleries.length) { 264 $unitedGalleries.each(function () { 265 const 266 $unitedGallery = $(this), 267 $innerGalleries = $unitedGallery.find('.js-gallery'), 268 nonce = $innerGalleries.first().attr('data-nonce'); 269 270 if ($innerGalleries.length && nonce) { 271 window.kinsey.components.AssetsManager 272 .loadPhotoswipe(nonce) 273 .then(() => { 274 new window.kinsey.components.PswpGallery({ 275 target: $unitedGallery, 276 scope, 277 options: { 278 history: false, 279 showAnimationDuration: 300, 280 } 281 }); 282 }); 283 } 284 }); 285 } 286 287 if ($scrollDown.length) { 288 $scrollDown.each(function () { 289 new window.kinsey.components.ScrollDown({ 290 target: $(this), 291 scope, 292 duration: 0.6 293 }); 294 }) 295 } 296 297 new Form({ 298 target: scope, 299 scope 300 }); 301 302 // refresh animation triggers 303 // for Waypoints library 304 if (typeof Waypoint !== 'undefined') { 305 Waypoint.refreshAll(); 306 } 307 308 // custom JS code 309 if (window.theme.ajax.customJS) { 310 try { 311 window.eval(window.theme.ajax.customJS); 312 } catch (error) { 313 console.warn(error); 314 } 315 } 316 317 // scroll to anchor from URL hash 318 if (scrollToHashElement) {
319 window.kinsey.components.Scroll.scrollToAnchorFromHash(scrollToHashElement); 320 } 321 322 // Attempt to load slider menu 323 if (window.$pageHeader.length && !window.theme.isSliderMenuLoaded) { 324 loadSliderMenu(window.$document); 325 } 326} 327 328/** 329 * Init Template Components 330 * only once after the initial 331 * page load 332 */ 333function initComponentsOnce({ 334 scope = window.$document, 335 container = window.$pageWrapper 336}) { 337 if (!window.$cursor || !window.$cursor.length || window.Modernizr.touchevents) { 338 window.$html.addClass('no-cursorfollower'); 339 } 340 341 // Run AJAX navigation 342 if (window.theme.ajax.enabled && window.$barbaWrapper.length && !window.theme.elementor.isEditor) { 343 window.kinsey.components.AssetsManager.loadPJAX(); 344 } 345 346 // Run page header 347 window.theme.header = new Header({ 348 target: window.$pageHeader, 349 scope 350 }); 351} 352 353/*!======================================================================== 354 1. Arts Hover 355 ======================================================================!*/ 356window.kinsey.components.ArtsHover = class ArtsHover extends window.kinsey.components.BaseComponent { 357 constructor({ 358 target, 359 scope 360 }) { 361 super({ 362 target, 363 scope 364 }); 365 } 366 367 set() { 368 this.hoverClass = this.$target.data('arts-hover-class') || null; 369 this.$trigger = this.$target.find('[data-arts-hover="trigger"]'); 370 } 371 372 run() { 373 this._bindEvents(); 374 } 375 376 mount() { 377 return new Promise((resolve) => resolve(true)); 378 } 379 380 _bindEvents() { 381 this.$trigger 382 .on('mouseenter touchstart', () => { 383 this.$target.addClass(this.hoverClass); 384 }) 385 .on('mouseleave touchend', () => { 386 this.$target.removeClass(this.hoverClass); 387 }); 388 } 389} 390 391/*!======================================================================== 392 2. Button Circles 393 ======================================================================!*/ 394window.kinsey.components.ButtonCircles = class ButtonCircles extends window.kinsey.components.BaseComponent { 395 constructor({ 396 target, 397 scope 398 }) { 399 super({ 400 target, 401 scope 402 }); 403 } 404 405 set() { 406 this.$circles = this.$target.find('.circle'); 407 this.timeline = new gsap.timeline(); 408 409 this.timeline.set(this.$circles, { 410 drawSVG: '0% 0%' 411 }); 412 } 413 414 run() { 415 this.bindEvents(); 416 } 417 418 bindEvents() { 419 this.$target 420 .on('mouseenter touchstart', () => { 421 this.timeline 422 .clear() 423 .staggerTo(this.$circles, 0.6, { 424 drawSVG: '0% 100%', 425 ease: 'power4.out' 426 }, 0.05); 427 }) 428 .on('mouseleave touchend', () => { 429 this.timeline 430 .clear() 431 .staggerTo(this.$circles, 0.6, { 432 drawSVG: '0% 0%', 433 ease: 'power4.out' 434 }, 0.05); 435 }); 436 } 437} 438 439/*!======================================================================== 440 3. Form 441 ======================================================================!*/ 442class Form { 443 constructor({ 444 scope, 445 target 446 }) { 447 this.$scope = scope; 448 this.$target = target; 449 450 if (this.$scope.length) { 451 this.set(); 452 this.run(); 453 } 454 } 455 456 set() { 457 this.input = '.input-float__input'; 458 this.inputClassNotEmpty = 'input-float__input_not-empty'; 459 this.inputClassFocused = 'input-float__input_focused'; 460 this.$inputs = this.$scope.find(this.input); 461 } 462 463 run() { 464 this._floatLabels(); 465 this._bindEvents(); 466 467 if (typeof window.theme !== 'undefined' && window.theme.contactForm7.customModals) { 468 if ($('.wpcf7-form').length) { 469 window.kinsey.components.AssetsManager.loadBootstrapModal().then(() => this._attachModalsEvents()); 470 } 471 } 472 } 473 474 _floatLabels() { 475 const self = this; 476 477 if (!this.$inputs || !this.$inputs.length) { 478 return false; 479 } 480 481 this.$inputs.each(function () { 482 const 483 $el = $(this), 484 $controlWrap = $el.parent('.wpcf7-form-control-wrap'); 485 486 // not empty value 487 if ($el.val()) { 488 $el.addClass(self.inputClassNotEmpty); 489 $controlWrap.addClass(self.inputClassNotEmpty); 490 // empty value 491 } else { 492 $el.removeClass([self.inputClassFocused, self.inputClassNotEmpty]); 493 $controlWrap.removeClass([self.inputClassFocused, self.inputClassNotEmpty]); 494 } 495 496 // has placeholder & empty value 497 if ($el.attr('placeholder') && !$el.val()) { 498 $el.addClass(self.inputClassNotEmpty); 499 $controlWrap.addClass(self.inputClassNotEmpty); 500 } 501 }); 502 503 } 504 505 _bindEvents() { 506 const self = this; 507 508 this.$scope 509 .off('focusin') 510 .on('focusin', self.input, function () { 511 const 512 $el = $(this), 513 $controlWrap = $el.parent('.wpcf7-form-control-wrap'); 514 515 $el.addClass(self.inputClassFocused).removeClass(self.inputClassNotEmpty); 516 $controlWrap.addClass(self.inputClassFocused).removeClass(self.inputClassNotEmpty); 517 518 }) 519 .off('focusout') 520 .on('focusout', self.input, function () { 521 522 const 523 $el = $(this), 524 $controlWrap = $el.parent('.wpcf7-form-control-wrap'); 525 526 // not empty value 527 if ($el.val()) { 528 $el.removeClass(self.inputClassFocused).addClass(self.inputClassNotEmpty); 529 $controlWrap.removeClass(self.inputClassFocused).addClass(self.inputClassNotEmpty); 530 } else { 531 // has placeholder & empty value 532 if ($el.attr('placeholder')) { 533 $el.addClass(self.inputClassNotEmpty); 534 $controlWrap.addClass(self.inputClassNotEmpty); 535 } 536 537 $el.removeClass(self.inputClassFocused); 538 $controlWrap.removeClass(self.inputClassFocused); 539 } 540 541 }); 542 543 } 544 545 _attachModalsEvents() { 546 window.$document 547 .off('wpcf7submit') 548 .on('wpcf7beforesubmit', (e) => { 549 const 550 $form = $(e.target), 551 $submit = $form.find('[type="submit"]'); 552 553 $form.addClass('pointer-events-none'); 554 window.$body.addClass('cursor-progress'); 555 556 557 if ($submit.length) { 558 const 559 $title = $submit.find('.button__label-hover .button__title'), 560 $icons = $submit.find('.button__icon'); 561 562 $title.data('original-title', $title.text()); 563 564 $submit.addClass('button_hovered'); 565 $title.html('<svg class="spinner spinner_small" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="spinner__path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle></svg>'); 566 567 if ($icons.length) { 568 gsap.set($icons, { 569 autoAlpha: 0 570 }); 571 } 572 } 573 574 // Set loading cursor follower 575 if (window.$cursor && window.$cursor.length) { 576 window.$cursor.trigger('startLoading'); 577 } 578 }) 579 .on('wpcf7submit', (e) => { 580 581 const 582 $modal = $('#modalContactForm7'), 583 $form = $(e.target), 584 $submit = $form.find('[type="submit"]'); 585 let template; 586 587 $modal.modal('dispose').remove(); 588 589 if (e.detail.apiResponse.status === 'mail_sent') { 590 591 template = this._getModalTemplate({ 592 icon: 'icon-success.svg', 593 message: e.detail.apiResponse.message, 594 }); 595 596 this._createModal({ 597 template, 598 onDismiss: () => { 599 $(e.target).find(this.input).parent().val('').removeClass(this.inputClassFocused).removeClass(this.inputClassNotEmpty); 600 } 601 }); 602 } 603 604 if (e.detail.apiResponse.status === 'mail_failed') { 605 template = this._getModalTemplate({ 606 icon: 'icon-error.svg', 607 message: e.detail.apiResponse.message 608 }); 609 610 this._createModal({ 611 template 612 }); 613 } 614 615 $form.removeClass('pointer-events-none'); 616 window.$body.removeClass('cursor-progress'); 617 618 // Hide loading cursor follower 619 if (window.$cursor && window.$cursor.length) { 620 window.$cursor.trigger('finishLoading'); 621 } 622 623 if ($submit.length) { 624 const 625 $title = $submit.find('.button__label-hover .button__title'), 626 originalTitle = $title.data('original-title'), 627 $icons = $submit.find('.button__icon'); 628 629 $submit.removeClass('button_hovered'); 630 631 if ($title.length && originalTitle) {
632 $title.text(originalTitle); 633 } 634 635 if ($icons.length) { 636 gsap.set($icons, { 637 clearProps: 'opacity,visibility' 638 }); 639 } 640 } 641 642 }); 643 } 644 645 _getModalTemplate({ 646 icon, 647 message 648 }) { 649 return ` 650 <div class="modal fade" id="modalContactForm"> 651 <div class="modal-dialog modal-dialog-centered"> 652 <div class="modal-content radius-img"> 653 <div class="modal__close" data-dismiss="modal"><img src="${window.theme.themeURL}/img/modal/icon-close.svg"/></div> 654 <header class="text-center mb-1"> 655 <img src="${window.theme.themeURL}/img/modal/${icon}" width="80px" height="80px" alt=""/> 656 <p class="modal__message h4"><strong>${message}</strong></p> 657 </header> 658 <button type="button" class="button button_solid bg-dark-1 button_fullwidth" data-dismiss="modal"><span class="button__label button__label-normal"><span class="button__title">OK</span></span><span class="button__label button__label-hover"><span class="button__title">OK</span></span> 659 </button> 660 </div> 661 </div> 662 </div> 663 `; 664 } 665 666 _createModal({ 667 template, 668 onDismiss 669 }) { 670 671 if (!template) { 672 return false; 673 } 674 675 let $modal; 676 window.$body.append(template); 677 $modal = $('#modalContactForm'); 678 679 $modal.modal('show'); 680 $modal.on('hidden.bs.modal', () => { 681 if (typeof onDismiss === 'function') { 682 onDismiss(); 683 } 684 $modal.modal('dispose').remove(); 685 }); 686 } 687} 688 689/*!======================================================================== 690 4. Scroll Down 691 ======================================================================!*/ 692window.kinsey.components.ScrollDown = class ScrollDown extends window.kinsey.components.BaseComponent { 693 constructor({ 694 target, 695 scope, 696 duration = 0.6 697 }) { 698 super({ 699 target, 700 scope 701 }) 702 703 this.duration = parseFloat(duration); 704 } 705 706 run() { 707 this._bindEvents(); 708 } 709 710 _bindEvents() { 711 this.$target.on('click', (e) => { 712 e.preventDefault(); 713 this._scrollDown(); 714 }); 715 } 716 717 _scrollDown() { 718 window.kinsey.components.Scroll.scrollTo({ 719 x: 0, 720 y: window.innerHeight + Math.min(0, -window.$pageHeader.height()), 721 duration: this.duration 722 }); 723 } 724} 725 726/*!======================================================================== 727 5. Mobile Bar Height 728 ======================================================================!*/ 729class MobileBarHeight extends window.kinsey.components.BaseComponent { 730 constructor({ 731 target, 732 scope 733 }) { 734 super({ 735 target, 736 scope 737 }); 738 this.vh = 0; 739 this._createStyleElement(); 740 this._setVh(); 741 742 if (window.theme.mobileBarFix.update) { 743 this._bindEvents(); 744 } 745 } 746 747 _setVh() { 748 this.vh = window.innerHeight * 0.01;
749 $('#arts-fix-bar').html(`:root { --fix-bar-vh: ${this.vh}px; }`); 750 } 751 752 _bindEvents() { 753 const event = this.getResponsiveResizeEvent(); 754 755 window.$window.on(event, this.debounce(() => { 756 this._setVh(); 757 }, 250)); 758 } 759 760 _createStyleElement() { 761 if (!$('#arts-fix-bar').length) { 762 $('head').append('<style id="arts-fix-bar"></style>'); 763 } 764 } 765} 766 767/*!======================================================================== 768 6. Debounce 769 ======================================================================!*/ 770function debounce(func, wait, immediate) { 771 let timeout; 772 773 return () => { 774 let 775 context = this, 776 args = arguments; 777 778 let later = () => { 779 timeout = null; 780 781 if (!immediate) { 782 func.apply(context, args) 783 }; 784 }; 785 786 let callNow = immediate && !timeout; 787 788 clearTimeout(timeout); 789 790 timeout = setTimeout(later, wait); 791 792 if (callNow) { 793 func.apply(context, args) 794 }; 795 }; 796} 797 798/*!======================================================================== 799 7. Get Color Values 800 ======================================================================!*/ 801// return array of [r,g,b,a] from any valid color. if failed returns undefined 802function getColorValues(color) { 803 804 // empty argument 805 if (color === '') { 806 return; 807 } 808 809 // transparent color 810 if (color.toLowerCase() === 'transparent') { 811 return [0, 0, 0, 0]; 812 } 813 814 // HEX 815 if (color[0] === '#') { 816 if (color.length < 7) { 817 // convert #RGB and #RGBA to #RRGGBB and #RRGGBBAA 818 color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3] + (color.length > 4 ? color[4] + color[4] : ''); 819 } 820 821 return [parseInt(color.substr(1, 2), 16), 822 parseInt(color.substr(3, 2), 16), 823 parseInt(color.substr(5, 2), 16), 824 color.length > 7 ? parseInt(color.substr(7, 2), 16) / 255 : 1 825 ]; 826 } 827 // RGB 828 if (color.indexOf('rgb') === -1) { 829 // convert named colors 830 let temp_elem = document.body.appendChild(document.createElement('fictum')); // intentionally use unknown tag to lower chances of css rule override with !important 831 let flag = 'rgb(1, 2, 3)'; // this flag tested on chrome 59, ff 53, ie9, ie10, ie11, edge 14 832 833 temp_elem.style.color = flag; 834 835 if (temp_elem.style.color !== flag) { 836 return; // color set failed - some monstrous css rule is probably taking over the color of our object 837 } 838 839 temp_elem.style.color = color; 840 if (temp_elem.style.color === flag || temp_elem.style.color === '') { 841 return; // color parse failed 842 } 843 844 color = getComputedStyle(temp_elem).color; 845 document.body.removeChild(temp_elem); 846 } 847 848 // RGBA 849 if (color.indexOf('rgb') === 0) { 850 if (color.indexOf('rgba') === -1) { 851 color += ',1'; // convert 'rgb(R,G,B)' to 'rgb(R,G,B)A' which looks awful but will pass the regxep below 852 return color.match(/[\.\d]+/g).map(function (a) { 853 return +a; 854 }); 855 } 856 } 857} 858 859/*!======================================================================== 860 8. Run On High Performance GPU 861 ======================================================================!*/ 862function runOnHighPerformanceGPU() { 863 const webGLCanvas = document.getElementById('js-webgl'); 864 865 // don't run on mobile devices 866 if (!window.Modernizr.touchevents && webGLCanvas !== null && typeof webGLCanvas !== undefined) { 867 webGLCanvas.getContext('webgl', { 868 powerPreference: 'high-performance' 869 }); 870 } 871} 872 873/*!======================================================================== 874 9. Sanitize Selector 875 ======================================================================!*/ 876function sanitizeSelector(string) { 877 if (!string || !string.length) { 878 return false; 879 } 880 881 return string 882 .replace(/(\r\n|\n|\r)/gm, '') // remove tabs, spaces 883 .replace(/(\\n)/g, '') // remove lines breaks 884 .replace(/^[,\s]+|[,\s]+$/g, '') // remove redundant commas 885 .replace(/\s*,\s*/g, ','); // remove duplicated commas 886} 887 888/*!======================================================================== 889 10. Header 890 ======================================================================!*/ 891class Header extends window.kinsey.components.BaseComponent { 892 constructor({ 893 target, 894 scope 895 }) { 896 super({ 897 target, 898 scope 899 }); 900 } 901 902 set() { 903 this.$controls = this.$target.find('.header__controls'); 904 this.$stickyHeader = this.$target.filter('.js-header-sticky');
905 this.$burger = this.$target.find('#js-burger'); 906 this.$overlay = this.$target.find('.header__wrapper-overlay-menu'); 907 this.$maskRevealOverlay = this.$overlay.find('.mask-reveal'); 908 this.$wrapperMenu = this.$target.find('.header__wrapper-menu'); 909 this.burgerOpenClass = 'header__burger_opened'; 910 this.$headerColumns = this.$target.find('.header__col'); 911 this.$headerLeft = this.$target.find('.header__col-left, .header__col-right'); 912 this.$overlayWidgets = this.$target.find('.header__wrapper-overlay-widgets'); 913 this.$allLinksOverlay = this.$target.find('.menu-overlay a'); 914 this.$allLinksClassic = this.$target.find('.menu a'); 915 this.$wrapperSlider = this.$target.find('.header__wrapper-slider'); 916 this.$headerLabelSubmenu = this.$target.find('.js-header-label-submenu'); 917 this.$infoLabel = this.$target.find('.header__overlay-menu-info'); 918 919 this.color = this._getColorTheme(); 920 this.colorSaved = this.color; 921 922 // Menu 923 this.$menu = this.$target.find('.js-menu'); 924 this.$menuOverlay = this.$overlay.find('.js-menu-overlay'); 925 this.$menuLinks = this.$overlay.find('.menu-overlay > li > a'); 926 this.$menuColumn = this.$overlay.find('.header__menu-column'); 927 this.$menuSmoothScrollingContainer = this.$overlay.find('.js-header-smooth-scroll-container'); 928 this.$menuGradientTop = this.$overlay.find('.header__menu-gradient_top'); 929 this.$menuGradientBottom = this.$overlay.find('.header__menu-gradient_bottom'); 930 this.selectedClass = 'selected'; 931 this.openClass = 'opened'; 932 this.currentMenuItemClass = 'current-menu-item'; 933 this.currentMenuAncestorClass = 'current-menu-ancestor'; 934 this.menuItemHasChildrenClass = 'menu-item-has-children'; 935 this.hoverClassOverlay = 'menu-overlay_hover'; 936 this.hoverClassClassic = 'menu_hover'; 937 938 // Submenu 939 this.$submenu = this.$overlay.find('.menu-overlay .sub-menu'); 940 this.$submenuButton = $('#js-submenu-back'); 941 this.$submenuOpeners = this.$overlay.find(`.${this.menuItemHasChildrenClass} > a`); 942 this.$submenuLinks = this.$submenu.find('> li > a'); 943 this.currentSubmenuLabel = ''; 944 this.prevSubmenuLabel = ''; 945 946 // Sticky 947 this.stickyScene = undefined; 948 this.stickyClass = 'header_sticky'; 949 this.stickyTimeline = new gsap.timeline(); 950 951 // Scrollbar 952 this.SB = undefined; 953 954 // Lock 955 this.lockClass = 'pointer-events-none'; 956 this.unlockClass = 'pointer-events-auto'; 957 958 this.labelTimeline = new gsap.timeline(); 959 960 this.setMenu(); 961 this._setMenusHover(); 962 } 963 964 run() { 965 if (typeof this.stickyScene !== 'undefined') { 966 this.stickyScene.refresh(); 967 this.stickyScene.disable(); 968 } 969 970 this.timeline = new gsap.timeline(); 971 this._correctTopOffset(); 972 this._stick(); 973 this._bindEvents(); 974 this._handleAnchors(); 975 this._runSmoothScrollOverlayMenu(); 976 this._setGradientBackgrounds(); 977 } 978 979 setBurger(open = false) { 980 if (open) { 981 this.$target.addClass(this.openClass); 982 this.$burger.addClass(this.burgerOpenClass); 983 } else { 984 this.$target.removeClass(this.openClass); 985 this.$burger.removeClass(this.burgerOpenClass); 986 } 987 } 988 989 setMenu() { 990 991 if (this.$headerColumns.length) { 992 gsap.set(this.$headerColumns, { 993 clearProps: 'all' 994 }); 995 } 996 997 if (this.$wrapperSlider.length) { 998 gsap.set(this.$wrapperSlider, { 999 autoAlpha: 0 1000 }); 1001 } 1002 1003 if (this.$overlay.length) { 1004 gsap.set(this.$overlay, { 1005 autoAlpha: 0, 1006 display: 'none', 1007 clearProps: 'transform' 1008 }); 1009 } 1010 1011 if (this.$menuOverlay.length) { 1012 this.$menuOverlay.removeClass(this.lockClass).addClass(this.unlockClass); 1013 } 1014 1015 if (this.$submenu.length) { 1016 gsap.set(this.$submenu, { 1017 autoAlpha: 0 1018 }); 1019 this.$submenu.removeClass(this.unlockClass).addClass(this.lockClass); 1020 } 1021 1022 if (this.$submenuButton.length) { 1023 gsap.set(this.$submenuButton, { 1024 autoAlpha: 0 1025 }); 1026 } 1027 1028 this.$submenu.removeClass(this.openClass); 1029 this.$target.removeClass(this.openClass); 1030 this.$burger.removeClass(this.burgerOpenClass); 1031 1032 if (this.$menuLinks.length) { 1033 gsap.effects.setLines(this.$menuLinks, { 1034 autoAlpha: 1, 1035 y: '-100%' 1036 }); 1037 } 1038 1039 if (this.$submenuLinks.length) { 1040 gsap.effects.setLines(this.$submenuLinks, { 1041 autoAlpha: 1, 1042 y: '-100%' 1043 }); 1044 } 1045 1046 if (this.$overlayWidgets.length) { 1047 gsap.set(this.$overlayWidgets, { 1048 autoAlpha: 0, 1049 y: -30 1050 }); 1051 } 1052 1053 if (this.$infoLabel.length) { 1054 gsap.set(this.$infoLabel, { 1055 x: -30, 1056 autoAlpha: 0 1057 }); 1058 } 1059 1060 this.$wrapperMenu.scrollTop(0); 1061 1062 if (typeof this.SB !== 'undefined') { 1063 this.SB.scrollTo(0, 0); 1064 } 1065 } 1066 1067 openMenu() { 1068 const timeScale = parseFloat(window.theme.animations.timeScale.overlayMenuOpen) || 1; 1069 1070 return this.timeline 1071 .clear() 1072 .set(this.$overlay, { 1073 autoAlpha: 1, 1074 display: 'block', 1075 y: () => this._getOverlayTopOffsetInAbsoluteHeaderSmoothScroling() 1076 }) 1077 .add([() => { 1078 this._setTransition(true); 1079 1080 // save current color theme which 1081 // can be different from the initial one
1082 this.colorSaved = this._getColorTheme(); 1083 this.el.dispatchEvent(new CustomEvent('menuOpenStart')); 1084 this._unstick(); 1085 this._updateThemeHeader({ 1086 text: this.color.overlay.text 1087 }); 1088 }]) 1089 .set(window.$adminBar, { 1090 position: 'fixed', 1091 }) 1092 .animateMask(this.$maskRevealOverlay, { 1093 scale: 1, 1094 direction: 'down' 1095 }, 'start') 1096 .to(this.$headerLeft, { 1097 duration: 1.2, 1098 x: 30, 1099 autoAlpha: 0, 1100 ease: 'expo.inOut' 1101 }, 'start') 1102 .to(this.$infoLabel, { 1103 duration: 1.2, 1104 x: 0, 1105 delay: 0.1, 1106 autoAlpha: 1, 1107 ease: 'expo.inOut' 1108 }, 'start') 1109 .add(() => { 1110 this.$target.addClass(this.openClass); 1111 }, '-=0.6') 1112 .add([ 1113 gsap.effects.animateLines(this.$menuLinks, { 1114 stagger: { 1115 amount: 0.3, 1116 from: 'end' 1117 }, 1118 duration: 1.2, 1119 ease: 'power4.out' 1120 }), 1121 gsap.to(this.$overlayWidgets, { 1122 autoAlpha: this._isMediumScreen() ? 1 : 0, 1123 y: this._isMediumScreen() ? 0 : 30, 1124 duration: 1.2, 1125 ease: 'power4.out' 1126 }), 1127 ], '-=1.0') 1128 .to(this.$wrapperSlider, { 1129 autoAlpha: 1, 1130 duration: 1.8 1131 }, 'start') 1132 .add(() => { 1133 this.el.dispatchEvent(new CustomEvent('menuOpenEnd')); 1134 this._setTransition(false); 1135 }, '-=0.6') 1136 .timeScale(timeScale); 1137 } 1138 1139 closeMenu(force = false, cb) { 1140 1141 if (!this.$target.hasClass(this.openClass) && !force) { 1142 return this.timeline; 1143 } 1144 1145 const 1146 $submenuLinksCurrent = this.$submenu.filter(`.${this.openClass}`).find(this.$submenuLinks), 1147 timeScale = parseFloat(window.theme.animations.timeScale.overlayMenuClose) || 1; 1148 1149 return this.timeline 1150 .clear() 1151 .add(() => { 1152 this._setTransition(true); 1153 this.el.dispatchEvent(new CustomEvent('menuCloseStart')); 1154 this._stick(); 1155 1156 if (this.$stickyHeader.length && window.pageYOffset >= 1) { 1157 this.$stickyHeader.addClass(this.stickyClass); 1158 1159 // restore theme header from the saved version 1160 this._updateThemeHeader({ 1161 theme: this.colorSaved.sticky.theme, 1162 text: this.colorSaved.sticky.text 1163 }); 1164 } else { 1165 this._updateThemeHeader({ 1166 text: this.colorSaved.normal.text 1167 }); 1168 } 1169 }) 1170 .to(this.$wrapperSlider, { 1171 autoAlpha: 0, 1172 duration: 1.8 1173 }, 'start') 1174 .hideMask(this.$maskRevealOverlay, { 1175 scale: 1, 1176 direction: 'down', 1177 }, 'start') 1178 .set(window.$adminBar, { 1179 clearProps: 'position' 1180 }) 1181 .to(this.$headerLeft, { 1182 duration: 1.2, 1183 x: 0, 1184 delay: 0.1, 1185 autoAlpha: 1, 1186 ease: 'expo.inOut' 1187 }, 'start') 1188 .to(this.$infoLabel, { 1189 duration: 1.2, 1190 x: -30, 1191 autoAlpha: 0 1192 }, 'start') 1193 .to(this.$submenuButton, { 1194 x: -10, 1195 autoAlpha: 0, 1196 duration: 0.3 1197 }, 'start') 1198 .add(() => { 1199 this.$target.removeClass(this.openClass); 1200 }, '-=0.9') 1201 .add([ 1202 gsap.effects.hideLines([$submenuLinksCurrent, this.$menuLinks], { 1203 stagger: { 1204 amount: 0, 1205 from: 'end'
1206 }, 1207 y: '100%', 1208 duration: 0.6, 1209 }), 1210 gsap.to(this.$overlayWidgets, { 1211 autoAlpha: 0, 1212 duration: 0.6, 1213 y: -30, 1214 ease: 'power4.out' 1215 }) 1216 ], 'start') 1217 .add(() => { 1218 if (typeof cb === 'function') { 1219 cb(); 1220 } 1221 this.el.dispatchEvent(new CustomEvent('menuCloseEnd')); 1222 this.setMenu(); 1223 this._setTransition(false); 1224 }, '-=0.6') 1225 .timeScale(timeScale); 1226 } 1227 1228 closeMenuTransition(force = false, cb) { 1229 1230 if (!this.$target.hasClass(this.openClass) && !force) { 1231 return this.timeline; 1232 } 1233 1234 const 1235 tl = new gsap.timeline(), 1236 $submenuLinksCurrent = this.$submenu.filter(`.${this.openClass}`).find(this.$submenuLinks), 1237 timeScale = window.theme.animations.timeScale.overlayMenuClose || 1; 1238 1239 return tl 1240 .add(() => { 1241 this._setTransition(true); 1242 this.el.dispatchEvent(new CustomEvent('menuCloseStart')); 1243 this.setBurger(false); 1244 }) 1245 .to(this.$wrapperSlider, { 1246 autoAlpha: 0, 1247 duration: 1.8 1248 }, 'start') 1249 .hideMask(this.$maskRevealOverlay, { 1250 scale: 1, 1251 direction: 'down', 1252 }, 'start') 1253 .set(window.$adminBar, { 1254 clearProps: 'position' 1255 }) 1256 .to(this.$headerLeft, { 1257 duration: 1.2, 1258 x: 0, 1259 delay: 0.1, 1260 autoAlpha: 1, 1261 ease: 'expo.inOut' 1262 }, 'start') 1263 .to(this.$infoLabel, { 1264 duration: 1.2, 1265 x: -30, 1266 autoAlpha: 0 1267 }, 'start') 1268 .to(this.$submenuButton, { 1269 x: -10, 1270 autoAlpha: 0, 1271 duration: 0.3 1272 }, 'start') 1273 .add(() => { 1274 this.$target.removeClass(this.openClass); 1275 }, '-=0.9') 1276 .add([ 1277 gsap.effects.hideLines([$submenuLinksCurrent, this.$menuLinks], { 1278 stagger: { 1279 amount: 0, 1280 from: 'end'
1281 }, 1282 y: '100%', 1283 duration: 0.6, 1284 }), 1285 gsap.to(this.$overlayWidgets, { 1286 autoAlpha: 0, 1287 y: -30, 1288 duration: 0.6, 1289 ease: 'power4.out' 1290 }) 1291 ], 'start') 1292 .add(() => { 1293 if (typeof cb === 'function') { 1294 cb(); 1295 } 1296 this.el.dispatchEvent(new CustomEvent('menuCloseEnd')); 1297 this.setMenu(); 1298 this._setTransition(false); 1299 }) 1300 .timeScale(timeScale); 1301 } 1302 1303 _bindEvents() { 1304 const self = this; 1305 1306 if (window.$adminBar.length) { 1307 window.$window.on('resize', this.debounce(() => { 1308 this._correctTopOffset(); 1309 }, 250)); 1310 } 1311 1312 if (this.$burger.length) { 1313 this.$burger.off('click').on('click', (e) => { 1314 e.preventDefault(); 1315 1316 if (this._isInTransition()) { 1317 return; 1318 } 1319 1320 if (this.$burger.hasClass(this.burgerOpenClass)) { 1321 this.closeMenu(); 1322 this.$burger.removeClass(this.burgerOpenClass); 1323 } else { 1324 this.openMenu(); 1325 this.$burger.addClass(this.burgerOpenClass); 1326 } 1327 }); 1328 } 1329 1330 if (this.$submenuOpeners.length) { 1331 this.$submenuOpeners.on('click', function (e) { 1332 if (self._isInTransition()) { 1333 e.preventDefault(); 1334 return; 1335 } 1336 1337 const 1338 $el = $(this), 1339 $currentMenu = $el.parents('ul'), 1340 $submenu = $el.next('.sub-menu'); 1341 1342 if ($submenu.length) { 1343 e.preventDefault(); 1344 1345 $el.addClass(self.linkSelectedClass); 1346 1347 self._openSubmenu({ 1348 submenu: $submenu, 1349 currentMenu: $currentMenu 1350 }); 1351 1352 self._updateLabel({ 1353 text: $el.find('.menu-overlay__heading').text() 1354 }); 1355 } 1356 }); 1357 } 1358 1359 if (this.$submenuButton.length) { 1360 this.$submenuButton.on('click', (e) => { 1361 e.preventDefault(); 1362 1363 if (self._isInTransition()) { 1364 return; 1365 } 1366 1367 const $submenu = this.$submenu.filter(`.${this.openClass}`), 1368 $prevMenu = $submenu.parent('li').parent('ul'); 1369 1370 self._closeSubmenu({ 1371 submenu: $submenu, 1372 currentMenu: $prevMenu 1373 }); 1374 1375 self._updateLabel({ 1376 text: $prevMenu.siblings('a').find('.menu-overlay__heading').text() 1377 }); 1378 }); 1379 } 1380 1381 // Customizer & Elementor preview options update 1382 this.$target 1383 .on('update', () => { 1384 this._unstick(); 1385 this.set(); 1386 this.stickyScene = undefined; 1387 this.timeline.clear(); 1388 this._stick(); 1389 this._setTransition(false); 1390 this._setGradientBackgrounds(); 1391 }) 1392 .on('updateOverlayMenu', () => { 1393 this.color = this._getColorTheme(); 1394 this._setGradientBackgrounds(); 1395 }) 1396 .on('updateSubmenuLabel', () => { 1397 this.$headerLabelSubmenu = this.$target.find('.js-header-label-submenu'); 1398 this.$infoLabel = this.$target.find('.header__overlay-menu-info'); 1399 1400 if (this.$headerLabelSubmenu.length) { 1401 this._updateLabel({ 1402 text: this.currentSubmenuLabel 1403 }); 1404 } 1405 }); 1406 1407 window.$window 1408 .on('arts/barba/transition/start', () => { 1409 this._unstick(); 1410 this._setTransition(true); 1411 }) 1412 .on('arts/barba/transition/end', () => { 1413 this.$controls.removeClass('pointer-events-none'); 1414 this.color = this._getColorTheme(); 1415 this.stickyScene = undefined; 1416 this.timeline.clear(); 1417 this._stick(); 1418 this._setTransition(false); 1419 this._handleAnchors(); 1420 this._setGradientBackgrounds(); 1421 }); 1422 } 1423 1424 isOverlayOpened() { 1425 return this.$target.hasClass(this.openClass); 1426 } 1427 1428 _getColorTheme() { 1429 return { 1430 normal: { 1431 text: this.$target.attr('data-arts-theme-text') || 'dark' 1432 }, 1433 sticky: { 1434 theme: this.$stickyHeader.attr('data-arts-header-sticky-theme') || null, 1435 text: this.$stickyHeader.attr('data-arts-header-sticky-theme-text') || 'dark' 1436 }, 1437 overlay: { 1438 text: this.$target.attr('data-arts-header-overlay-theme-text') || 'dark' 1439 } 1440 }; 1441 } 1442 1443 _updateThemeHeader({ 1444 theme, 1445 removeTheme, 1446 text, 1447 }) { 1448 if (theme) { 1449 this.$target.addClass(theme); 1450 } 1451 1452 if (text) { 1453 this.$target.attr('data-arts-theme-text', text); 1454 } 1455 1456 if (removeTheme) { 1457 this.$target.removeClass(removeTheme); 1458 } 1459 } 1460 1461 _isMediumScreen() { 1462 return window.Modernizr.mq('(max-width: 991px)'); 1463 } 1464 1465 _isInTransition() { 1466 return this.$target.attr('data-arts-header-animation') === 'intransition'; 1467 } 1468 1469 _setTransition(inTransition = true) { 1470 return this.$target.attr('data-arts-header-animation', inTransition ? 'intransition' : ''); 1471 } 1472 1473 _correctTopOffset() { 1474 if (typeof window.SB !== 'undefined' && this.$target.attr('data-arts-scroll-absolute')) { 1475 return; 1476 } 1477 1478 const top = window.$adminBar.length ? window.$adminBar.height() : 0; 1479 1480 if (top > 0) { 1481 gsap.to(this.$target, { 1482 duration: 0.6, 1483 top 1484 }); 1485 } 1486 } 1487 1488 _getOverlayTopOffsetInAbsoluteHeaderSmoothScroling() { 1489 const 1490 isAbsolutePosition = gsap.getProperty(this.target, 'position') === 'absolute', 1491 top = window.$adminBar.length ? window.$adminBar.height() : 0; 1492 1493 if (isAbsolutePosition && typeof window.SB !== 'undefined') { 1494 return window.SB.offset.y - top; 1495 } 1496 1497 return 0; 1498 } 1499 1500 _stick() { 1501 if (!this.$stickyHeader.length) { 1502 return; 1503 } 1504 1505 if (this.stickyScene) { 1506 this.stickyScene.refresh(true); 1507 this.stickyScene.enable(); 1508 return; 1509 } 1510 1511 const classesToggle = [this.color.sticky.theme, this.stickyClass].join(' '); 1512 1513 this.stickyScene = ScrollTrigger.create({ 1514 start: 2, 1515 end: 'bottom center', 1516 scrub: true, 1517 onEnter: () => { 1518 this._updateThemeHeader({ 1519 theme: classesToggle, 1520 text: this.color.sticky.text 1521 }); 1522 }, 1523 onLeaveBack: () => { 1524 this._updateThemeHeader({ 1525 removeTheme: classesToggle, 1526 text: this.color.normal.text 1527 }); 1528 } 1529 }); 1530 } 1531 1532 _unstick() { 1533 if (!this.$stickyHeader.length || !this.stickyScene) { 1534 return; 1535 } 1536 1537 const classesToggle = [this.color.sticky.theme, this.stickyClass].join(' '); 1538 1539 this.stickyScene.disable(); 1540 this._updateThemeHeader({ 1541 removeTheme: classesToggle 1542 }); 1543 } 1544 1545 _openSubmenu({ 1546 submenu, 1547 currentMenu 1548 }) { 1549 const 1550 $currentLinks = currentMenu.find('> li > a .menu-overlay__item-wrapper'), 1551 $submenuLinks = submenu.find('> li > a .menu-overlay__item-wrapper'); 1552 1553 this.timeline 1554 .clear() 1555 .add(() => { 1556 this._setTransition(true); 1557 this.$submenu.removeClass(this.openClass); 1558 submenu.not(this.$menuOverlay).addClass(this.openClass); 1559 1560 this.$submenu.not(submenu).removeClass(this.unlockClass).addClass(this.lockClass); 1561 submenu.removeClass(this.lockClass).addClass(this.unlockClass); 1562 1563 if (typeof this.SB !== 'undefined') { 1564 this.SB.track.yAxis.hide(); 1565 this.SB.track.update(); 1566 } 1567 1568 if (this.$submenu.hasClass(this.openClass)) { 1569 this.$menuOverlay.removeClass(this.unlockClass).addClass(this.lockClass); 1570 1571 gsap.to(this.$submenuButton, { 1572 autoAlpha: 1, 1573 x: 0, 1574 duration: 0.3 1575 }); 1576 1577 if (this._isMediumScreen()) { 1578 gsap.to(this.$overlayWidgets, { 1579 autoAlpha: 0, 1580 y: 30, 1581 duration: 1.2, 1582 ease: 'power4.out', 1583 }); 1584 } 1585 } else { 1586 this.$menuOverlay.removeClass(this.lockClass).addClass(this.unlockClass); 1587 1588 gsap.to(this.$submenuButton, { 1589 autoAlpha: 0, 1590 x: -10, 1591 duration: 0.3 1592 }); 1593 1594 gsap.to(this.$overlayWidgets, { 1595 autoAlpha: 1, 1596 y: 0, 1597 duration: 1.2, 1598 ease: 'power4.out', 1599 }); 1600 } 1601 }) 1602 .set(submenu, { 1603 autoAlpha: 1, 1604 zIndex: 100 1605 }) 1606 .add(gsap.effects.hideLines($currentLinks, { 1607 stagger: { 1608 amount: 0.2, 1609 from: 'end'
1610 }, 1611 y: '100%', 1612 duration: 1.2, 1613 ease: 'power4.out' 1614 })) 1615 .add(gsap.effects.animateLines($submenuLinks, { 1616 stagger: { 1617 amount: 0.2, 1618 from: 'end' 1619 }, 1620 duration: 1.2, 1621 ease: 'power4.out', 1622 onStart: () => { 1623 this.$wrapperMenu.scrollTop(0); 1624 // reset virtual scroll position 1625 if (typeof this.SB !== 'undefined') { 1626 this.SB.scrollTo(0, 0); 1627 this.SB.track.yAxis.hide(); 1628 } 1629 }, 1630 }), '-=0.9') 1631 .add(() => { 1632 this.$menuLinks.removeClass(this.openClass); 1633 this._setTransition(false); 1634 }, '-=0.6') 1635 .timeScale(1.25); 1636 } 1637 1638 _closeSubmenu({ 1639 submenu, 1640 currentMenu 1641 }) { 1642 const 1643 $currentLinks = currentMenu.find('> li > a .menu-overlay__item-wrapper'), 1644 $submenuLinks = submenu.find('> li > a .menu-overlay__item-wrapper'); 1645 1646 this.timeline 1647 .clear() 1648 .add(() => { 1649 this._setTransition(true); 1650 this.$submenu.removeClass(this.openClass); 1651 currentMenu.not(this.$menuOverlay).addClass(this.openClass); 1652 1653 this.$submenu.not(currentMenu).removeClass(this.unlockClass).addClass(this.lockClass); 1654 currentMenu.removeClass(this.lockClass).addClass(this.unlockClass); 1655 1656 if (typeof this.SB !== 'undefined') { 1657 this.SB.track.yAxis.hide(); 1658 this.SB.track.update(); 1659 } 1660 1661 if (this.$submenu.hasClass(this.openClass)) { 1662 this.$menuOverlay.removeClass(this.unlockClass).addClass(this.lockClass); 1663 1664 gsap.to(this.$submenuButton, { 1665 autoAlpha: 1, 1666 x: 0, 1667 duration: 0.3 1668 }); 1669 1670 gsap.to(this.$overlayWidgets, { 1671 autoAlpha: 0, 1672 y: -30, 1673 duration: 1.2, 1674 ease: 'power4.out', 1675 }); 1676 1677 } else { 1678 this.$menuOverlay.removeClass(this.lockClass).addClass(this.unlockClass); 1679 1680 gsap.to(this.$submenuButton, { 1681 autoAlpha: 0, 1682 x: -10, 1683 duration: 0.3 1684 }); 1685 1686 if (this._isMediumScreen()) { 1687 gsap.to(this.$overlayWidgets, { 1688 autoAlpha: 1, 1689 y: 0, 1690 duration: 1.2, 1691 ease: 'power4.out', 1692 }); 1693 } 1694 } 1695 }) 1696 .set(submenu, { 1697 zIndex: -1 1698 }) 1699 .add(gsap.effects.setLines($currentLinks, { 1700 y: '100%' 1701 }), 'start') 1702 .add(gsap.effects.hideLines($submenuLinks, { 1703 stagger: { 1704 amount: 0.1, 1705 from: 'start' 1706 }, 1707 y: '-100%', 1708 duration: 1.2, 1709 ease: 'power4.out' 1710 })) 1711 .add( 1712 gsap.effects.animateLines($currentLinks, { 1713 stagger: { 1714 amount: 0.2, 1715 from: 'start' 1716 }, 1717 duration: 1.2, 1718 ease: 'power4.out', 1719 onStart: () => { 1720 this.$wrapperMenu.scrollTop(0); 1721 // reset virtual scroll position 1722 if (typeof this.SB !== 'undefined') { 1723 this.SB.scrollTo(0, 0); 1724 this.SB.track.yAxis.hide(); 1725 } 1726 }, 1727 }), '-=0.9') 1728 .set(submenu, { 1729 autoAlpha: 0, 1730 }) 1731 .add(() => { 1732 this._setTransition(false); 1733 }, '-=0.6') 1734 .timeScale(1.25); 1735 } 1736 1737 _handleAnchors() { 1738 1739 const self = this; 1740 1741 // overlay anchor links 1742 this.$allLinksOverlay.filter('a[href*="#"]:not([href="#"]):not([href*="#elementor-action"])').each(function () { 1743 const 1744 $current = $(this), 1745 url = $current.attr('href'); 1746 1747 self._scrollToAnchorFromMenu({ 1748 element: $current, 1749 url, 1750 menu: 'overlay' 1751 }); 1752 }); 1753 1754 // classic menu anchor links 1755 this.$allLinksClassic.filter('a[href*="#"]:not([href="#"]):not([href*="#elementor-action"])').each(function () { 1756 const 1757 $current = $(this), 1758 url = $current.attr('href'); 1759 1760 self._scrollToAnchorFromMenu({ 1761 element: $current, 1762 url, 1763 menu: 'classic' 1764 }); 1765 }); 1766 1767 } 1768 1769 _scrollToAnchorFromMenu({ 1770 element, 1771 url, 1772 menu = 'classic' 1773 }) { 1774 if (!url || !element) { 1775 return; 1776 } 1777 1778 const filteredUrl = url.substring(url.indexOf('#')); 1779 1780 try { 1781 if (filteredUrl.length) { 1782 const $el = window.$pageWrapper.find(filteredUrl); 1783 1784 if ($el.length) { 1785 element.on('click', (e) => { 1786 e.stopPropagation(); 1787 e.preventDefault(); 1788 1789 if (menu === 'classic') { 1790 window.kinsey.components.Scroll.scrollTo({ 1791 y: $el.offset().top - this.$target.innerHeight(), 1792 duration: 0.8 1793 }); 1794 } 1795 1796 if (menu === 'overlay') { 1797 this.closeMenu(false, () => {
1798 window.kinsey.components.Scroll.scrollTo({ 1799 y: $el.offset().top - this.$target.innerHeight(), 1800 duration: 0.8 1801 }); 1802 }); 1803 } 1804 }); 1805 1806 } else { 1807 element.off('click'); 1808 } 1809 } 1810 } catch (error) { 1811 console.error('Error when handling menu anchor links: ' + error); 1812 } 1813 1814 } 1815 1816 _runSmoothScrollOverlayMenu() { 1817 if (!window.Modernizr.touchevents && this.$menuSmoothScrollingContainer.length && typeof window.Scrollbar !== 'undefined') { 1818 this._initSmoothScroll(); 1819 } 1820 } 1821 1822 _initSmoothScroll() { 1823 const options = typeof arts_ss_settings !== 'undefined' ? arts_ss_settings.options : {}; 1824 1825 if (typeof DisableScrollPlugin !== 'undefined') { 1826 window.Scrollbar.use(DisableScrollPlugin); 1827 } 1828 1829 if (typeof options.plugins !== 'undefined' && typeof options.plugins.edgeEasing !== 'undefined' && typeof SoftscrollPlugin !== 'undefined') { 1830 window.Scrollbar.use(SoftscrollPlugin); 1831 } 1832 1833 this.SB = window.Scrollbar.init(this.$menuSmoothScrollingContainer[0], options); 1834 } 1835 1836 _setGradientBackgrounds() { 1837 1838 if (this.$menuGradientTop.length) { 1839 this.$menuGradientTop.each(function () { 1840 const 1841 $this = $(this), 1842 ancestorRGB = getColorValues($this.parent().css('background-color')); 1843 1844 if (ancestorRGB) { 1845 gsap.set($this, { 1846 background: `linear-gradient(0deg, rgba(${ancestorRGB[0]}, ${ancestorRGB[1]}, ${ancestorRGB[2]}, 0) 0%, rgba(${ancestorRGB[0]}, ${ancestorRGB[1]}, ${ancestorRGB[2]}, 1) 100%)` 1847 }); 1848 } 1849 }); 1850 } 1851 1852 if (this.$menuGradientBottom.length) { 1853 this.$menuGradientBottom.each(function () { 1854 const 1855 $this = $(this), 1856 ancestorRGB = getColorValues($this.parent().css('background-color')); 1857 1858 if (ancestorRGB) { 1859 gsap.set($this, { 1860 background: `linear-gradient(180deg, rgba(${ancestorRGB[0]}, ${ancestorRGB[1]}, ${ancestorRGB[2]}, 0) 0%, rgba(${ancestorRGB[0]}, ${ancestorRGB[1]}, ${ancestorRGB[2]}, 1) 100%)` 1861 }); 1862 } 1863 }); 1864 } 1865 } 1866 1867 _updateLabel({ 1868 text = 'text' 1869 }) { 1870 if (this.$headerLabelSubmenu.length) { 1871 this.currentSubmenuLabel = text; 1872 1873 this.labelTimeline 1874 .clear() 1875 .to(this.$headerLabelSubmenu, { 1876 y: '-50%', 1877 autoAlpha: 0, 1878 duration: 0.3, 1879 onComplete: () => { 1880 this.$headerLabelSubmenu.text(text); 1881 } 1882 }) 1883 .fromTo(this.$headerLabelSubmenu, { 1884 y: '50%', 1885 autoAlpha: 0 1886 }, { 1887 y: '0%', 1888 autoAlpha: 1, 1889 duration: 0.3, 1890 immediateRender: false 1891 }); 1892 } 1893 } 1894 1895 _setMenusHover() { 1896 const self = this; 1897 1898 if (this.$allLinksOverlay.length) { 1899 this.$allLinksOverlay 1900 .on('mouseenter touchstart', function () { 1901 self.$menuOverlay.addClass(self.hoverClassOverlay); 1902 }) 1903 .on('mouseleave touchend', function () { 1904 self.$menuOverlay.removeClass(self.hoverClassOverlay); 1905 }); 1906 } 1907 1908 if (this.$allLinksClassic.length) { 1909 this.$allLinksClassic 1910 .on('mouseenter touchstart', function () { 1911 self.$menu.addClass(self.hoverClassClassic); 1912 }) 1913 .on('mouseleave touchend', function () { 1914 self.$menu.removeClass(self.hoverClassClassic); 1915 }) 1916 .on('click', function (e) { 1917 const $currentTarget = $(e.currentTarget); 1918 1919 self.$menu.find(`.${self.currentMenuItemClass}`).removeClass(`${self.currentMenuItemClass}`); 1920 self.$menu.find(`.${self.currentMenuAncestorClass}`).removeClass(`${self.currentMenuAncestorClass}`); 1921 $currentTarget.parent().addClass(`${self.currentMenuItemClass}`); 1922 $currentTarget.parents(`.${self.menuItemHasChildrenClass}`).last().addClass(`${self.currentMenuAncestorClass}`); 1923 }); 1924 } 1925 } 1926} 1927 1928/*!======================================================================== 1929 11. Load Slider Menu 1930 ======================================================================!*/ 1931function loadSliderMenu($scope) { 1932 if (!$scope || window.theme.isSliderMenuLoaded === true) { 1933 return; 1934 } 1935 1936 const 1937 $sliderMenuColumn = $scope.find('.header__slider-column'), 1938 $sliderMenu = $scope.find('.js-slider-menu'); 1939 1940 // Slider exists 1941 if ($sliderMenuColumn.length && $sliderMenu.length) { 1942 1943 // Slider exists but yet displayed 1944 if (!window.Modernizr.mq('(min-width: 992px)')) { 1945 1946 // Watch if it will be displayed later 1947 window.$window.on('resize orientationchange', debounce(load, 500)); 1948 } else { // Slider exists and displayed â load immediately 1949 load(); 1950 } 1951 } 1952 1953 function load() { 1954 // Slider column became visible 1955 if (window.Modernizr.mq('(min-width: 992px)')) { 1956 window.$window.off('resize orientationchange', this); 1957 1958 window.kinsey.components.AssetsManager 1959 .loadSliderMenu() 1960 .then(() => { 1961 $sliderMenu.each(function () { 1962 new window.kinsey.components.SliderMenu({ 1963 target: $(this), 1964 scope: $scope 1965 }); 1966 }); 1967 1968 window.$pageHeader.trigger('sliderInit'); 1969 1970 // Set flag 1971 window.theme.isSliderMenuLoaded = true; 1972 }); 1973 } 1974 } 1975} 1976 1977/*!======================================================================== 1978 12. Preloader 1979 ======================================================================!*/ 1980function Preloader() { 1981 let 1982 tl = new gsap.timeline(), 1983 $counter = $('.js-preloader__counter'), 1984 $content = $('.js-preloader__content'), 1985 backgroundSizeHeight, 1986 counter = { 1987 width: 'auto', 1988 val: 0 1989 }, 1990 value = _addZeros(0, 2) + '%'; 1991 1992 this.start = function () { 1993 window.dispatchEvent(new CustomEvent('arts/preloader/start')); 1994 1995 if (!window.$pagePreloader.length) { 1996 return; 1997 } 1998 1999 tl 2000 .to($content, { 2001 y: 0, 2002 duration: 0.3, 2003 autoAlpha: 1, 2004 ease: 'power3.out', 2005 }, '0'); 2006 2007 if ($counter.length) { 2008 backgroundSizeHeight = $counter.css('background-size').split(' ')[1]; 2009 2010 // get maximum possible width to prevent shaking during the animation 2011 $counter.text('100%'); 2012 2013 // save width 2014 counter.width = $counter.width(); 2015 2016 // restore counter value 2017 $counter.text(value); 2018 2019 // hard set the width 2020 gsap.set($counter, { 2021 width: counter.width 2022 }); 2023 2024 tl 2025 .to($counter, { 2026 duration: 0.3, 2027 autoAlpha: 1, 2028 y: 0, 2029 ease: 'power3.out', 2030 }, '0') 2031 .to(counter, { 2032 onUpdate: () => { 2033 value = parseFloat(counter.val).toFixed(0); 2034 value = _addZeros(value, 2); 2035 $counter.text(value + '%'); 2036 }, 2037 val: 100, 2038 duration: 20, 2039 ease: 'power3.out', 2040 }); 2041 } 2042 2043 } 2044 2045 this.finish = function () { 2046 return new Promise((resolve) => { 2047 const timeScale = parseFloat(window.theme.animations.timeScale.preloader) || 1; 2048 2049 if (!window.$pagePreloader.length) { 2050 window.dispatchEvent(new CustomEvent('arts/preloader/end')); 2051 return; 2052 } 2053 2054 tl 2055 .clear() 2056 .add([ 2057 gsap.to($content, { 2058 y: 0, 2059 autoAlpha: 1, 2060 ease: 'power3.out', 2061 duration: 0.3, 2062 overwrite: true 2063 }), 2064 gsap.to($counter, { 2065 y: 0, 2066 autoAlpha: 1, 2067 ease: 'power3.out', 2068 duration: 0.3, 2069 overwrite: true 2070 }) 2071 ]) 2072 .add([ 2073 gsap.to($counter, { 2074 onStart: () => { 2075 $counter.removeClass('preloader__counter_started'); 2076 }, 2077 backgroundSize: `100% ${backgroundSizeHeight}`, 2078 duration: 2.4 / timeScale, 2079 ease: 'expo.inOut' 2080 }), 2081 gsap.to(counter, { 2082 onUpdate: () => { 2083 value = parseFloat(counter.val).toFixed(0); 2084 value = _addZeros(value, 2); 2085 $counter.text(value + '%'); 2086 }, 2087 val: 100, 2088 duration: 2.4 / timeScale, 2089 ease: 'expo.inOut' 2090 }) 2091 ]) 2092 .set($counter, { 2093 backgroundPosition: '100% 100%', 2094 }) 2095 .to($counter, { 2096 backgroundSize: `0% ${backgroundSizeHeight}`, 2097 duration: 1.2, 2098 ease: 'expo.inOut', 2099 }) 2100 .add([ 2101 gsap.effects.hideMask(window.$pagePreloader, { 2102 duration: 1.2, 2103 scale: 1, 2104 direction: 'down', 2105 }), 2106 gsap.to($counter, { 2107 y: -50, 2108 autoAlpha: 0, 2109 duration: 0.3, 2110 onComplete: () => {
2111 window.kinsey.components.Scroll.scrollToTop(); 2112 window.$pagePreloader.addClass('preloader_ended'); 2113 } 2114 }), 2115 gsap.to($content, { 2116 y: -50, 2117 autoAlpha: 0, 2118 duration: 0.3, 2119 delay: 0.1 2120 }), 2121 ], '-=0.3') 2122 .set(window.$pagePreloader, { 2123 display: 'none' 2124 }) 2125 .add(() => { 2126 window.dispatchEvent(new CustomEvent('arts/preloader/end')); 2127 resolve(true); 2128 }, '-=0.3'); 2129 }); 2130 } 2131 2132 function _addZeros(value, zeros) { 2133 while (value.toString().length < zeros) { 2134 value = '0' + value; 2135 } 2136 2137 return value; 2138 } 2139 2140 if (window.$pagePreloader.length) { 2141 window.$window.on('arts/preloader/preview', () => { 2142 window.$pagePreloader.removeClass('preloader_ended'); 2143 2144 gsap.set(window.$pagePreloader, { 2145 clearProps: 'all' 2146 }); 2147 2148 gsap.effects.animateMask(window.$pagePreloader, { 2149 duration: 0 2150 }); 2151 2152 $counter.addClass('preloader__counter_started'); 2153 2154 gsap.set($counter, { 2155 clearProps: 'all' 2156 }); 2157 2158 gsap.set($content, { 2159 clearProps: 'all' 2160 }); 2161 }); 2162 } 2163} 2164 2165/*!======================================================================== 2166 13. Section Content 2167 ======================================================================!*/ 2168window.kinsey.components.SectionContent = class SectionContent extends window.kinsey.components.BaseComponent { 2169 constructor({ 2170 target, 2171 scope 2172 }) { 2173 super({ 2174 target, 2175 scope 2176 }); 2177 } 2178} 2179 2180/*!======================================================================== 2181 14. Section Masthead 2182 ======================================================================!*/ 2183window.kinsey.components.SectionMasthead = class SectionMasthead extends window.kinsey.components.BaseComponent { 2184 constructor({ 2185 target, 2186 scope, 2187 afterMount, 2188 afterRun 2189 }) { 2190 super({ 2191 target, 2192 scope, 2193 afterRun, 2194 afterMount 2195 }); 2196 } 2197 2198 set() { 2199 this.$inner = this.$target.find('.section-masthead__inner'); 2200 this.$maskReveal = this.$target.find('.mask-reveal'); 2201 this.$heading = this.$target.find('.section-masthead__heading'); 2202 this.$category = this.$target.find('.section-masthead__category'); 2203 this.$subheading = this.$target.find('.section-masthead__subheading'); 2204 this.$background = this.$target.find('.section__bg'); 2205 this.$divider = this.$target.find('.section-masthead__meta-divider'); 2206 this.$button = this.$target.find('.section-masthead__button'); 2207 this.$scrollDown = this.$target.find('.section-masthead__wrapper-scroll-down'); 2208 this.$overlay = this.$target.find('.section-masthead__overlay'); 2209 2210 if (this.$target.hasClass('section-masthead_fixed')) { 2211 this._fixMasthead(); 2212 } 2213 } 2214 2215 animateIn() { 2216 const 2217 $heading = this.$heading.not('.js-transition-animated'), 2218 $maskReveal = this.$maskReveal.not('.js-transition-animated'), 2219 $background = this.$background.not('.js-transition-animated'); 2220 2221 this.timeline 2222 .animateText($heading, { 2223 duration: 1.2, 2224 stagger: { 2225 amount: 0.3, 2226 from: 'left' 2227 } 2228 }) 2229 .add([ 2230 gsap.effects.animateText(this.$category, { 2231 duration: 0.6, 2232 stagger: { 2233 amount: 0.3, 2234 from: 'left' 2235 } 2236 }), 2237 gsap.effects.animateText(this.$subheading, { 2238 duration: 0.6, 2239 stagger: { 2240 amount: 0.3, 2241 from: 'left' 2242 } 2243 }), 2244 gsap.effects.animateHeadline(this.$divider, { 2245 // duration: 0.6, 2246 }) 2247 ], $heading.length ? '-=0.8' : '0.2') 2248 .add([ 2249 gsap.effects.animateMask($maskReveal, { 2250 direction: 'down' 2251 }), 2252 gsap.effects.animateScale($background, { 2253 direction: 'down' 2254 }), 2255 gsap.fromTo(this.$overlay, { 2256 autoAlpha: 0, 2257 immediateRender: true 2258 }, { 2259 autoAlpha: 1, 2260 duration: 0.6 2261 }), 2262 gsap.effects.animateJump(this.$scrollDown) 2263 ], '-=1.2'); 2264 2265 } 2266 2267 animateOut() { 2268 this.timelineOut.add([ 2269 gsap.effects.hideText(this.$target, { 2270 stagger: 0 2271 }), 2272 gsap.effects.hideHeadline(this.$divider), 2273 gsap.effects.hideMask(this.$maskReveal), 2274 gsap.effects.hideScale(this.$background) 2275 ], '0'); 2276 2277 } 2278 2279 _getFixedScrollingDistance() { 2280 if (typeof window.SB !== 'undefined') { 2281 return window.SB.containerEl.scrollHeight; 2282 } else { 2283 return Math.max( 2284 document.body.scrollHeight, document.documentElement.scrollHeight, 2285 document.body.offsetHeight, document.documentElement.offsetHeight, 2286 document.body.clientHeight, document.documentElement.clientHeight 2287 ); 2288 } 2289 } 2290 2291 _fixMasthead() { 2292 if (typeof window.SB === 'undefined') { 2293 2294 ScrollTrigger.create({ 2295 pin: true, 2296 pinType: 'fixed', 2297 pinSpacing: false, 2298 invalidateOnRefresh: true, 2299 anticipatePin: 1, 2300 trigger: this.$target, 2301 scrub: true, 2302 start: () => 'top top', 2303 end: () => this._getFixedScrollingDistance(), 2304 }); 2305 } 2306 2307 ScrollTrigger.create({ 2308 animation: gsap.fromTo(this.$inner, { 2309 autoAlpha: 1, 2310 y: 0 2311 }, { 2312 autoAlpha: 0, 2313 y: '-10%' 2314 }), 2315 start: `top+=${window.innerHeight} bottom`, 2316 end: `top+=${window.innerHeight * 1.33} bottom`, 2317 scrub: true, 2318 trigger: window.$pageContent, 2319 invalidateOnRefresh: true 2320 }); 2321 } 2322} 2323 2324 2325})(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.