UNPKG

spectre.css-js

Version:
199 lines (162 loc) 4.4 kB
/* * Created by Artyom Manchenkov * artyom@manchenkoff.me * manchenkoff.me © 2019 */ import Widget from '../classes/widget' /** * Chips component * @property {string[]} chips * @property {HTMLFormElement} input * @property {HTMLElement} chipsBlock * @property {object} config */ export default class Chips extends Widget { /** * @inheritDoc */ static get selector() { return '[data-chips]'; } /** * @inheritDoc */ static get class() { return Chips; } /** * @inheritDoc */ init() { this.chips = []; this._buildConfig(); this._buildContainer(); this._buildInput(); } /** * Builds widget configuration * @private */ _buildConfig() { this.config = { chipsEnter: true, chipsComma: true, chipsClasses: [], chipsContainerClasses: ['mb-3'], }; this.loadDataParams(this.config); } /** * Builds container for the chip items * @private */ _buildContainer() { this.chipsContainer = document.createElement('div'); this.chipsContainer.classList.add( ...this.config.chipsContainerClasses ); this.element.parentElement.prepend(this.chipsContainer); } /** * Builds an input to store value * @private */ _buildInput() { this.input = document.createElement('input'); this.input.type = 'hidden'; this.input.name = `${this.element.name}`; this.element.removeAttribute('name'); this.element.parentElement.append(this.input); this.element.onkeyup = (event) => { let useComma = (event.key === "," && this.config.chipsComma); let useEnter = (event.key === "Enter" && this.config.chipsEnter); if (useComma || useEnter) { let content = event.target.value; if (useComma) { content = content.replace(',', ''); } this.add(content); event.target.value = ''; } }; } /** * Creates a new chip item to append to the container * @param label * @returns {HTMLSpanElement} * @private */ _buildChip(label) { // chip item let chip = document.createElement('span'); chip.classList.add('chip'); chip.innerText = label; chip.dataset.chip = label; if (this.config.chipsClasses.length > 0) { chip.classList.add(...this.config.chipsClasses); } // close button let closeButton = document.createElement('a'); closeButton.classList.add('btn', 'btn-clear'); closeButton.role = 'button'; closeButton.href = '#'; closeButton.onclick = (event) => { this.delete(event.target.parentElement.dataset.chip); }; chip.appendChild(closeButton); return chip; } /** * Resets UI values to update the latest changes * @private */ _reset() { this.chipsContainer.innerHTML = ''; this.input.value = ''; } /** * Updates UI to the latest changes */ refresh() { this._reset(); this.chips.forEach( (label) => { let chip = this._buildChip(label); this.input.value += `${label},`; this.chipsContainer.appendChild(chip); } ); this.input.value = this.input.value.substr( 0, this.input.value.length - 1 ); } /** * Adds a new chip value * @param value */ add(value) { // check value is not empty if (value !== '' && value !== ' ') { // replace " to ' value = value.replace(/"/g, "'"); // check duplicates let exists = this.chips.find((item) => { return item === value; }); if (!exists) { this.chips.push(value); this.refresh(); } } } /** * Removes a chip by value * @param value */ delete(value) { this.chips = this.chips.filter((item) => { return item !== value; }); this.refresh(); } }