diff --git a/example/indexTs.ts b/example/indexTs.ts index d96c107..88d4c99 100644 --- a/example/indexTs.ts +++ b/example/indexTs.ts @@ -4,16 +4,41 @@ const dropdn = new CGSelect({ selector: '.cg-dropdown_one', placeholder: 'Выберите авто', items: [ - 'BMW', { - id: '213sade', - title: 'Opel', - value: 'ds', + category: 'Russia', + categoryItems: [ + { + id: '28qwds', + title: 'Москва', + value: 0, + }, + , + 'Ростов-на-дону', + 'Саратов', + 'Волгоград', + 'Донецк', + ], + }, + { + category: 'USA', + categoryItems: ['Alabama', 'Texas', 'Colorado', 'Klirens', 'Los-Angeles'], + }, + { + category: 'France', + categoryItems: ['Paris'], }, - 'Mersedes', - 'MAN', - 'Ferari', ], + styles: { + head: { + width: '830px', + }, + list: { + width: '824px', + }, + placeholder: { + maxWidth: '500px ', + }, + }, multiselect: true, multiselectTag: true, }); diff --git a/src/cg-select.js b/src/cg-select.js index 96bf00c..3230143 100644 --- a/src/cg-select.js +++ b/src/cg-select.js @@ -548,7 +548,7 @@ export class DropDown { /** * Приватный метод рендера экземпляра класса DropDown - *@protected + * @protected * @method #renderUrl * @description Рендер елементов в селекте переданных с URL и их настойка */ diff --git a/src/cg-selectTS.ts b/src/cg-selectTS.ts index 2a2722c..51b230c 100644 --- a/src/cg-selectTS.ts +++ b/src/cg-selectTS.ts @@ -8,6 +8,8 @@ import { ICreateBreadCrumb } from './components/create-element/create-element.in import { clearSelect, createSelected, + customStyles, + customStylesFormat, getFormatItem, getSelectText, nativeOptionMultiple, @@ -15,7 +17,7 @@ import { } from './components/utils/utilsTs'; import { IDataItem, ISelectedItems } from './components/utils/urils.interface'; -import { ICgSelect } from './interfaces/cg-select.interface'; +import { ICgSelect, IStyle } from './interfaces/cg-select.interface'; import { IItems } from './interfaces/items.interface'; import './main.scss'; @@ -32,7 +34,7 @@ export class CGSelect implements ICgSelect { listDisplayMode?: boolean; language?: string; lable?: string; - styles?: object; + styles?: IStyle; event?: string; url?: string; multiselect?: boolean; @@ -104,15 +106,25 @@ export class CGSelect implements ICgSelect { items.forEach((dataItem: any, index: number) => { let itemInputs: IDataItem = { ItemValue: dataItem, + // category: dataItem.category, + // categoryItems: dataItem.categoryItems, }; - this.itemsSelect.push(getFormatItem(itemInputs.ItemValue, index)); + if (dataItem.category && dataItem.categoryItems) { + this.category = dataItem.category!; + this.itemsSelect.push(this.category); + dataItem.categoryItems.forEach((categoryItem, indexCategory) => { + this.itemsSelect.push(getFormatItem(categoryItem, indexCategory)); + }); + } else { + this.itemsSelect.push(getFormatItem(itemInputs.ItemValue, index)); + } }); } /** * Приватный метод рендера экземпляра класса DropDown - *@protected + * @protected * @method render * @param {string} select необязательный елемент. Передаеться в метод initSelected * @description Рендер елементов в селекте. @@ -131,7 +143,12 @@ export class CGSelect implements ICgSelect { const random = Math.random().toString(36).substring(2, 10); - this.initSelected(); + if (select || (select && styles)) { + this.initSelected(select); + customStyles(this.element!, styles); + } else { + this.initSelected(); + } const ulList = document.createElement('ul'); const nativeSelect = createNativeSelect(); @@ -143,6 +160,11 @@ export class CGSelect implements ICgSelect { ulList.classList.add('list'); + if (styles) { + const { list } = styles; + customStylesFormat(list!, ulList); + } + this.element?.appendChild(ulList); this.itemsSelect.forEach((dataItem: IItems | any) => { @@ -184,13 +206,98 @@ export class CGSelect implements ICgSelect { } }); + this.itemsSelect.filter((item, index) => { + if (typeof item !== 'object') { + this.itemsSelect.splice(index, 1); + } + return item; + }); + + if (darkTheme == false) { + this.checkTheme(); + } + + if (nativeSelectMode === true) { + // this.#selectMode(nativeSelectMode); + } + this.list = this.element?.querySelector('.list'); this.caret = this.element?.querySelector('.caret'); this.addOptionsBehaviour(); } - private renderUrl() {} + /** + * Приватный метод рендера экземпляра класса DropDown + * @protected + * @method renderUrl + * @description Рендер елементов в селекте переданных с URL и их настойка + */ + private async renderUrl() { + const { url, items, multiselect, multiselectTag } = this.options; + + if (items) { + return; + } + + if (!url) { + return; + } + + const response = await fetch(url); + const dataUrl = await response.json(); + + const nativeSelect = createNativeSelect(); + + dataUrl.forEach((dataItem: IItems, index: number) => { + const item = { + id: dataItem.id, + title: dataItem.title, + value: index, + }; + + const ulUrl = this.element!.querySelector('.list'); + + const nativeOption = createNativeSelectOption(); + const liUrl = document.createElement('li'); + const textUrl = document.createTextNode(item.title); + + if (multiselect) { + const checkBox = document.createElement('input'); + checkBox.type = 'checkbox'; + + if (multiselectTag) { + checkBox.classList.add('displayHide'); + } + + checkBox.setAttribute('id', `chbox-${item.id}`); + nativeSelect.setAttribute('multiple', 'multiple'); + + liUrl.appendChild(checkBox); + } + + liUrl.classList.add('list__item'); + nativeOption.value = item.title; + nativeOption.text = item.title; + + nativeSelect.appendChild(nativeOption); + liUrl.appendChild(textUrl); + ulUrl!.appendChild(liUrl); + + this.itemsSelect.push(item); + }); + + this.element!.appendChild(nativeSelect); + + this.itemsSelect.filter((item, index) => { + if (typeof item !== 'object') { + this.itemsSelect.splice(index, 1); + } + return item; + }); + + this.addOptionsBehaviour(); + } /** * Привaтный метод экземпляра класса DropDown @@ -208,11 +315,29 @@ export class CGSelect implements ICgSelect { } else if (placeholder) { createSelected(this.element, placeholder); } else { - // if (language && language === 'ru') { - // createSelected(this.#element, ru.selectPlaceholder); - // } else { - // createSelected(this.#element, en.selectPlaceholder); - // } + if (language && language === 'ru') { + // createSelected(this.#element, ru.selectPlaceholder); + } else { + // createSelected(this.#element, en.selectPlaceholder); + } + } + + if (select) { + createSelected(this.element, select, styles); + } + + if (lable) { + const lableItem = document.createElement('h1'); + const textLable = document.createTextNode(lable); + + lableItem.appendChild(textLable); + lableItem.classList.add('label'); + + this.element!.insertAdjacentElement('beforebegin', lableItem); + } + + if (styles) { + customStyles(this.element!, styles); } } @@ -237,7 +362,7 @@ export class CGSelect implements ICgSelect { * Приватный метод экземпляра класса DropDown * @protected * @description Закрывает список - * @method #close + * @method close */ private close(): void { this.list?.classList.remove('open'); @@ -396,4 +521,33 @@ export class CGSelect implements ICgSelect { }); }); } + + /** + * Приватный метод рендера экземпляра класса DropDown + * @protected + * @method #checkTheme + * @description Изменяет цветовую схему с темной на светлую. + */ + private checkTheme(): void { + const { darkTheme, searchMode } = this.options; + + const select = this.element!.querySelector('.cg-select'); + const caret = this.element!.querySelector('.caret'); + const list = this.element!.querySelector('ul.list'); + const search = this.element!.querySelector('.inputSearch'); + + if (darkTheme == false) { + select!.classList.add('selectWhite'); + caret!.classList.add('caretWhite'); + list!.classList.add('listWhite'); + + if (searchMode == true) { + search!.classList.add('inputWhite'); + } + } else if (darkTheme == true || !darkTheme) { + return; + } else { + throw new Error('Styles error or invalid value entered!'); + } + } } diff --git a/src/components/utils/utilsTs.ts b/src/components/utils/utilsTs.ts index eca9b81..4c82a65 100644 --- a/src/components/utils/utilsTs.ts +++ b/src/components/utils/utilsTs.ts @@ -204,3 +204,42 @@ export function nativeOptionMultiple( } }); } + +/** + * Поиск и стилизация елементов полученных из styles экземпляра DropDown + * @param {Element} element созданный экземпляр класса DropDown + * @param {object} styles объект в котором находяться настройки кастомизации частей селекта + */ +export function customStyles(element: Element, styles: any) { + if (!styles) { + return; + } + + const { head, caret, placeholder, lable } = styles; + + const cgSelect = element.querySelector('.cg-select'); + const caretSelect = element.querySelector('.caret'); + const placeholderSelect = element.querySelector('.selected'); + const lableItem = element.parentElement!.querySelector('h1.label'); + + customStylesFormat(head, cgSelect!); + customStylesFormat(caret, caretSelect!); + customStylesFormat(lable, lableItem!); + + if (placeholderSelect) { + customStylesFormat(placeholder, placeholderSelect); + } +} + +/** + * Универсальный метод для стилизации селекта + * @param {object} elemOption объект полученное из объекта styles у которого мы получаем ключ-значение стилей + * @param {HTMLElement} selector HTMLElement подвергающиеся кастомизации + */ +export function customStylesFormat(elemOption: object, selector: any) { + if (elemOption) { + Object.entries(elemOption).forEach(([key, value]) => { + selector.style[key] = value; + }); + } +} diff --git a/src/interfaces/cg-select.interface.ts b/src/interfaces/cg-select.interface.ts index fe0d651..b2cb7f6 100644 --- a/src/interfaces/cg-select.interface.ts +++ b/src/interfaces/cg-select.interface.ts @@ -12,9 +12,18 @@ export interface ICgSelect { listDisplayMode?: boolean; language?: string; lable?: string; - styles?: object; + styles?: IStyle; event?: string; url?: string; multiselect?: boolean; multiselectTag?: boolean; } + +export interface IStyle { + head?: object; + caret?: object; + placeholder?: object; + lable?: object; + list?: object; + search?: object; +}