UNPKG

gd-bs

Version:

Bootstrap JavaScript, TypeScript and Web Components library.

163 lines (138 loc) 6.02 kB
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); } } }