<a href="#one" id="one" onclick="event.preventDefault(); javascript:collapsElement(1);">Раздел один</a>
interface UIOption {
el?: HTMLElement;
parent?: UI;
content?: string;
classList?: string[];
styleList?: { [name: string]: string | number };
hidden?: boolean;
}
function concat(left: string[], right: string[]) {
if (left && right) {
return left.concat(right);
}
return left || right;
}
class UI {
protected el: HTMLElement;
constructor(tagName: string, option: UIOption = { classList: [] }) {
if (option.el == null) {
option.el = document.createElement(tagName);
}
if (option.parent != null) option.parent.el.appendChild(option.el);
if (option.classList != null) option.el.classList.add(...option.classList);
if (option.styleList != null) null;
if (option.content != null) option.parent.el.textContent = option.content;
if (option.hidden != null) option.el.hidden = option.hidden;
this.el = option.el;
}
set hidden(hidden: boolean) {
this.el.hidden = hidden;
}
get hidden(): boolean {
return this.el.hidden;
}
get classList(): DOMTokenList {
return this.el.classList;
}
getAttribute(name: string): string {
return this.el.getAttribute(name);
}
addEventListener<K extends keyof HTMLElementEventMap>(
type: K,
listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,
options?: boolean | AddEventListenerOptions
) {
this.el.addEventListener(type, listener, options);
}
}
namespace UI {
export class Panel extends UI {
constructor(option: UIOption = { classList: [] }) {
super(
"div",
Object.assign<UIOption, UIOption>(option, {
classList: concat(["panel"], option.classList)
})
);
}
}
export class TabPanel extends Panel {
private _active: number = 0;
private _strip = new UI("ol", {
parent: this,
classList: ["strip", "container"]
});
items: Array<{ content: UI; button: UI }> = [];
opens: { [name: string]: number } = {};
constructor(option: UIOption = { classList: [] }) {
super(
Object.assign<UIOption, UIOption>(option, {
classList: concat(["tab"], option.classList)
})
);
this.el.querySelectorAll<HTMLElement>(":scope > div").forEach(el => {
this.createButton(new UI("div", { el, parent: this, hidden: true }));
});
this.items[this._active].button.classList.add("active");
this.items[this._active].content.hidden = false;
}
createButton(content: UI): number {
let button = new UI("button", { parent: this._strip });
let index = this.items.push({ content, button });
button.addEventListener("click", () => {
this.active = index - 1;
});
new UI("div", {
parent: button,
content: content.getAttribute("data-title")
});
return index - 1;
}
set active(index: number) {
if (this._active == index) return;
this.items[this._active].button.classList.remove("active");
this.items[this._active].content.hidden = true;
this.items[index].button.classList.add("active");
this.items[index].content.hidden = false;
this._active = index;
}
createPanel(el: HTMLDivElement, options?: { name?: string }): number {
let content = new UI("div", { el, parent: this, hidden: true });
let index = this.createButton(content);
if (options && options.name !== undefined) {
this.opens[options.name] = index;
}
return index;
}
open(name: string, create: (name: string) => HTMLDivElement) {
let index = this.opens[name];
if (index == undefined) {
index = this.createPanel(create(name), { name });
}
this.active = index;
}
}
}
export default UI;