diff --git a/src/cg-dropdown.js b/src/cg-dropdown.js index 01e16e6..ade425b 100644 --- a/src/cg-dropdown.js +++ b/src/cg-dropdown.js @@ -1,30 +1,46 @@ -import { customStyles, createSelected, getFormatItem } from './components/utils'; +import { + customStyles, + createSelected, + getFormatItem, + customStylesFormat, +} from './components/utils'; import { createBreadcrumb } from './components/create-element'; export class DropDown { + // Глобальные переменные класса #element; #list; #options; #caret; #items; + #category; #selectedItems; #indexes = []; + // Геттер возвращающий выбранные элементы get value() { return this.#selectedItems ?? null; } + // Геттер возвращающий индексы выбранных элементов get indexes() { return this.#indexes ?? []; } + // Конструктор принимающий настройки селекта constructor(options = {}) { this.#init(options); this.#render(); this.#initEvent(); } + // Метод добавления елемента в список index == string/object addItem(item) { + if (this.#category) { + console.log('can`t add item to category'); + return; + } + if (!item) { return false; } @@ -35,37 +51,48 @@ export class DropDown { this.#render(); } - deleteItem(item) { - let index = this.#items.indexOf(item); + // Метод удаления елемента из спискаindex == number + deleteItem(index) { + if (this.#category) { + console.log('can`t add item to category'); + return; + } + + const item = this.#items[index]; this.#items.splice(index, 1); - this.#render(); } + // Метод удаляющий все элементы списка. deleteItemAll() { this.#items.splice(0, this.#items.length); this.#render(); } + // Метод позволяющий в селекте выбрать элемент который будет изначально отрисовывать, index == number selectIndex(index) { + if (this.#category) { + console.log('can`t add item to category'); + return; + } + const options = this.#element.querySelectorAll('.list__item'); - // const selected = this.#element.querySelector('.selected'); if (index > options.length) { return; } const select = options[index].innerText; - // selected.innerText = select; - this.#render(select); } + // Метод возвращающий елемент по номеру, number == number getElement(number) { return this.#items[number]; } + // Метод позволяющий сделать селект disabled, value == boolean; disabled(value) { if (typeof value !== 'boolean') { return; @@ -81,6 +108,7 @@ export class DropDown { } } + // Метод позволяющий открывать/закрывать селект с помощью кнопок, button == внешняя кнопка(HTMLElement); method == string; buttonControl(button, method) { button.addEventListener('click', () => { if (method === 'open') { @@ -93,6 +121,7 @@ export class DropDown { }); } + // Общая инициализация селекта и формирование элементов #init(options) { this.#options = options; const { items, multiselect, url } = this.#options; @@ -121,12 +150,10 @@ export class DropDown { } items.forEach((dataItem, index) => { - let category = ''; - if (dataItem.category && dataItem.categoryItems) { - category = dataItem.category; + this.#category = dataItem.category; - this.#items.push(category); + this.#items.push(this.#category); dataItem.categoryItems.forEach((categoryItem, indexCategory) => { this.#items.push(getFormatItem(categoryItem, indexCategory)); }); @@ -136,6 +163,7 @@ export class DropDown { }); } + // Метод отрисовывающий кнопку селекта и каретку #initSelected(select) { const { styles, selected, placeholder } = this.#options; @@ -156,9 +184,9 @@ export class DropDown { } } + // Общий рендер элементов в список и их настойка #render(select) { const { styles, multiselect } = this.#options; - // const { category } = this.#items; if (select || (select && styles)) { this.#initSelected(select); @@ -166,20 +194,16 @@ export class DropDown { } else { this.#initSelected(); } + const ulList = document.createElement('ul'); + ulList.classList.add('list'); + if (styles) { const { list } = styles; - - if (ulList && list) { - Object.entries(list).forEach(([key, value]) => { - ulList.style[key] = value; - }); - } + customStylesFormat(list, ulList); } - ulList.classList.add('list'); - this.#element.appendChild(ulList); this.#items.forEach((dataItem) => { @@ -220,6 +244,7 @@ export class DropDown { this.#addOptionsBehaviour(); } + // Общий рендер элементов в список и их настойка с получением данных с URL async #renderUrl() { const { url, items, multiselect } = this.#options; @@ -253,15 +278,24 @@ export class DropDown { } liUrl.classList.add('list__item'); + liUrl.appendChild(textUrl); ulUrl.appendChild(liUrl); this.#items.push(item); }); + this.#items.filter((item, index) => { + if (typeof item !== 'object') { + this.#items.splice(index, 1); + } + return item; + }); + this.#addOptionsBehaviour(); } + // Метод открывающий список #open(oneClick) { this.#list = this.#element.querySelector('.list'); this.#caret = this.#element.querySelector('.caret'); @@ -275,17 +309,18 @@ export class DropDown { } } + // Метод закрывающий список #close() { this.#list.classList.remove('open'); this.#caret.classList.remove('caret_rotate'); } + // Метод реализовывающий выбор элементов в разных режимах. Обычный/Мультиселект/Мультиселект + мультиселект таг. #addOptionsBehaviour() { const { multiselect, placeholder, selected, multiselectTag } = this.#options; const options = this.#element.querySelectorAll('.list__item'); const select = this.#element.querySelector('.selected'); - const category = this.#element.querySelector('strong'); const ul = document.createElement('ul'); @@ -370,6 +405,7 @@ export class DropDown { }); } + // Метод позволяющий открывать/закрывать список по переданному эвенту. #initEvent() { const { event } = this.#options; if (!event) { diff --git a/src/components/create-element.js b/src/components/create-element.js index f897488..9394c49 100644 --- a/src/components/create-element.js +++ b/src/components/create-element.js @@ -1,28 +1,33 @@ +import { customStylesFormat } from './utils'; + +// Метод который создает и отвечает за поведение chips export function createBreadcrumb(data, title, index, id) { const { element, option, indexes, selectedItems } = data; - const { placeholder } = option; + const { placeholder, styles } = option; + const { chips } = styles; const selected = element.querySelector('.selected'); - - const li = document.createElement('li'); - const text = document.createTextNode(title); - const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + const liChip = document.createElement('li'); + const textNode = document.createTextNode(title); + const svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); const path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); const path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - svg.setAttribute('viewBox', '0 0 10 10'); + svgIcon.setAttribute('viewBox', '0 0 10 10'); path1.setAttribute('d', 'M3,7 L7,3'); path2.setAttribute('d', 'M3,3 L7,7'); - li.setAttribute('id', `tag-${index}`); + liChip.setAttribute('id', `tag-${index}`); - svg.classList.add('svg-icon'); + svgIcon.classList.add('svg-icon'); - svg.appendChild(path1); - svg.appendChild(path2); - li.appendChild(text); - li.appendChild(svg); + svgIcon.appendChild(path1); + svgIcon.appendChild(path2); + liChip.appendChild(textNode); + liChip.appendChild(svgIcon); - svg.addEventListener('click', (event) => { + customStylesFormat(chips, liChip); + + svgIcon.addEventListener('click', (event) => { event.stopPropagation(); const deleteIcon = indexes.indexOf(index); @@ -31,6 +36,7 @@ export function createBreadcrumb(data, title, index, id) { selectedItems.splice(deleteIcon, 1); let checkBox = ''; + if (id) { checkBox = document.getElementById(`chbox-${id}`); } else { @@ -44,8 +50,8 @@ export function createBreadcrumb(data, title, index, id) { selected.innerText = placeholder; } - li.parentElement.removeChild(li); + liChip.parentElement.removeChild(liChip); }); - return li; + return liChip; } diff --git a/src/components/utils.js b/src/components/utils.js index 26fde71..4950db2 100644 --- a/src/components/utils.js +++ b/src/components/utils.js @@ -1,10 +1,11 @@ +// Создание селектора export function createSelected(element, content, styles) { if (content) { element.innerHTML = `
-

${content}

-
-
+

${content}

+
+ `; } @@ -20,38 +21,28 @@ export function createSelected(element, content, styles) { } } +// Метод ищет и стилизует полученные елементы из styles export function customStyles(element, styles) { if (!styles) { return; } const { head, caret, placeholder } = styles; + const cgSelect = element.querySelector('.cg-select'); - const crt = element.querySelector('.caret'); + const caretSelect = element.querySelector('.caret'); + const placeholderSelect = element.querySelector('.selected'); - const placeh = element.querySelector('.selected'); + customStylesFormat(head, cgSelect); - if (head) { - Object.entries(head).forEach(([key, value]) => { - cgSelect.style[key] = value; - }); - } + customStylesFormat(caret, caretSelect); - if (caret) { - Object.entries(caret).forEach(([key, value]) => { - crt.style[key] = value; - }); - } - - if (placeh) { - if (placeholder) { - Object.entries(placeholder).forEach(([key, value]) => { - placeh.style[key] = value; - }); - } + if (placeholderSelect) { + customStylesFormat(placeholder, placeholderSelect); } } +// Метод checkItemStruct возвращает true/false если item содержит указанные свойства, export function checkItemStruct(item) { if (item && typeof item !== 'object') { return false; @@ -60,6 +51,7 @@ export function checkItemStruct(item) { return item.hasOwnProperty('id') && item.hasOwnProperty('title') && item.hasOwnProperty('value'); } +// Метод getFormatItem преобразовывает каждый елемент полученный из поля Items; export function getFormatItem(dataItem, index) { const random = Math.random().toString(36).substring(2, 10); let item = {}; @@ -80,3 +72,12 @@ export function getFormatItem(dataItem, index) { return item; } + +// Универсальный метод для стилизации селекта +export function customStylesFormat(elemOption, selector) { + if (elemOption) { + Object.entries(elemOption).forEach(([key, value]) => { + selector.style[key] = value; + }); + } +} diff --git a/src/index.js b/src/index.js index b63f3c7..b62ccb4 100644 --- a/src/index.js +++ b/src/index.js @@ -9,6 +9,8 @@ const dropdown = new DropDown({ multiselectTag: true, }); +dropdown.deleteItem(2); + // ------------------------------URL-------------------- const dropdown3 = new DropDown({ selector: '.cg-dropdown_three', @@ -53,7 +55,17 @@ const dropdown4 = new DropDown({ categoryItems: ['Paris'], }, ], - + styles: { + head: { + background: 'red', + }, + list: { + background: 'green', + }, + chips: { + background: 'blue', + }, + }, multiselect: true, multiselectTag: true, });