(function () { const nav = document.getElementById('sidebar-nav'); const wrap = document.getElementById('sidebar-nav-wrap'); const track = document.getElementById('sb-track'); const thumb = document.getElementById('sb-thumb'); if (!nav || !track || !thumb || !wrap) return; let isDragging = false; function show() { track.style.opacity = '1'; } function hide() { if (!isDragging) track.style.opacity = '0'; } function update() { const sh = nav.scrollHeight, ch = nav.clientHeight; if (sh <= ch) { track.style.display = 'none'; return; } track.style.display = 'block'; track.style.opacity = '1'; const st = nav.scrollTop, th = Math.max((ch / sh) * ch, 24); const maxTop = ch - th, ratio = sh > ch ? st / (sh - ch) : 0; thumb.style.height = th + 'px'; thumb.style.top = (ratio * maxTop) + 'px'; } const observer = new MutationObserver(function () { update(); setTimeout(function () { update(); if (nav.scrollHeight > nav.clientHeight) { track.style.display = 'block'; track.style.opacity = '1'; } }, 350); }); observer.observe(nav, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); nav.addEventListener('scroll', update); window.addEventListener('resize', update); wrap.addEventListener('mouseenter', function () { show(); update(); }); wrap.addEventListener('mouseleave', hide); thumb.addEventListener('mousedown', function (e) { e.preventDefault(); isDragging = true; track.style.opacity = '1'; document.body.style.cursor = 'pointer'; document.body.style.userSelect = 'none'; function onMove(ev) { if (!isDragging) return; const rect = track.getBoundingClientRect(); nav.scrollTop = ((ev.clientY - rect.top) / rect.height) * (nav.scrollHeight - nav.clientHeight); } function onUp() { isDragging = false; document.body.style.cursor = ''; document.body.style.userSelect = ''; document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); } document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp); }); update(); setTimeout(update, 300); nav.querySelectorAll('.submenu-group:not(.open) > .submenu-body').forEach(function (b) { b.style.maxHeight = '0px'; }); function setBodyHeight(group) { const body = group.querySelector(':scope > .submenu-body'); if (!body) return; if (group.classList.contains('open')) { body.style.maxHeight = body.scrollHeight + 'px'; } else { body.style.maxHeight = '0px'; } } nav.addEventListener('transitionend', function (e) { if (!e.target.classList || !e.target.classList.contains('submenu-body')) return; if (e.propertyName !== 'max-height') return; if (e.target.style.maxHeight !== '0px') { e.target.style.maxHeight = 'none'; } }); nav.addEventListener('click', function (e) { const head = e.target.closest('.submenu-head'); if (!head) return; const group = head.parentElement; if (group && group.classList.contains('submenu-group')) { group.classList.toggle('open'); setBodyHeight(group); update(); } }); function activateCurrent() { const currentPage = window.location.pathname.split('/').pop(); if (!currentPage) return; const activeLink = nav.querySelector('a[href="' + currentPage + '"]'); if (!activeLink) return; activeLink.classList.add('active'); let node = activeLink.parentElement; while (node && node !== nav) { if (node.classList && node.classList.contains('submenu-group')) { node.classList.add('open'); setBodyHeight(node); } node = node.parentElement; } update(); requestAnimationFrame(function () { activeLink.scrollIntoView({ block: 'nearest' }); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', activateCurrent); } else { activateCurrent(); } })();