UNPKG

jcore-ui

Version:

jcore-ui - components for building an interface

192 lines (155 loc) 4.7 kB
import Component, { IComponent, IComponentOn, IComponentOptions, IComponentSelector, } from "../core/Component"; import config from "../../config"; import { $, JDom } from "../core/JDom"; const selectors = { element: `.${config.prefix}-collapse`, wrapper: `.${config.prefix}-collapse-wrapper`, button: `.${config.prefix}-collapse-button`, }; interface ICollapseSelector extends IComponentSelector { wrapper?: string; button?: string; } interface ICollapseOptions extends IComponentOptions { height?: number; duration?: number; } interface ICollapseOn extends IComponentOn { toggle?: (ctx?: Component) => void; } interface ICollapse extends IComponent { selectors?: ICollapseSelector; options?: ICollapseOptions; on?: ICollapseOn; } interface Collapse { selectors: ICollapseSelector; $wrapper: JDom; $button: JDom; options: ICollapseOptions; isActive: boolean; scrollHeight: number; on: ICollapseOn; } class Collapse extends Component { constructor(props: ICollapse = {}) { super({ ...props, Component: Collapse, selectors: Object.assign(selectors, props.selectors || {}), }); if (this.options && this.options.mount) { this.mount(); } } mount() { if (!this.$element || this._mount || this.$element.attr("data-mount")) { return; } super.mount(); this.options = Object.assign( { height: this.$element.dataset.height || 0, duration: this.$element.dataset.duration || 300, }, this.options ); this.handlers = { toggle: this.toggle.bind(this), resize: this.resize.bind(this), }; this.on = Object.assign( { toggle: () => {}, }, this.on ); this.$wrapper = $(this.$element).find(this.selectors.wrapper); this.$button = $(this.$element).find(this.selectors.button); this.isActive = false; this.scrollHeight = this.$wrapper.scrollHeight; this.addEvents(); this.on.mount(this); this.emitter.emit("mount", this); } addEvents() { this.$wrapper.style.setProperty( "max-height", `${this.options.height}px` ); this.$wrapper.style.setProperty( "transition", `all ease-in-out ${this.options.duration}ms` ); this.$button.on("click", this.handlers.toggle); window.addEventListener("resize", this.handlers.resize); this.initButtonByHeight(); } unmount() { super.unmount(); this.$button.off("click", this.handlers.toggle, null); window.removeEventListener("resize", this.handlers.resize); this.$button.attr("data-mount", null); this.on.unmount(this); this.emitter.emit("unmount", this); } toggle() { this.scrollHeight = this.$wrapper.scrollHeight; if (this.isActive) { this.close(); } else { this.open(); } this.emitter.emit("toggle", this); this.on.toggle(this); } open() { this.$button.attr("data-active", ""); this.$element.attr("data-active", ""); this.$wrapper.attr("data-active", ""); this.$wrapper.style.setProperty("max-height", `${this.scrollHeight}px`); this.isActive = true; } close() { this.$button.attr("data-active", null); this.$element.attr("data-active", null); this.$wrapper.attr("data-active", null); this.$wrapper.style.setProperty( "max-height", `${this.options.height}px` ); this.isActive = false; } resize() { if (this.$wrapper) { this.scrollHeight = this.$wrapper.scrollHeight; if (this.isActive) { this.$wrapper.style.setProperty( "max-height", `${this.scrollHeight}px` ); } else { this.$wrapper.style.setProperty( "max-height", `${this.options.height}px` ); } } this.initButtonByHeight(); } initButtonByHeight() { if (this.$button) { if (this.scrollHeight < this.options.height) { this.$button.attr("data-mount", null); } else { this.$button.attr("data-mount", ""); } } } } export default Collapse;