54 lines
1.9 KiB
JavaScript
54 lines
1.9 KiB
JavaScript
(() => {
|
|
const tablist = document.querySelector('.install-tabs');
|
|
const tabs = Array.from(tablist.querySelectorAll('.install-tab'));
|
|
const panels = tabs.map(tab => document.querySelector(tab.getAttribute('href')));
|
|
|
|
function selectTab(index) {
|
|
tabs.forEach((tab, i) => {
|
|
tab.setAttribute('aria-selected', String(i === index));
|
|
tab.tabIndex = i === index ? 0 : -1;
|
|
panels[i].hidden = i !== index;
|
|
});
|
|
}
|
|
|
|
tablist.setAttribute('role', 'tablist');
|
|
tabs.forEach((tab, index) => {
|
|
tab.setAttribute('role', 'tab');
|
|
tab.setAttribute('aria-controls', panels[index].id);
|
|
panels[index].setAttribute('role', 'tabpanel');
|
|
panels[index].tabIndex = 0;
|
|
tab.addEventListener('click', event => {
|
|
event.preventDefault();
|
|
selectTab(index);
|
|
});
|
|
tab.addEventListener('keydown', event => {
|
|
let next;
|
|
if (event.key === 'ArrowRight') next = (index + 1) % tabs.length;
|
|
else if (event.key === 'ArrowLeft') next = (index - 1 + tabs.length) % tabs.length;
|
|
else if (event.key === 'Home') next = 0;
|
|
else if (event.key === 'End') next = tabs.length - 1;
|
|
else if (event.key === ' ') next = index;
|
|
else return;
|
|
event.preventDefault();
|
|
selectTab(next);
|
|
tabs[next].focus();
|
|
});
|
|
});
|
|
|
|
function selectHash() {
|
|
let target;
|
|
try { target = document.getElementById(decodeURIComponent(location.hash.slice(1))); } catch { return; }
|
|
const index = panels.indexOf(target?.closest('.install-panel'));
|
|
if (index !== -1) {
|
|
selectTab(index);
|
|
// Selecting a panel changes the page height, so the browser's native
|
|
// hash jump can land at the old position. Re-align after the layout settles.
|
|
requestAnimationFrame(() => target.scrollIntoView({ block: 'start' }));
|
|
}
|
|
}
|
|
|
|
selectTab(0);
|
|
selectHash();
|
|
window.addEventListener('hashchange', selectHash);
|
|
})();
|