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