(function initNavbarWhenReady() { if (!window.jQuery || !window.gsap) { setTimeout(initNavbarWhenReady, 50); return; } let menuLink = $(".menu_dp-link"); let tabLink = $(".menu_dropdown-tab-item"); let content = $(".menu_dropdown_content"); let tabContent = $(".menu_tab-content-wrap"); let menuBG = $(".menu_bg"); let dropdownWrap = $(".menu_content"); let closeDropdownTimeout; gsap.defaults({ duration: 0.2, }); function getMenuIndex(link) { return menuLink.index(link); } function getMenuContent(link) { let scopedContent = link .closest(".menu_dp-wrap") .find(".menu_dropdown_content") .first(); if (scopedContent.length) { return scopedContent; } return content.eq(getMenuIndex(link)); } function getMenuWrap(link) { let scopedWrap = link.closest(".menu_dp-wrap").find(".menu_content").first(); if (scopedWrap.length) { return scopedWrap; } return dropdownWrap.eq(getMenuIndex(link)); } function getMenuBG(link) { let scopedBG = getMenuWrap(link).find(".menu_bg").first(); if (scopedBG.length) { return scopedBG; } return menuBG.eq(getMenuIndex(link)); } function getActiveMenuContent() { let activeLink = menuLink.filter(".active").first(); if (!activeLink.length) return $(); return getMenuContent(activeLink); } function getActiveMenuWrap() { let activeLink = menuLink.filter(".active").first(); if (!activeLink.length) return $(); return getMenuWrap(activeLink); } function getActiveMenuBG() { let activeLink = menuLink.filter(".active").first(); if (!activeLink.length) return $(); return getMenuBG(activeLink); } function getContentSize(currentContent) { let measuredContent = currentContent .find(".menu_dropdown-padding, .menu_dropdown-wrap, .menu_flex") .filter(function () { return $(this).outerWidth() > 0 && $(this).outerHeight() > 0; }) .first(); if (!measuredContent.length) { measuredContent = currentContent; } return { width: measuredContent.outerWidth(), height: measuredContent.outerHeight(), }; } function clearDropdownClose() { clearTimeout(closeDropdownTimeout); } function isPointInElement(element, event, buffer) { if (!element || !event || event.clientX == null || event.clientY == null) return false; let rect = element.getBoundingClientRect(); return ( event.clientX >= rect.left - buffer && event.clientX <= rect.right + buffer && event.clientY >= rect.top - buffer && event.clientY <= rect.bottom + buffer ); } function isInsideDesktopDropdown(event) { let target = event && event.target ? event.target : event; let activeLink = menuLink.filter(".active").first(); let activeBG = getActiveMenuBG(); let activeContent = getActiveMenuContent(); if ($(target).closest(".menu_dp-link").length) return true; if (event && event.clientX != null) { return ( isPointInElement(activeLink[0], event, 12) || isPointInElement(activeBG[0], event, 8) || isPointInElement(activeContent[0], event, 8) ); } return $(target).closest(".menu_dropdown_content, .menu_bg, .menu_content").length > 0; } function closeDesktopDropdown() { clearDropdownClose(); gsap.killTweensOf(content); gsap.killTweensOf(dropdownWrap); gsap.killTweensOf(menuBG); let activeWrap = getActiveMenuWrap(); gsap.set(content, { display: "none" }); content.removeClass("active"); gsap.to(".menu_dropdown-caret", { rotation: 0, duration: 0 }); menuLink.removeClass("active"); if (activeWrap.length) { gsap.to(activeWrap, { opacity: 0, rotateX: -10, duration: 0.2, onComplete: function () { dropdownWrap.css("display", "none"); gsap.set(dropdownWrap, { opacity: 1, rotateX: 0 }); $("body").css("overflow-x", ""); }, }); } else { dropdownWrap.css("display", "none"); $("body").css("overflow-x", ""); } } function scheduleDropdownClose(event) { clearDropdownClose(); closeDropdownTimeout = setTimeout(function () { if (isInsideDesktopDropdown(event)) { return; } closeDesktopDropdown(); }, 50); } $(document).ready(function () { $(window).scroll(function () { if ($(this).scrollTop() > 0) { $(".nav_component-2").addClass("bottom-border"); } else { $(".nav_component-2").removeClass("bottom-border"); } }); handleMobileNavDisplay(); // Handle scroll event $(window).on("scroll", handleMobileNavDisplay); // Handle resize event $(window).on("resize", handleMobileNavDisplay); }); function handleMobileNavDisplay() { if (window.innerWidth <= 1024) { if ($(window).scrollTop() > 0) { $(".button-12.mobile-nav").css("display", "block"); setTimeout(() => { // Small timeout to ensure the block is rendered before animating $(".button-12.mobile-nav").css("opacity", "1"); }, 10); } else { $(".button-12.mobile-nav").css("opacity", "0"); setTimeout(() => { $(".button-12.mobile-nav").css("display", "none"); }, 300); // This timeout should match the duration of your CSS transition } } else { // Optionally hide the button on larger screens $(".button-12.mobile-nav").css("display", "none"); } } function revealDropdown(currentLink, currentContent) { let currentWrap = getMenuWrap(currentLink); let currentBG = getMenuBG(currentLink); dropdownWrap.not(currentWrap).css("display", "none"); currentWrap.css("display", "flex"); // Prevent horizontal scrollbar during dropdown animation $("body").css("overflow-x", "hidden"); let linkText = currentLink.find(".menu_link-text"); let linkTextOffset; // center of the link // Get content dimensions const contentSize = getContentSize(currentContent); const contentWidth = contentSize.width; const contentHeight = contentSize.height; const viewportWidth = window.innerWidth; const linkLeft = linkText.offset().left; const linkWidth = linkText.outerWidth(); // Center the dropdown under the link for all screen sizes linkTextOffset = linkLeft + linkWidth / 2 - contentWidth / 2; // Ensure dropdown doesn't go beyond viewport boundaries const minOffset = 10; // Minimum distance from left edge const maxOffset = viewportWidth - contentWidth - 10; // Minimum distance from right edge // Only constrain if the dropdown would go outside viewport if (linkTextOffset < minOffset) { linkTextOffset = minOffset; } else if (linkTextOffset > maxOffset) { linkTextOffset = maxOffset; } // Set the initial width of menuBG with constrained dimensions gsap.set(currentBG, { width: Math.min(contentWidth, viewportWidth - 20), // Ensure it doesn't exceed viewport height: contentHeight, x: linkTextOffset, }); // Update the x transform of menuBG gsap.to(currentBG, { x: linkTextOffset, }); gsap.set(currentContent, { opacity: 0, display: "none", }); gsap.set(currentContent, { opacity: 1, x: "0em", display: "flex", }); gsap.fromTo( currentWrap, { opacity: 0, rotateX: -10 }, { opacity: 1, rotateX: 0, duration: 0.2 } ); } function switchDropdown(currentLink, previousContent, currentContent) { let previousWrap = previousContent.closest(".menu_content"); let currentWrap = getMenuWrap(currentLink); let currentBG = getMenuBG(currentLink); if (!previousWrap.length || !previousWrap.is(currentWrap)) { gsap.set(previousContent, { display: "none" }); previousContent.removeClass("active"); previousWrap.css("display", "none"); revealDropdown(currentLink, currentContent); return; } let linkText = currentLink.find(".menu_link-text"); let linkTextOffset; // Get content dimensions and viewport info const contentSize = getContentSize(currentContent); const contentWidth = contentSize.width; const contentHeight = contentSize.height; const viewportWidth = window.innerWidth; const linkLeft = linkText.offset().left; const linkWidth = linkText.outerWidth(); // Center the dropdown under the link for all screen sizes linkTextOffset = linkLeft + linkWidth / 2 - contentWidth / 2; // Ensure dropdown doesn't go beyond viewport boundaries const minOffset = 10; const maxOffset = viewportWidth - contentWidth - 10; // Only constrain if the dropdown would go outside viewport if (linkTextOffset < minOffset) { linkTextOffset = minOffset; } else if (linkTextOffset > maxOffset) { linkTextOffset = maxOffset; } // invert moveDistance if needed let moveDistance = 10; if (currentContent.index() < previousContent.index()) { moveDistance = moveDistance * -1; } gsap.to(currentBG, { x: linkTextOffset, width: Math.min(contentWidth, viewportWidth - 20), // Ensure it doesn't exceed viewport height: contentHeight, duration: 0.2, }); gsap.fromTo( previousContent, { opacity: 1, x: "0em", display: "flex" }, { opacity: 0, x: moveDistance * -1 + "em", duration: 0.2, display: "none", onComplete: function () { previousContent.removeClass("active"); gsap.set(previousContent, { display: "none" }); }, } ); gsap.fromTo( currentContent, { opacity: 0, x: moveDistance + "em", display: "none" }, { opacity: 1, x: "0em", duration: 0.2, display: "flex", onComplete: function () { // Update the width of menuBG after the animation has completed let finalContentSize = getContentSize(currentContent); gsap.to(currentBG, { width: finalContentSize.width, duration: 0.2, }); }, } ); } menuLink.on("mouseenter", function () { clearDropdownClose(); let previousLink = menuLink.filter(".active").removeClass("active"); let currentLink = $(this).addClass("active"); let previousContent = content.filter(".active").removeClass("active"); let currentContent = getMenuContent(currentLink).addClass("active"); let relatedCaret = $(this).find(".menu_dropdown-caret"); gsap.killTweensOf(content); gsap.killTweensOf(dropdownWrap); gsap.killTweensOf(menuBG); gsap.to(".menu_dropdown-caret", { rotation: 0, duration: 0 }); gsap.to(relatedCaret, { rotation: 180, duration: 0 }); // Set the display property of all dropdown content to "none" gsap.set(content.not(currentContent), { display: "none" }); // Set the display property of the currentContent to "flex" gsap.set(currentContent, { display: "flex" }); if (previousLink.length === 0 || previousLink[0] === currentLink[0]) { revealDropdown(currentLink, currentContent); } else if (getMenuIndex(previousLink) !== getMenuIndex(currentLink)) { switchDropdown(currentLink, previousContent, currentContent); } }); menuLink.on("click", function (event) { event.preventDefault(); event.stopPropagation(); $(this).trigger("mouseenter"); }); menuLink.on("mouseleave", function (event) { scheduleDropdownClose(event); }); // Menu Hover Out dropdownWrap.on("mouseenter", function () { clearDropdownClose(); }); dropdownWrap.on("mouseleave", function (event) { scheduleDropdownClose(event); }); $(document).on("click", function (event) { if (!isInsideDesktopDropdown(event)) { closeDesktopDropdown(); } }); $(document).on("mousemove", function (event) { let activeWrap = getActiveMenuWrap(); if ( !menuLink.filter(".active").length || !activeWrap.length || activeWrap.css("display") === "none" ) { return; } if (isInsideDesktopDropdown(event)) { clearDropdownClose(); } else { scheduleDropdownClose(event); } }); function revealTab(currentLink, currentContent) { dropdownWrap.css("display", "flex"); gsap.set(tabContent, { opacity: 0, }); gsap.set(currentContent, { opacity: 1, y: "0em", }); } function switchTab(currentLink, previousContent, currentContent) { // invert moveDistance if needed let moveDistance = 2; if (currentContent.index() < previousContent.index()) { moveDistance = moveDistance * -1; } gsap.fromTo( previousContent, { opacity: 1, y: "0em" }, { opacity: 0, y: moveDistance * -1 + "em", duration: 0.2, } ); gsap.fromTo( currentContent, { opacity: 0, y: moveDistance + "em" }, { opacity: 1, y: "0em", duration: 0.2, } ); } // Open tab animation let showTab = gsap.timeline({ paused: true, onReverseComplete: () => { dropdownWrap.css("display", "none"); tabLink.removeClass("active"); }, }); showTab.from(dropdownWrap, { opacity: 0, rotateX: -10, duration: 0.2 }); // Tab Hover Out $(".menu_dropdown-tab-wrap").on("mouseleave", function () { showTab.reverse(); }); // Tab Link Hover In tabLink.on("mouseenter", function () { // get elements let previousLink = tabLink.filter(".active").removeClass("active"); let currentLink = $(this).addClass("active"); let previousContent = tabContent.filter(".active").removeClass("active"); let currentContent = tabContent.eq($(this).index()).addClass("active"); // play animations if (previousLink.length === 0) { revealTab(currentLink, currentContent); } else if (previousLink.index() !== currentLink.index()) { switchTab(currentLink, previousContent, currentContent); } }); // Mobile Menu // Open mobile menu $(".w-nav-button").on("click", function () { setTimeout(function () { if ($(".w-nav-overlay").is(":visible")) { // Add the 'modal-open' class to the body element $("body").addClass("menu-open"); // Add the 'container-scroll' class to the specific container $(".nav_mobile-menu").addClass("container-scroll"); } else { // Reverse the actions $("body").removeClass("menu-open"); $(".nav_mobile-menu").removeClass("container-scroll"); } }, 500); }); function animateMenu(clickClass, animateClass) { $(clickClass).on("click", function (event) { event.preventDefault(); event.stopPropagation(); // Toggle the 'active' class $(animateClass).toggleClass("active"); $(".logo").hide(); $(".nav_back-link").css("display", "flex"); // Use GSAP to animate the menus gsap.to(".nav_mobile-main", { x: "-100%", duration: 0.4, ease: "power2.out", }); gsap.fromTo( animateClass, { x: "100%" }, { x: "0%", duration: 0.4, ease: "power2.out" } ); }); // Back link click $(".nav_back-link, .toggle-menu-2").on("click", function (event) { $("[class^='nav_mobile-']").removeClass("active"); // Prevent the default action from closing menu event.preventDefault(); event.stopPropagation(); // Toggle the 'active' class //$(animateClass).toggleClass("active"); $(".logo").show(); $(".nav_back-link").hide(); // Use GSAP to animate the menus gsap.to(".nav_mobile-main", { x: "0%", duration: 0.4, ease: "power2.out", }); gsap.to(animateClass, { x: "100%", duration: 0.4, ease: "power2.out", }); }); } animateMenu(".nav_link-2.resources", ".nav_mobile-resources"); })();