work.suroh.tk/_includes/components/nav-primary.js

128 lines
3.1 KiB
JavaScript

import { Synth } from '../../assets/js/synth.js'
class NavPrimary extends HTMLElement {
categories = []
subs = []
audioEngine = null
masterGain = null
menuVoices = {}
connectedCallback() {
this.setupAudio()
this.categories = this.querySelectorAll('nav-link')
this.subs = this.querySelectorAll('#sub ul')
this.activate()
window.addEventListener('popstate', () => {
this.activate()
})
this.categories.forEach(n => {
this.setupVoice(n)
n.addEventListener('click', () => {
const category = n.attributes.getNamedItem('category')
const link = n.attributes.getNamedItem('link')
console.log('category click', link, category)
if (link) {
history.pushState({}, '', link.value)
location.pathname = link.value
} else if (category) {
location.hash = category.value
}
})
n.addEventListener('mouseenter', () => {
const menuItem = this.querySelector('#menuItem h1')
menuItem.textContent = n.dataset.name
this.menuVoices[n.dataset.name].noteOn()
menuItem.classList.add('active')
})
n.addEventListener('mouseleave', () => {
const menuItem = this.querySelector('#menuItem h1')
this.menuVoices[n.dataset.name].noteOff()
menuItem.classList.remove('active')
})
})
const audioEl = this.querySelector('.audioToggle')
audioEl.addEventListener('click', () => this.toggleAudio())
}
activate() {
let active, toOpen
this.categories.forEach(c => {
const { value } = c.attributes.getNamedItem('category') || false
if (c.classList.contains('active')) {
c.classList.remove('active')
} else if (value == location.hash.replace('#', '')) {
c.classList.add('active')
}
})
console.log(this.subs)
this.subs.forEach(s => {
const { name } = s.dataset
if (name == location.hash.replace('#', '') || name == location.pathname) {
toOpen = s
} else if (s.classList.contains('active')){
active = s
}
})
if (active) {
active.addEventListener('transitionend', () => {
toOpen.classList.add('active')
}, { once: true })
active.classList.remove('active')
} else if (toOpen) {
toOpen.classList.add('active')
}
}
setupAudio() {
// AUDIO SETUP
this.audioEngine = new (window.AudioContext || window.webkitAudioContext)()
this.audioEngine.suspend()
this.masterGain = this.audioEngine.createGain()
this.masterGain.gain.value = 0.9
this.masterGain.connect(this.audioEngine.destination)
}
toggleAudio() {
const audioEl = this.querySelector('.audioToggle')
if (this.audioEngine.state == 'suspended') {
this.audioEngine.resume()
audioEl.classList.add('active')
} else {
this.audioEngine.suspend()
audioEl.classList.remove('active')
}
}
setupVoice(el) {
// create synthVoices per navItem
this.menuVoices[el.dataset.name] = new Synth(this.audioEngine)
this.menuVoices[el.dataset.name].gain.connect(this.masterGain)
}
}
customElements.define('nav-primary', NavPrimary)