1/** 2 * Episode content tabs (dramatic layout). Wires [role="tab"] buttons 3 * to [role="tabpanel"] via aria-controls. 4 */ 5(function () { 6 "use strict"; 7 8 function activate(root, target) { 9 root.querySelectorAll('[role="tab"]').forEach(function (tab) { 10 var isActive = tab.dataset.tabTarget === target; 11 tab.setAttribute("aria-selected", isActive ? "true" : "false"); 12 tab.classList.toggle("is-selected", isActive); 13 }); 14 root.querySelectorAll("[data-tab-panel]").forEach(function (panel) { 15 panel.hidden = panel.dataset.tabPanel !== target; 16 }); 17 } 18 19 function init(root) { 20 if (root.dataset.tabsReady) return; 21 root.dataset.tabsReady = "1"; 22 23 root.addEventListener("click", function (e) { 24 var tab = e.target.closest('[role="tab"][data-tab-target]'); 25 if (!tab || !root.contains(tab)) return; 26 activate(root, tab.dataset.tabTarget); 27 }); 28 29 // Keyboard arrow navigation. 30 root.addEventListener("keydown", function (e) { 31 var tab = e.target.closest('[role="tab"]'); 32 if (!tab) return; 33 var tabs = Array.prototype.slice.call(root.querySelectorAll('[role="tab"]')); 34 var idx = tabs.indexOf(tab); 35 if (idx === -1) return; 36 var next = idx; 37 if (e.key === "ArrowRight") next = (idx + 1) % tabs.length; 38 else if (e.key === "ArrowLeft") next = (idx - 1 + tabs.length) % tabs.length; 39 else return; 40 e.preventDefault(); 41 tabs[next].focus(); 42 activate(root, tabs[next].dataset.tabTarget); 43 }); 44 } 45 46 function initAll() { 47 document.querySelectorAll("[data-episode-tabs]").forEach(init); 48 } 49 50 if (document.readyState === "loading") { 51 document.addEventListener("DOMContentLoaded", initAll); 52 } else { 53 initAll(); 54 } 55 document.addEventListener("htmx:afterSwap", initAll); 56 // Back/Forward restores cached markup and fires only `historyRestore`; 57 // pv-boost-nav.js clears data-tabs-ready so this re-init is not a no-op. 58 document.addEventListener("htmx:historyRestore", initAll); 59})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.