spectre.css-js
Version:
JavaScript code base for Spectre.css
199 lines (162 loc) • 4.4 kB
JavaScript
/*
* 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();
}
}