/* Progressive enhancement: without JS, the tab links jump to visible sections. Add a link and matching panel to extend the tabs (for example, a future SAE tab). */ (function () { const list = document.querySelector('.landing-tabs'); if (!list) return; const tabs = Array.from(list.querySelectorAll('a[href^="#"]')); const panels = tabs.map(tab => document.getElementById(tab.hash.slice(1))); if (panels.some(panel => !panel)) return; list.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; }); const activate = (index, focus = false) => { tabs.forEach((tab, i) => { const selected = i === index; tab.setAttribute('aria-selected', String(selected)); tab.tabIndex = selected ? 0 : -1; panels[i].hidden = !selected; }); if (focus) tabs[index].focus(); }; const fromHash = () => { const target = document.getElementById(location.hash.slice(1)); // Keep the original overview's quick-start and download links useful. const aliases = { start: 'use', availability: 'models', cite: 'models', more: 'models', zeroshot: 'overview', scaling: 'overview', finetune: 'overview' }; const alias = aliases[location.hash.slice(1)]; const index = panels.findIndex(panel => panel.id === alias || panel === target || (target && panel.contains(target))); activate(index < 0 ? 0 : index); }; tabs.forEach((tab, index) => { tab.addEventListener('click', event => { if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) return; event.preventDefault(); activate(index); // Preserve Hugging Face's query parameters when updating the fragment. if (location.hash !== tab.hash) history.pushState(null, '', tab.hash); }); tab.addEventListener('keydown', event => { let next; if (event.key === 'ArrowRight') next = (index + 1) % tabs.length; if (event.key === 'ArrowLeft') next = (index + tabs.length - 1) % tabs.length; if (event.key === 'Home') next = 0; if (event.key === 'End') next = tabs.length - 1; if (event.key === ' ' || event.key === 'Enter') next = index; if (next === undefined) return; event.preventDefault(); activate(next, true); history.replaceState(null, '', tabs[next].hash); }); }); window.addEventListener('hashchange', fromHash); window.addEventListener('popstate', fromHash); fromHash(); })(); /* Copy-to-clipboard for the BibTeX blocks. The entry stays selectable without JS. */ (function () { const fallback = text => { const area = document.createElement('textarea'); area.value = text; area.setAttribute('readonly', ''); area.style.position = 'fixed'; area.style.opacity = '0'; document.body.appendChild(area); area.select(); let ok = false; try { ok = document.execCommand('copy'); } catch (e) { ok = false; } area.remove(); return ok; }; document.querySelectorAll('.copy-bibtex').forEach(button => { const label = button.textContent; const code = button.parentElement.querySelector('pre code'); if (!code) return; let timer = null; const done = (state, text) => { button.dataset.state = state; button.textContent = text; clearTimeout(timer); timer = setTimeout(() => { delete button.dataset.state; button.textContent = label; }, 1800); }; button.addEventListener('click', () => { const text = code.textContent; const write = navigator.clipboard && window.isSecureContext ? navigator.clipboard.writeText(text).then(() => true, () => fallback(text)) : Promise.resolve(fallback(text)); write.then(ok => done(ok ? 'copied' : 'failed', ok ? 'Copied' : 'Select and copy')); }); }); })();