gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
163 lines (138 loc) • 6.02 kB
text/typescript
import { IAccordionItem } from "./types";
import { appendContent } from "../common";
/**
* Accordion Item
*/
export class AccordionItem {
private _autoCollapse: boolean = null;
private _el: HTMLDivElement = null;
private _elCollapse: HTMLDivElement = null;
private _elHeader: HTMLButtonElement = null;
private _id: string = null;
private _itemId: string = null;
private _parentId: string = null;
private _props: IAccordionItem = null;
// Constructor
constructor(parentId: string, itemId: string, props: IAccordionItem, template: string, autoCollapse: boolean) {
// Save the properties
this._autoCollapse = autoCollapse;
this._id = "collapse" + itemId;
this._itemId = itemId;
this._parentId = parentId;
this._props = props;
// Create the item
let elItem = document.createElement("div");
elItem.innerHTML = template;
this._el = elItem.firstChild as HTMLDivElement;
// Set the class name
let classNames = (this._props.className || "").trim().split(" ");
for (let i = 0; i < classNames.length; i++) {
let className = classNames[i];
// Add the class name
className ? this._el.classList.add(className) : null;
}
// Render the header
this.renderHeader();
// Append the content
appendContent(this._el.querySelector(".accordion-body"), this._props.content);
// Configure the collapse element
this.configureCollapse();
// Configure the events
this.configureEvents();
}
// Configures the collapse element
private configureCollapse() {
this._elCollapse = this._el.querySelector(".accordion-collapse");
if (this._elCollapse) {
this._props.showFl ? this._elCollapse.classList.add("show") : null;
this._elCollapse.setAttribute("aria-labelledby", this._itemId);
this._elCollapse.setAttribute("data-bs-parent", "#" + this._parentId);
this._elCollapse.id = this._id;
}
}
// Configures the events
private configureEvents() {
// Add a click event
this._elHeader.addEventListener("click", () => {
// See if the auto collapse flag is not set
if (!this._autoCollapse) {
// Toggle the element
this.toggle();
}
// Call the click event
this._props.onClick ? this._props.onClick(this._elHeader, this._props) : null;
});
// Execute the render event
this._props.onRender ? this._props.onRender(this._el, this._props) : null;
this._props.onRenderBody ? this._props.onRenderBody(this._el.querySelector(".accordion-body"), this._props) : null;
this._props.onRenderHeader ? this._props.onRenderHeader(this._el.querySelector(".accordion-header"), this._props) : null;
}
// Renders the header
private renderHeader() {
let elHeader = this._el.querySelector(".accordion-header");
if (elHeader) {
// Set the properties
elHeader.id = this._itemId;
}
// Get the button
this._elHeader = this._el.querySelector(".accordion-button");
if (this._elHeader) {
// Set the class
this._props.showFl ? null : this._elHeader.classList.add("collapsed");
// Set the properties
this._elHeader.setAttribute("aria-controls", "collapse" + this._itemId);
this._elHeader.setAttribute("aria-expanded", this._props.showFl ? "true" : "false");
this._elHeader.setAttribute("data-bs-target", '#' + "collapse" + this._itemId);
this._elHeader.innerHTML = this._props.header;
}
}
/**
* Public Properties
*/
// The component HTML element
get el(): HTMLDivElement { return this._el; }
// The collapse element
get elCollapse(): HTMLDivElement { return this._elCollapse; }
// The header element
get elHeader(): HTMLButtonElement { return this._elHeader; }
// The item id
get id(): string { return this._id; }
// Returns true if the item is expanded
get isExpanded(): boolean {
// See if the item is expanded
return this.elCollapse.classList.contains("collapsing") || this.elCollapse.classList.contains("show");
}
// Toggles the item
toggle() {
// See if it's expanded
if (this.isExpanded) {
// Start the animation
this.elCollapse.style.height = this.el.getBoundingClientRect()["height"] + "px";
setTimeout(() => {
this.elCollapse.classList.add("collapsing");
this.elCollapse.classList.remove("collapse");
this.elCollapse.classList.remove("show");
this.elCollapse.style.height = "";
}, 10);
// Wait for the animation to complete
setTimeout(() => {
this.elCollapse.classList.remove("collapsing");
this.elCollapse.classList.add("collapse");
this.elHeader.classList.add("collapsed");
}, 250);
} else {
// Start the animation
this.elCollapse.classList.remove("collapse");
this.elCollapse.classList.add("collapsing");
this.elCollapse.style.height = this.el.scrollHeight + "px";
// Wait for the animation to complete
setTimeout(() => {
this.elCollapse.classList.remove("collapsing");
this.elCollapse.classList.add("collapse");
this.elCollapse.classList.add("show");
this.elCollapse.style.height = "";
this.elHeader.classList.remove("collapsed");
}, 250);
}
}
}