Skip to content

Instantly share code, notes, and snippets.

@thesandybridge
Last active December 9, 2022 21:49
Show Gist options
  • Save thesandybridge/63b44196c9f359b2c25713861ee66df4 to your computer and use it in GitHub Desktop.
Save thesandybridge/63b44196c9f359b2c25713861ee66df4 to your computer and use it in GitHub Desktop.
/*****************************************
* Hamburger Menu with Drawer
*****************************************
/
/**
* Initiates the header hamburger menu.
*/
const hamburgerMenu = () => {
const menu = document.querySelector('#hamburger-menu')
const nav = document.querySelector('.primary-nav-container')
document.addEventListener('click', (e) => {
if (e.target.id !== 'hamburger-menu' && e.target.id !== 'menu-hidden-primary-menu') {
togglePrimaryNav(false)
}
})
if (menu) {
menu.addEventListener('click', togglePrimaryNav)
}
}
/**
* Toggles primary nav display. If param = true the menu opens, else it closes.
* @param {boolean} bool
*/
const togglePrimaryNav = (bool = true) => {
const nav = document.querySelector('.primary-nav-container')
if (bool) {
nav.classList.toggle('menu-active')
hamburgerMenuOpenClose()
} else if (!bool && nav.classList.contains('menu-active')) {
hamburgerMenuOpenClose()
nav.classList.remove('menu-active')
}
}
/**
* Toggle the hamburger menu icon animation.
* @param {*} status
*/
const hamburgerMenuOpenClose = () => {
const btn = document.querySelector('#hamburger-menu')
requestAnimationFrame(() => {
btn.setAttribute("aria-pressed", "false" === btn.getAttribute("aria-pressed"))
let svg = btn.querySelector("#hamburger")
console.log(svg)
if (svg) {
let svgTitles = svg.getElementsByTagName("title")
if (svgTitles) {
let svgTitle = svgTitles[0]
if (btn.getAttribute("aria-pressed") === 'false') {
svgTitle.textContent = 'Close'
} else {
svgTitle.textContent = 'Open'
}
}
}
})
}
/*****************************************
* Sticky Nav
*****************************************
/
/**
* Sticky Navigation
* ---
* Toggles sticky navigation
*/
const stickyNavigation = () => {
const header = document.querySelector('.site-header')
const offset = header.offsetTop
const HEADER_HEIGHT = parseInt(getComputedStyle(header).getPropertyValue("height"))
if (window.pageYOffset > offset) {
header.classList.add('sticky-header')
fixAnchorPadding(`${HEADER_HEIGHT + 10}px`)
} else {
header.classList.remove('sticky-header')
fixAnchorPadding('0')
}
}
/**
* Sets the body padding to a set value. This is used for pushing body content down if an absolutely positioned element is covering it.
* @param {*} value
*/
const fixAnchorPadding = (value) => {
const body = document.querySelector('body')
body.style.paddingTop = value
}
/*****************************************
* Helpers
*****************************************
/
/**
* Throttle
* ---
* Prevents multiple actions from overriding functionality.
* @param {*} callback
* @param {*} delay
* @returns
*/
const throttle = (callback, delay = 1000) => {
let shouldWait = false
let waitingArgs
const timeoutFunc = () => {
if (waitingArgs == null) {
shouldWait = false
} else {
callback(...waitingArgs)
waitingArgs = null
setTimeout(timeoutFunc, delay)
}
}
return (...args) => {
if (shouldWait) {
waitingArgs = args
return
}
callback(...args)
shouldWait = true
setTimeout(timeoutFunc, delay)
}
}
/*****************************************
* Custom Slider/Carousel
*****************************************
/
/**
* Toggles the next expert.
*/
const expertSlider = () => {
setInterval(sliderNext, 5000)
const button = document.querySelector('#sliderNextBtn')
if (!button)
return
button.addEventListener('click', sliderNext)
}
/**
* Appends the first child to the end of the list of children.
* This is delayed based on the transition speed of the added class.
*/
const sliderNext = throttle(() => {
const slider = document.querySelector('#expert-slider-container .gb-grid-wrapper')
if (!slider) return
if (slider.childElementCount <= 1) return
const firstChild = slider.firstElementChild
// Trigger the animation
slider.classList.add('slider-transition')
const sliderTransition = document.querySelector('.slider-transition')
let speed = parseInt(getComputedStyle(sliderTransition).getPropertyValue("--transition-speed"))
// Appends first child to end of list.
setTimeout(() => {
slider.appendChild(firstChild)
slider.classList.remove('slider-transition')
}, speed)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment