11cb0ef41Sopenharmony_ci 21cb0ef41Sopenharmony_ciexport class Tabs { 31cb0ef41Sopenharmony_ci private container: HTMLElement; 41cb0ef41Sopenharmony_ci private tabBar: HTMLElement; 51cb0ef41Sopenharmony_ci private nextTabId: number; 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci private mkTabBar(container: HTMLElement) { 81cb0ef41Sopenharmony_ci container.classList.add("nav-tabs-container"); 91cb0ef41Sopenharmony_ci this.tabBar = document.createElement("ul"); 101cb0ef41Sopenharmony_ci this.tabBar.id = `tab-bar-${container.id}`; 111cb0ef41Sopenharmony_ci this.tabBar.className = "nav-tabs"; 121cb0ef41Sopenharmony_ci this.tabBar.ondrop = this.tabBarOnDrop.bind(this); 131cb0ef41Sopenharmony_ci this.tabBar.ondragover = this.tabBarOnDragover.bind(this); 141cb0ef41Sopenharmony_ci this.tabBar.onclick = this.tabBarOnClick.bind(this); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci const defaultDiv = document.createElement("div"); 171cb0ef41Sopenharmony_ci defaultDiv.className = "tab-content tab-default"; 181cb0ef41Sopenharmony_ci defaultDiv.id = `tab-content-${container.id}-default`; 191cb0ef41Sopenharmony_ci container.insertBefore(defaultDiv, container.firstChild); 201cb0ef41Sopenharmony_ci container.insertBefore(this.tabBar, container.firstChild); 211cb0ef41Sopenharmony_ci } 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci constructor(container: HTMLElement) { 241cb0ef41Sopenharmony_ci this.container = container; 251cb0ef41Sopenharmony_ci this.nextTabId = 0; 261cb0ef41Sopenharmony_ci this.mkTabBar(container); 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci activateTab(tab: HTMLLIElement) { 301cb0ef41Sopenharmony_ci if (typeof tab.dataset.divid !== "string") return; 311cb0ef41Sopenharmony_ci for (const li of this.tabBar.querySelectorAll<HTMLLIElement>("li.active")) { 321cb0ef41Sopenharmony_ci li.classList.remove("active"); 331cb0ef41Sopenharmony_ci this.showTab(li, false); 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci tab.classList.add("active"); 361cb0ef41Sopenharmony_ci this.showTab(tab, true); 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci clearTabsAndContent() { 401cb0ef41Sopenharmony_ci for (const tab of this.tabBar.querySelectorAll(".nav-tabs > li")) { 411cb0ef41Sopenharmony_ci if (!(tab instanceof HTMLLIElement)) continue; 421cb0ef41Sopenharmony_ci if (tab.classList.contains("persistent-tab")) continue; 431cb0ef41Sopenharmony_ci const tabDiv = document.getElementById(tab.dataset.divid); 441cb0ef41Sopenharmony_ci tabDiv.parentNode.removeChild(tabDiv); 451cb0ef41Sopenharmony_ci tab.parentNode.removeChild(tab); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci private showTab(li: HTMLElement, show: boolean = true) { 501cb0ef41Sopenharmony_ci const tabDiv = document.getElementById(li.dataset.divid); 511cb0ef41Sopenharmony_ci tabDiv.style.display = show ? "block" : "none"; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci public addTab(caption: string): HTMLLIElement { 551cb0ef41Sopenharmony_ci const newTab = document.createElement("li"); 561cb0ef41Sopenharmony_ci newTab.innerHTML = caption; 571cb0ef41Sopenharmony_ci newTab.id = `tab-header-${this.container.id}-${this.nextTabId++}`; 581cb0ef41Sopenharmony_ci const lastTab = this.tabBar.querySelector("li.last-tab"); 591cb0ef41Sopenharmony_ci this.tabBar.insertBefore(newTab, lastTab); 601cb0ef41Sopenharmony_ci return newTab; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci public addTabAndContent(caption: string): [HTMLLIElement, HTMLDivElement] { 641cb0ef41Sopenharmony_ci const contentDiv = document.createElement("div"); 651cb0ef41Sopenharmony_ci contentDiv.className = "tab-content tab-default"; 661cb0ef41Sopenharmony_ci contentDiv.id = `tab-content-${this.container.id}-${this.nextTabId++}`; 671cb0ef41Sopenharmony_ci contentDiv.style.display = "none"; 681cb0ef41Sopenharmony_ci this.container.appendChild(contentDiv); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci const newTab = this.addTab(caption); 711cb0ef41Sopenharmony_ci newTab.dataset.divid = contentDiv.id; 721cb0ef41Sopenharmony_ci newTab.draggable = true; 731cb0ef41Sopenharmony_ci newTab.ondragstart = this.tabOnDragStart.bind(this); 741cb0ef41Sopenharmony_ci const lastTab = this.tabBar.querySelector("li.last-tab"); 751cb0ef41Sopenharmony_ci this.tabBar.insertBefore(newTab, lastTab); 761cb0ef41Sopenharmony_ci return [newTab, contentDiv]; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci private moveTabDiv(tab: HTMLLIElement) { 801cb0ef41Sopenharmony_ci const tabDiv = document.getElementById(tab.dataset.divid); 811cb0ef41Sopenharmony_ci tabDiv.style.display = "none"; 821cb0ef41Sopenharmony_ci tab.classList.remove("active"); 831cb0ef41Sopenharmony_ci this.tabBar.parentNode.appendChild(tabDiv); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci private tabBarOnDrop(e: DragEvent) { 871cb0ef41Sopenharmony_ci if (!(e.target instanceof HTMLElement)) return; 881cb0ef41Sopenharmony_ci e.preventDefault(); 891cb0ef41Sopenharmony_ci const tabId = e.dataTransfer.getData("text"); 901cb0ef41Sopenharmony_ci const tab = document.getElementById(tabId) as HTMLLIElement; 911cb0ef41Sopenharmony_ci if (tab.parentNode != this.tabBar) { 921cb0ef41Sopenharmony_ci this.moveTabDiv(tab); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci const dropTab = 951cb0ef41Sopenharmony_ci e.target.parentNode == this.tabBar 961cb0ef41Sopenharmony_ci ? e.target : this.tabBar.querySelector("li.last-tab"); 971cb0ef41Sopenharmony_ci this.tabBar.insertBefore(tab, dropTab); 981cb0ef41Sopenharmony_ci this.activateTab(tab); 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci private tabBarOnDragover(e) { 1021cb0ef41Sopenharmony_ci e.preventDefault(); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci private tabOnDragStart(e: DragEvent) { 1061cb0ef41Sopenharmony_ci if (!(e.target instanceof HTMLElement)) return; 1071cb0ef41Sopenharmony_ci e.dataTransfer.setData("text", e.target.id); 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci private tabBarOnClick(e: MouseEvent) { 1111cb0ef41Sopenharmony_ci const li = e.target as HTMLLIElement; 1121cb0ef41Sopenharmony_ci this.activateTab(li); 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci} 115