/* global.js ========= All global logic for the carsington theme For detailed documentation on how things in this theme works -: https://docs.google.com/document/d/1nAW00kGPRfQl4rHOzwR2mlBwuAgOZOkhLoJxjReu3eo/edit */ /* FUNCTIONS ========= fOnWindowResize() - Called when window resizes fNotOnHomePage() - this function is called on load if we aren't on the homepage fOpenMobileMenu() - Shows the navigation on mobile fCloseMobileMenu() - Closes the navigaiton on mobile /* /* GLOBAL VARIABLES ================ */ // Store if the mobile menu is active or not var bMobileMenuActive = false; // Store the state of the mobile menu var bIsMobileMenuInTransition = false; // Store the last scroll position var nLastScrollPosition = 0; // Store the state of the header var bIsHeaderOutOfView = false; /* On Document Loaded ================== Called by Jquery event handler when the document is ready (When content has been loaded) */ $( document ).ready( function() { // Set the windoe on scroll after 1s, this is to stop the navigation bar being hidden on page load (singe scroll is sometimes triggerd on firefox) setTimeout(function () { // On window scroll, invoke callback $(window).scroll( fOnWindowScroll ); }, 1000); // If we are not on the homepage if( $("#homepage-div").length == 0 ) { // Call the not on homepage function fNotOnHomePage(); } // On window reisze whilst not on the home page $(window).on("resize", fOnWindowResize); // Trigger the resize to set the initals $(window).trigger('resize'); /* INITATE NAVIGATION DROPDOWNS ============================ Make it so when we hover the navigation elements / click them the navigation menu displays */ // On mouse over dropdown container $(".dropdown-root-container").mouseover( function() { // If we are on desktop if( $(window).width() >= 992 ) { // Open the menu fOnDropdownHover( $(this) ); } }); // On mouse leave dropdown container $(".dropdown-root-container").mouseleave( function() { // If we are on desktop if( $(window).width() >= 992 ) { // Close the menu fOnDropdownNoLongerHover( $(this) ); } }); // On mouse click $(".dropdown-root-container").click( function() { // If the menu is open if( $(this).children().last().is(":visible") ) { // Then close the menu fOnDropdownNoLongerHover( $(this) ); } // If the menu is closed else { // Then open the menu fOnDropdownHover( $(this) ); } }); /* QOL fix for search icon ----------------------- When customers press search icon, we want to make the input field active so customer know they need to search something */ // If the search is enabled if( $("#search-dropdown-toggle").length !== 0 ) { // When the search icon toggle is clicked, make the input focused $("#search-dropdown-toggle").click( function() { // We need to use settimeout to get this to work for some reason setTimeout(() => { $("#search-input-field").get(0).focus(); }, 1); }); } }); /* On content loaded ================= Called when all content is loaded */ $(window).load( function() { // Trigger the resize to set the initals $(window).trigger('resize'); // Retrigger resize after 500ms just to make sure everything is working as it should be setTimeout(function () { // Trigger the resize to set the initals $(window).trigger('resize'); }, 500); }); /* fOnWindowResize() ================= Called when the window resizes */ function fOnWindowResize() { // If we have the newsletter input box if( $(".newsletter-input-boxes").length ) { // Store the target height of the sign up button var nTargetHeight = $(".sign-up-button").outerHeight(true); // Set the height of the newsletter input box $(".newsletter-input-boxes").css( { height : nTargetHeight + "px" } ); } // Store the length of the navbar var nNavigationLength = $(".header-right").innerWidth(); // Store teh navigation elements length var nNavigationElementsLength = 0; // If we have a nav bar if( $(".nav-bar").length != 0 ) { // Store the navigation elements length nNavigationElementsLength += $(".nav-bar").outerWidth(true); } // If we have a nav icons if( $(".nav-bar-icons").length != 0 ) { // Store the navigation elements length nNavigationElementsLength += $(".nav-bar-icons").outerWidth(true); } // If the elements are too squished if( nNavigationElementsLength >= (nNavigationLength - 4) ) { // Set the margin top $(".nav-bar-icons").css( { marginTop : "25px" } ); } // If elements are not squished else { // Ensure the margin isn't set $(".nav-bar-icons").css( { marginTop : "0px" } ); } // If we are on mobile but the mobile menu is active if( $(window).width() > 600 && bMobileMenuActive ) { // Remove the locking of background scrolling let scrollY = document.body.style.top; document.body.style.position = ''; document.body.style.top = ''; window.scrollTo(0, parseInt(scrollY || '0') * -1); } } /* fNotOnHomePage() ================ This function is called on document load, if we are not on the homepage, it fixes global styling that otherwise we want to ignore if we are on the homepage. */ function fNotOnHomePage() { // Each time an image loads, we want to call the resize function to ensure everything is correctly sized / positioned $("img").on('load', function() { // Manuall invoke the window resize fOnWindowResize(); }); // On window reisze whilst not on the home page $(window).on("resize", function() { // On window resize fOnWindowResize(); // Set the height of the relative container $(".header-relative").css( { display : "block", height : $(".header").outerHeight(true) + "px" } ); }); // Trigger the resize to set the initals $(window).trigger('resize'); } /* fOpenMobileMenu() ================= Opens the mobile menu, works using a combo of inline css + classes, speed of animations can be altered in global.css file (transition speed) for - mobile-menu-black-overlay - nav-bar-wrapper This applied to the mobile menu only (doesn't effect desktop unless you specify it to) */ function fOpenMobileMenu() { // If the mobile menu isn't active if( !bMobileMenuActive && !bIsMobileMenuInTransition ) { // Store that the mobile menu is in transition bIsMobileMenuInTransition = true; // Make the black overlay active class $(".mobile-menu-black-overlay").addClass("mobile-menu-black-overlay-active"); // Add the nav bar wrapper active class $(".nav-bar-wrapper").addClass("nav-bar-wrapper-active"); // Add the locking of background scrolling (And do some scroll trickery to move the scroll position abck to where it was) document.body.style.top = `-${window.scrollY}px`; document.body.style.position = 'fixed'; // After 25ms (This is required to initalise the fade, otherwise the dispaly : block will just make it active ) setTimeout(function () { // Set the opacity of the overlay $(".mobile-menu-black-overlay").css( { opacity : 1 } ); // Set the left of the menu $(".nav-bar-wrapper").css( { left : "0px" } ); }, 25); // After a 1s setTimeout(function () { // Update that mobile menu status bMobileMenuActive = true; // Store that the mobile menu is not in transition bIsMobileMenuInTransition = false; }, 1000); } } /* fCloseMobileMenu() ================== Closes the mobile menu, works using a combo of inline css + classes, speed of animations can be altered in global.css file (transition speed) for - mobile-menu-black-overlay - nav-bar-wrapper This applied to the mobile menu only (doesn't effect desktop unless you specify it to) */ function fCloseMobileMenu() { // If the mobile menu is active if( bMobileMenuActive && !bIsMobileMenuInTransition ) { // Store that the mobile menu is in transition bIsMobileMenuInTransition = true; // Set the opacity of the overlay $(".mobile-menu-black-overlay").css( { opacity : 0 } ); // Set the left of the menu $(".nav-bar-wrapper").css( { left : "" } ); // Remove the locking of background scrolling let scrollY = document.body.style.top; document.body.style.position = ''; document.body.style.top = ''; window.scrollTo(0, parseInt(scrollY || '0') * -1); // After a 1s setTimeout(function () { // Remove the active class from the menu $(".mobile-menu-black-overlay").removeClass("mobile-menu-black-overlay-active"); // Remove the active class from teh nav bar wrapper $(".nav-bar-wrapper").removeClass("nav-bar-wrapper-active"); // Update that mobile menu status bMobileMenuActive = false; // Store that the mobile menu is in transition bIsMobileMenuInTransition = false; }, 1000); } } /* fOnWindowScroll() ================= Called when the user scrolls */ function fOnWindowScroll() { // Store a local reference to the scroll position var nScrollPosition = $(window).scrollTop(); // Store if we can alter the header position var bCanAlterHeader = true; // If we are on mobile if( $(window).width() <= 991 ) { // If the mobile menu is open or we are in the transition phase between opening and closing the menu if( bMobileMenuActive || bIsMobileMenuInTransition ) { // make it so we can't adjust the header, as we need to finish the mobile menu transtiions first bCanAlterHeader = false; } } // If we are scrolling up, the header is out of view and we can adjust the header if( nLastScrollPosition > nScrollPosition && bIsHeaderOutOfView && bCanAlterHeader || (nScrollPosition < 100 && bIsHeaderOutOfView && bCanAlterHeader ) ) { // Remove the hide nav bar class $(".header").removeClass("hide-nav-bar"); // Add the show nav-bar class $(".header").addClass("show-nav-bar"); // Store that we have enabled the navbar bIsHeaderOutOfView = false; } // Or if we are scroll down, the header is not out of view and we can adjust the header else if( nLastScrollPosition < nScrollPosition && !bIsHeaderOutOfView && bCanAlterHeader && nScrollPosition > 100 ) { // Remove the show nav bar class $(".header").removeClass("show-nav-bar"); // Add the hide nav-bar class $(".header").addClass("hide-nav-bar"); // Store that we have hidden the navbar bIsHeaderOutOfView = true; } // Store the last known scroll position nLastScrollPosition = nScrollPosition; } /* fOnDropdownHover() ================== Opens the releavnt dropdown menu for the navigation */ function fOnDropdownHover( oElement) { // Store the dropdown menu var oDropdownMenu = oElement.children().last(); // If the dropdown menu isn't active if( !oDropdownMenu.hasClass("menu-is-active") ) { // Add the menu is active class oDropdownMenu.addClass("menu-is-active"); // Store the first child (first col-) var oMenuFirstChild = oDropdownMenu.children().first().children().first(); // If the dropdown menu's outer width is too small (The navigation looks squished) if( oDropdownMenu.outerWidth() <= 350 ) { // If the first child has the class of col-md-6, then it's a half menu if( oMenuFirstChild.hasClass("col-md-6") ) { // Store the last child (Second col-6) var oMenuLastChild = oDropdownMenu.children().first().children().last(); // Remove the col-md-6 class oMenuFirstChild.removeClass("col-md-6"); // Add the col-md-12 class oMenuFirstChild.addClass("col-md-12"); // Add a class to track if the menu used to have col-md-6 oMenuFirstChild.addClass("had-col-md-6"); // Remove the col-md-6 class oMenuLastChild.removeClass("col-md-6"); // Add the col-md-12 class oMenuLastChild.addClass("col-md-12"); // Add a class to track if the menu used to have col-md-6 oMenuLastChild.addClass("had-col-md-6"); } } // If the dropdown menu is sized ok else { // If the menu item is a col-12 but should be a col-6 (after the swap), since it is now sized fine for 2 menus, we can put back if( oMenuFirstChild.hasClass("had-col-md-6") ) { // Store the last child (Second col-6) var oMenuLastChild = oDropdownMenu.children().first().children().last(); // Remove the col-md-12 class oMenuFirstChild.removeClass("col-md-12"); // Add the col-md-6 class oMenuFirstChild.addClass("col-md-6"); // Remove a class to track if the menu used to have col-md-6 oMenuFirstChild.removeClass("had-col-md-6"); // Remove the col-md-12 class oMenuLastChild.removeClass("col-md-12"); // Add the col-md-6 class oMenuLastChild.addClass("col-md-6"); // Remove a class to track if the menu used to have col-md-6 oMenuLastChild.removeClass("had-col-md-6"); } } // Stop any animations playing (cancels close animation if required) oDropdownMenu.stop(); // Remove the menu is active closing class incase we have canceld the closing oDropdownMenu.removeClass("menu-is-closing"); // Set the opaciy to 0 oDropdownMenu.css( { opacity : 0 } ); // Show the dropdown menu oDropdownMenu.show(); // Set the opaciy to 1 oDropdownMenu.animate( { opacity : 1 } , 500 ); } } /* fOnDropdownNoLongerHover() ========================== closes the releavnt dropdown menu for the navigation */ function fOnDropdownNoLongerHover( oElement ) { // Store the dropdown menu var oDropdownMenu = oElement.children().last(); // If the dropdown menu is active if( oDropdownMenu.hasClass("menu-is-active") ) { // Remove the dropdown menu class oDropdownMenu.removeClass("menu-is-active"); // Add the removing class oDropdownMenu.addClass("menu-is-closing"); // Set the opaciy to 0 oDropdownMenu.stop().animate( { opacity : 0 } , 300, function() { // If we are still wanting to close the menu if( oDropdownMenu.hasClass("menu-is-closing") ) { // Hide the dropdown menu oDropdownMenu.hide(); // Remove the dropdown closing class oDropdownMenu.removeClass("menu-is-closing"); } }); } }