diff --git a/src/cg-dropdown.js b/src/cg-dropdown.js index be9ad98..a858828 100644 --- a/src/cg-dropdown.js +++ b/src/cg-dropdown.js @@ -4,6 +4,16 @@ export class DropDown { #options; #caret; #items; + #value; + #indexes = []; + + get value() { + return this.#value ?? null; + } + + get indexes() { + return this.#indexes ?? []; + } constructor(options = {}) { this.#init(options); @@ -53,15 +63,18 @@ export class DropDown { this.#element = elem; this.#element.addEventListener('click', () => { - this.#selectItem(); this.#open(); }); this.#list = this.#element.querySelector('.list'); this.#caret = this.#element.querySelector('.caret'); - const { items } = this.#options; + const { items, multiselect } = this.#options; this.#items = items; + + if (multiselect) { + this.#value = []; + } } #initSelected(select) { @@ -105,7 +118,7 @@ export class DropDown { } #render(select) { - const { items, styles, url } = this.#options; + const { items, styles, url, multiselect } = this.#options; if (select || (select && styles)) { this.#initSelected(select); @@ -122,42 +135,49 @@ export class DropDown { ul.classList.add('list'); - if (ul) { - if (list) { - Object.entries(list).forEach(([key, value]) => { - ul.style[key] = value; - }); - } + if (ul && list) { + Object.entries(list).forEach(([key, value]) => { + ul.style[key] = value; + }); } + this.#element.appendChild(ul); } else { ul.classList.add('list'); this.#element.appendChild(ul); } - if (!items) { - if (url) { - this.#renderUrl(); - } - } else { - items.map((item) => { - let li = document.createElement('li'); + if (!items && url) { + this.#renderUrl(); - if (typeof item == 'object') { - const text = document.createTextNode(item.title); - - li.classList.add('list__item'); - li.appendChild(text); - } else { - const text = document.createTextNode(item); - - li.classList.add('list__item'); - li.appendChild(text); - } - - ul.appendChild(li); - }); + return; } + + items.forEach((item) => { + const li = document.createElement('li'); + let text = ''; + + li.classList.add('list__item'); + + if (this.#checkItemStruct(item)) { + text = item.title; + } else { + text = item; + } + + if (multiselect) { + const checkBox = document.createElement('input'); + checkBox.type = 'checkbox'; + li.appendChild(checkBox); + } + + let textNode = document.createTextNode(text); + + li.appendChild(textNode); + ul.appendChild(li); + }); + + this.#addOptionsBehaviour(); } async #renderUrl() { @@ -172,25 +192,33 @@ export class DropDown { } const response = await fetch(url); - const data = await response.json(); //ToDO: fix title(item.title!) - data.forEach((item, index) => { - const items = { - id: item.id, - title: item.name, + this.#items = []; + + data.forEach((dataItem, index) => { + const item = { + id: dataItem.id, + title: dataItem.name, value: index, }; - const ul = this.#element.querySelector('.list'); - const li = document.createElement('li'); - const text = document.createTextNode(items.title); + const text = document.createTextNode(item.title); + + const checkBox = document.createElement('input'); + checkBox.type = 'checkbox'; + li.appendChild(checkBox); + li.classList.add('list__item'); li.appendChild(text); ul.appendChild(li); + + this.#items.push(item); }); + + this.#addOptionsBehaviour(); } #open() { @@ -206,18 +234,92 @@ export class DropDown { this.#caret.classList.remove('caret_rotate'); } - #selectItem() { + #addOptionsBehaviour() { + const { multiselect, placeholder, multiselectTag } = this.#options; + const options = this.#element.querySelectorAll('.list__item'); const selected = this.#element.querySelector('.selected'); - options.forEach((option) => { - option.addEventListener('click', () => { - selected.innerText = option.innerText; + // const ul = document.createElement('ul'); - options.forEach((option) => { - option.classList.remove('active'); - }); - option.classList.add('active'); + // ul.classList.add('multiselectTag'); + + options.forEach((option, index) => { + option.addEventListener('click', (event) => { + const item = this.#items[index]; + + if (multiselect) { + event.stopPropagation(); + option.classList.toggle('active'); + + const checkBox = option.querySelector('input[type="checkbox"]'); + + if (checkBox) { + if (!(event.target instanceof HTMLInputElement)) { + checkBox.checked = !checkBox.checked; + } + + const checkIndex = this.#indexes.indexOf(index); + + let templete = ''; + if (checkIndex === -1) { + this.#indexes.push(index); + + if (this.#checkItemStruct(item)) { + this.#value.push(item.title); + } else { + this.#value.push(item); + } + + //TODO refactoring code!!!! + if (multiselectTag) { + for (let i = 0; i < this.#value.length; i++) { + templete += `
  • ${this.#value[i]}
  • `; + } + + selected.innerHTML = ``; + } else { + selected.innerText = this.#value; + } + + return; + } + + this.#indexes.splice(checkIndex, 1); + this.#value.splice(checkIndex, 1); + + if (multiselectTag) { + for (let i = 0; i < this.#value.length; i++) { + templete += `
  • ${this.#value[i]}
  • `; + } + + selected.innerHTML = ``; + } + + if (!this.#value.length) { + selected.innerText = placeholder; + } else { + if (multiselectTag) { + selected.innerHTML = ``; + } else { + selected.innerText = this.#value; + } + } + } + } else { + if (this.#checkItemStruct(item)) { + selected.innerText = item.title; + } else { + selected.innerText = item; + } + + this.#value = item; + + options.forEach((option) => { + option.classList.remove('active'); + }); + option.classList.add('active'); + } }); }); } @@ -296,4 +398,14 @@ export class DropDown { `; } } + + #checkItemStruct(item) { + if (item && typeof item !== 'object') { + return false; + } + + return ( + item.hasOwnProperty('id') && item.hasOwnProperty('title') && item.hasOwnProperty('value') + ); + } } diff --git a/src/index.html b/src/index.html index 2856148..b0acd6d 100644 --- a/src/index.html +++ b/src/index.html @@ -13,7 +13,7 @@
    -
    +
    diff --git a/src/index.js b/src/index.js index f8ef3e8..eaa4547 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,8 @@ const dropdown = new DropDown({ selector: '.cg-dropdown', placeholder: 'Выберите авто', items: ['BMW', 'Opel', 'Mersedes', 'MAN', 'max'], + multiselect: true, + multiselectTag: true, }); dropdown.addItem('ZAZ'); @@ -11,36 +13,51 @@ dropdown.addItem('LADA'); const dropdown2 = new DropDown({ selector: '.cg-dropdown2', - placeholder: 'Выберите авто', - items: ['BMW', 'Opel', 'Mersedes', 'MAN', 'Kamaz'], - event: 'mouseenter', - styles: { - head: { - background: 'red', - color: 'black', - width: '400px', + placeholder: 'SELECT CAR', + items: [ + { + id: 'addaw21', + title: 'BMW', + value: '1', }, - placeholder: { - color: 'grey', + { + id: '2414q', + title: 'Opel', + value: '2', }, - caret: { - 'border-top': '6px solid black', + { + id: '24qwds', + title: 'Kamaz 258', + value: '3', }, - list: { - background: 'red', - color: 'black', - width: '412px', + { + id: '28wds', + title: 'MAN', + value: '4', }, - }, + { + id: '28qwds', + title: 'BOOT', + value: '5', + }, + ], + multiselect: true, }); -dropdown2.addItem('LADA'); +setTimeout(() => { + console.log(dropdown.value); +}, 10000); +setTimeout(() => { + console.log(dropdown.indexes); +}, 10000); //ToDo: paste the desired url; + const dropdown3 = new DropDown({ selector: '.cg-dropdown3', placeholder: 'URL', url: 'http://jsonplaceholder.typicode.com/users', + multiselect: true, }); // const dropdown3 = new DropDown({ diff --git a/src/style/main.scss b/src/style/main.scss index 634b0bc..0742c1f 100644 --- a/src/style/main.scss +++ b/src/style/main.scss @@ -21,17 +21,26 @@ body { .cg-select { padding: 14px; min-width: 200px; + max-width: 200px; height: 30px; color: #fff; display: flex; justify-content: space-between; align-items: center; + overflow: hidden; + text-overflow: ellipsis; background: #2a2f3b; cursor: pointer; border-radius: 5px; transition: 0.5s; + .selected { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + &:hover { transition: 0.5s; background: #394050; @@ -105,3 +114,28 @@ body { ::-webkit-scrollbar-thumb { background-color: #4d4d4d; } + +.multiselect { + height: 20px; + + display: flex; + align-items: center; + + li { + color: red; + border: 1px solid #4d4d4d; + } + z-index: 999; +} + +.multiselectTag { + display: flex; + text-decoration: none; + flex-direction: row; + height: 15px; + list-style-type: none; +} + +input[type='checkbox'] { + cursor: pointer; +}