UNPKG

jcore-ui

Version:

jcore-ui - components for building an interface

171 lines (136 loc) 4.62 kB
import Component, { IComponent, IComponentOn, IComponentOptions, IComponentSelector } from '../core/Component'; import config from '../../config'; import { $, JDom } from '../core/JDom'; const selectors = { element: `.${config.prefix}-select`, wrapper: `.${config.prefix}-select-wrapper`, value: `.${config.prefix}-select-value`, items: `.${config.prefix}-select-items`, item: `.${config.prefix}-select-item`, input: `.${config.prefix}-select-input`, current: `.${config.prefix}-select-current`, } interface ISelectSelector extends IComponentSelector { wrapper: string; value: string; items: string; item: string; input: string; current: string; } interface ISelectValue { value: string| number; label: string| number; } interface ISelectOptions extends IComponentOptions { value?: ISelectValue; items?: ISelectValue[]; } interface ISelectOn extends IComponentOn { toggle?: (ctx?: Component) => void; change?: (ctx?: Component) => void; } interface ISelect extends IComponent { selectors?: ISelectSelector; options?: ISelectOptions; on?: ISelectOn; } interface Select { selectors: ISelectSelector; options: ISelectOptions; value: ISelectValue; items: ISelectValue[]; $input: JDom; $value: JDom; $items: JDom; $itemList: JDom; on: ISelectOn; } class Select extends Component { constructor(props: ISelect = {}) { super({ ...props, Component: Select, 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({ // active: this.$element.dataset.active || false }, this.options); this.on = Object.assign({ toggle: () => { }, change: () => { } }, this.on); this.handlers = { toggle: this.toggle.bind(this), documentClickHandler: this.documentClickHandler.bind(this), change: this.change.bind(this) }; this.value = this.options && this.options.value || null; this.items = this.options && this.options.items || null; this.$input = this.$element.find(this.selectors.input); this.$value = this.$element.find(this.selectors.value); this.$items = this.$element.find(this.selectors.items); this.$itemList = this.$items.find(this.selectors.item); this.addEvents(); this.on.mount(this); this.emitter.emit('mount', this); } addEvents() { this.$value.on('click', this.handlers.toggle); document.addEventListener('click', this.handlers.documentClickHandler); this.$itemList.each(($item) => $item.addEventListener('click', this.handlers.change)); } documentClickHandler(e: Event) { if (!e.target.closest(this.selectors.element) && this.$element.attr('data-active')) { this.$element.toggleAttribute('data-active'); this.on.toggle(this); this.emitter.emit('toggle', this); } } toggle() { this.$element.toggleAttribute('data-active'); this.on.toggle(this); this.emitter.emit('toggle', this); } close() { this.$element.attr('data-active', null); } change(e: Event) { const $current = this.$items.find('[data-selected]'); const $item = $(e.target as HTMLElement).closest(this.selectors.item); const value = $item.dataset.value.trim(); const label = $item.html.toString().trim(); if ($item.hasAttr('data-selected')) { return; } if ($current) { $current.attr('data-selected', null); } $item.attr('data-selected', ''); this.value = { value, label }; this.$input.value = value; this.$value.attr('data-value', value); this.$value.html = label; this.close(); this.on.change(this); this.emitter.emit('change', this); } unmount() { super.unmount(); this.on.unmount(this); this.emitter.emit('unmount', this); } } export default Select