forked from izu/student-web-if-development-kit
refactor(tapops): modularize page code
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
export class NavigationController {
|
||||
constructor({
|
||||
menuSelector = '[data-menu]',
|
||||
overlayId = 'mega-overlay',
|
||||
} = {}) {
|
||||
this.menuItems = Array.from(document.querySelectorAll(menuSelector));
|
||||
this.overlay = document.getElementById(overlayId);
|
||||
this.activeMenu = null;
|
||||
this.menuMap = {
|
||||
tentang: 'mega-tentang',
|
||||
program: 'mega-program',
|
||||
sdm: 'mega-sdm',
|
||||
fasilitas: 'mega-fasilitas',
|
||||
karya: 'mega-karya',
|
||||
kontak: 'mega-kontak',
|
||||
};
|
||||
}
|
||||
|
||||
init() {
|
||||
if (this.menuItems.length === 0 || !this.overlay) return;
|
||||
|
||||
this.menuItems.forEach(item => {
|
||||
const menuId = item.getAttribute('data-menu');
|
||||
const button = item.querySelector('.nav-menu-btn');
|
||||
if (!button) return;
|
||||
|
||||
button.setAttribute('aria-haspopup', 'true');
|
||||
button.setAttribute('aria-expanded', 'false');
|
||||
button.addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this.activeMenu === menuId) {
|
||||
this.closeMenus();
|
||||
} else {
|
||||
this.openMenu(menuId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.overlay.addEventListener('click', () => this.closeMenus());
|
||||
document.addEventListener('click', event => this._handleOutsideClick(event));
|
||||
document.addEventListener('keydown', event => {
|
||||
if (event.key === 'Escape' && this.activeMenu) this.closeMenus();
|
||||
});
|
||||
}
|
||||
|
||||
openMenu(menuId) {
|
||||
const targetPanel = document.getElementById(this.menuMap[menuId]);
|
||||
if (!targetPanel) return;
|
||||
|
||||
Object.values(this.menuMap).forEach(panelId => {
|
||||
document.getElementById(panelId)?.classList.remove('active');
|
||||
});
|
||||
|
||||
targetPanel.classList.add('active');
|
||||
this.overlay.classList.add('active');
|
||||
this._setButtonState(menuId);
|
||||
this.activeMenu = menuId;
|
||||
}
|
||||
|
||||
closeMenus() {
|
||||
Object.values(this.menuMap).forEach(panelId => {
|
||||
document.getElementById(panelId)?.classList.remove('active');
|
||||
});
|
||||
|
||||
this.overlay.classList.remove('active');
|
||||
this._setButtonState(null);
|
||||
this.activeMenu = null;
|
||||
}
|
||||
|
||||
_setButtonState(menuId) {
|
||||
this.menuItems.forEach(item => {
|
||||
const isActive = item.getAttribute('data-menu') === menuId;
|
||||
const button = item.querySelector('.nav-menu-btn');
|
||||
const chevron = item.querySelector('.fa-chevron-down');
|
||||
|
||||
button?.classList.toggle('active', isActive);
|
||||
button?.setAttribute('aria-expanded', isActive ? 'true' : 'false');
|
||||
if (chevron) chevron.style.transform = isActive ? 'rotate(180deg)' : '';
|
||||
});
|
||||
}
|
||||
|
||||
_handleOutsideClick(event) {
|
||||
const clickedInsideNav = event.target.closest('#main-nav');
|
||||
const clickedInsidePanel = event.target.closest('.mega-panel');
|
||||
if (!clickedInsideNav && !clickedInsidePanel && this.activeMenu) this.closeMenus();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user