Files
IPB/applications/core/interface/theme/navigationMoreMenu.js
T
2025-12-19 16:27:35 -08:00

92 lines
2.8 KiB
JavaScript

customElements.define('i-navigation-menu', class extends HTMLElement {
constructor () {
super();
this.menu = this.querySelector('.ipsNavBar');
this.moreLi = this.menu.querySelector("[data-el='nav-more']");
this.moreMenu = this.moreLi.querySelector(".ipsNav__dropdown");
}
emptyMoreMenu() {
// Move all children back into main
this.moreLi.before(...this.moreMenu.children);
// Then hide the More menu
this.moreLi.hidden = true;
}
fillMoreMenu(clientWidth){
let scrollWidth = this.menu.scrollWidth;
// If there's no overflow, return early
if(scrollWidth <= clientWidth) return;
// Show More menu
this.moreLi.hidden = false;
// While the navigation list overflows, move items into the More menu
while(scrollWidth > clientWidth){
// If the More menu is the first element, end the while loop
if(!this.moreLi.previousElementSibling){ break; }
// Move last link into More menu
this.moreMenu.prepend(this.moreLi.previousElementSibling);
scrollWidth = this.menu.scrollWidth;
}
}
updateAttributes(){
// Reapply the light-dismiss functionality to items which have been moved from the More menu back to the main menu
this.menu.querySelectorAll('[data-ips-hidden-light-dismiss-disabled]').forEach(el => {
el.removeAttribute('data-ips-hidden-light-dismiss-disabled');
el.setAttribute('data-ips-hidden-light-dismiss', '');
});
// Then loop through menus inside More menu and remove their light-dismiss feature, and add a -disabled variant so we can reapply the correct attribute later
this.moreMenu.querySelectorAll('[data-ips-hidden-light-dismiss]').forEach(el => {
el.removeAttribute('data-ips-hidden-light-dismiss');
el.setAttribute('data-ips-hidden-light-dismiss-disabled', '');
});
// If the active link is inside the More menu...
if(this.moreMenu.querySelector("[aria-current]")){
// ..add [data-active] to "More"
this.moreLi.setAttribute("data-active", "");
// ..and expand the active dropdown
this.moreMenu.querySelectorAll(':scope > [data-active]').forEach(el => {
const button = el.querySelector(":scope > [aria-expanded]");
if(button){
button.setAttribute("aria-expanded", "true");
}
const menu = el.querySelector(":scope > .ipsNav__dropdown");
if(menu){
menu.hidden = false;
}
});
} else {
// Otherwise remove [data-active] from the More menu
this.moreLi.removeAttribute("data-active");
}
}
connectedCallback(){
// Empty More menu and refill it on resize
this.ro = new ResizeObserver(entries => {
for (let entry of entries) {
let entryWidth = Math.ceil(entry.contentRect.width);
if(this.lastWidth && entryWidth > this.lastWidth){
this.emptyMoreMenu();
}
this.fillMoreMenu(entryWidth);
this.updateAttributes();
this.lastWidth = entryWidth;
}
});
this.ro.observe(this.menu);
}
});