Merge pull request #6 from apuc/refactoring-core

Refactoring core cg-select
This commit is contained in:
MaxOvs19 2022-10-12 10:40:23 +03:00 committed by GitHub
commit e00ac0d1a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 253 additions and 228 deletions

View File

@ -1,3 +1,6 @@
import { customStyles, createSelected } from './components/utils';
import { createBreadcrumb } from './components/create-element';
export class DropDown {
#element;
#list;
@ -5,7 +8,6 @@ export class DropDown {
#caret;
#items;
#selectedItems;
#id = [];
#indexes = [];
get value() {
@ -23,6 +25,27 @@ export class DropDown {
}
addItem(item) {
if (!item) {
return false;
}
const random = Math.random().toString(36).substring(2, 10);
const index = this.#items.length;
if (typeof item === 'object') {
item = {
id: item.id,
title: item.title,
value: item.value,
};
} else {
item = {
id: random,
title: item,
value: index,
};
}
this.#items.push(item);
this.#render();
}
@ -43,7 +66,11 @@ export class DropDown {
selectIndex(index) {
const options = this.#element.querySelectorAll('.list__item');
let select = options[index].innerText;
if (index > options.length) {
return;
}
const select = options[index].innerText;
this.#render(select);
}
@ -54,6 +81,8 @@ export class DropDown {
#init(options) {
this.#options = options;
const { items, multiselect, url } = this.#options;
const elem = document.querySelector(options.selector);
if (!elem) {
@ -66,119 +95,110 @@ export class DropDown {
this.#open();
});
this.#list = this.#element.querySelector('.list');
this.#caret = this.#element.querySelector('.caret');
const { items, multiselect } = this.#options;
this.#items = items;
this.#items = [];
if (multiselect) {
this.#selectedItems = [];
}
if (!items && url) {
this.#renderUrl();
return;
}
items.forEach((dataItem, index) => {
const random = Math.random().toString(36).substring(2, 10);
let item = {};
if (this.#checkItemStruct(dataItem)) {
item = {
id: dataItem.id,
title: dataItem.title,
value: index,
};
} else {
item = {
id: random,
title: dataItem,
value: index,
};
}
this.#items.push(item);
});
}
#initSelected(select) {
const { styles } = this.#options;
const { styles, selected, placeholder } = this.#options;
if (this.#options.selected) {
this.#createSelected(this.#options.selected);
if (selected) {
createSelected(this.#element, selected);
} else if (placeholder) {
createSelected(this.#element, placeholder);
} else {
this.#createSelected('Select...');
createSelected(this.#element, 'Select...');
}
if (!this.#options.selected && this.#options.placeholder) {
this.#createSelected(this.#options.placeholder);
}
if ((styles && this.#options.placeholder) || (styles && this.#options.selected)) {
this.#createSelected(this.#options.placeholder);
this.#customStyles(styles);
} else {
this.#customStyles(styles);
if (styles) {
customStyles(this.#element, styles);
}
if (select) {
this.#createSelected(select);
createSelected(this.#element, select, styles);
}
}
#render(select) {
const { items, styles, url, multiselect, multiselectTag } = this.#options;
const { styles, multiselect } = this.#options;
if (select || (select && styles)) {
this.#initSelected(select);
this.#customStyles(styles);
customStyles(this.#element, styles);
} else {
this.#initSelected();
}
const ul = document.createElement('ul');
const ulList = document.createElement('ul');
if (styles) {
const { list } = styles;
ul.classList.add('list');
if (ul && list) {
if (ulList && list) {
Object.entries(list).forEach(([key, value]) => {
ul.style[key] = value;
ulList.style[key] = value;
});
}
this.#element.appendChild(ul);
} else {
ul.classList.add('list');
this.#element.appendChild(ul);
}
if (!items && url) {
this.#renderUrl();
ulList.classList.add('list');
this.#element.appendChild(ulList);
return;
}
this.#items.forEach((dataItem) => {
const liItem = document.createElement('li');
items.forEach((item, index) => {
const li = document.createElement('li');
let text = '';
let id = '';
li.classList.add('list__item');
if (this.#checkItemStruct(item)) {
text = item.title;
id = item.id;
} else {
text = item;
}
liItem.classList.add('list__item');
if (multiselect) {
const checkBox = document.createElement('input');
checkBox.type = 'checkbox';
checkBox.setAttribute('id', `chbox-${dataItem.id}`);
if (multiselectTag) {
if (this.#checkItemStruct(item)) {
checkBox.setAttribute('id', `chbox-${item.id}`);
} else {
checkBox.setAttribute('id', `chbox-${index}`);
}
}
li.appendChild(checkBox);
liItem.appendChild(checkBox);
}
let textNode = document.createTextNode(text);
let textNode = document.createTextNode(dataItem.title);
li.appendChild(textNode);
ul.appendChild(li);
liItem.appendChild(textNode);
ulList.appendChild(liItem);
});
this.#addOptionsBehaviour();
}
async #renderUrl() {
const { url } = this.#options;
const { url, items, multiselect } = this.#options;
if (this.#items) {
if (items) {
return;
}
@ -187,30 +207,30 @@ export class DropDown {
}
const response = await fetch(url);
const data = await response.json();
this.#items = [];
const dataUrl = await response.json();
data.forEach((dataItem, index) => {
dataUrl.forEach((dataItem, index) => {
const item = {
id: dataItem.phone,
title: dataItem.name,
value: index,
};
const ul = this.#element.querySelector('.list');
const li = document.createElement('li');
const text = document.createTextNode(item.title);
const ulUrl = this.#element.querySelector('.list');
const liUrl = document.createElement('li');
const textUrl = document.createTextNode(item.title);
const checkBox = document.createElement('input');
checkBox.type = 'checkbox';
if (multiselect) {
const checkBox = document.createElement('input');
checkBox.type = 'checkbox';
checkBox.setAttribute('id', `chbox-${item.id}`);
checkBox.setAttribute('id', `chbox-${item.id}`);
liUrl.appendChild(checkBox);
}
li.appendChild(checkBox);
li.classList.add('list__item');
li.appendChild(text);
ul.appendChild(li);
liUrl.classList.add('list__item');
liUrl.appendChild(textUrl);
ulUrl.appendChild(liUrl);
this.#items.push(item);
});
@ -232,16 +252,16 @@ export class DropDown {
}
#addOptionsBehaviour() {
const { multiselect, placeholder, multiselectTag } = this.#options;
const { multiselect, placeholder, selected, multiselectTag } = this.#options;
const options = this.#element.querySelectorAll('.list__item');
const selected = this.#element.querySelector('.selected');
const select = this.#element.querySelector('.selected');
const ul = document.createElement('ul');
if (multiselect) {
ul.classList.add('multiselect-tag');
selected.classList.add('overflow-hidden');
select.classList.add('overflow-hidden');
}
options.forEach((option, index) => {
@ -260,64 +280,56 @@ export class DropDown {
}
const checkIndex = this.#indexes.indexOf(index);
let value = '';
let id = '';
if (checkIndex === -1) {
this.#indexes.push(index);
if (this.#checkItemStruct(item)) {
this.#selectedItems.push(item.title);
value = item.title;
id = item.id;
} else {
this.#selectedItems.push(item);
value = item;
}
selected.innerText = '';
select.innerText = '';
if (multiselectTag) {
selected.appendChild(ul);
this.#selectedItems.push(item);
select.appendChild(ul);
if (this.#checkItemStruct(item)) {
ul.appendChild(this.#createBreadcrumb(value, index, id));
} else {
ul.appendChild(this.#createBreadcrumb(value, index));
}
const data = {
option: this.#options,
element: this.#element,
indexes: this.#indexes,
selectedItems: this.#selectedItems,
};
ul.appendChild(createBreadcrumb(data, item.title, index, item.id));
} else {
selected.innerText = this.#selectedItems;
this.#selectedItems.push(item.title);
select.innerText = this.#selectedItems;
}
} else {
if (multiselectTag) {
const tagItem = document.getElementById(`tag-${index}`);
ul.removeChild(tagItem);
this.#indexes.splice(checkIndex, 1);
this.#selectedItems.splice(checkIndex, 1);
} else {
this.#indexes.splice(checkIndex, 1);
this.#selectedItems.splice(checkIndex, 1);
}
this.#indexes.splice(checkIndex, 1);
this.#selectedItems.splice(checkIndex, 1);
}
if (!this.#selectedItems.length) {
selected.innerText = placeholder;
if (placeholder) {
select.innerText = placeholder;
} else if (selected) {
select.innerText = selected;
} else {
select.innerText = 'Select...';
}
} else {
if (multiselectTag) {
selected.appendChild(ul);
select.appendChild(ul);
} else {
selected.innerText = this.#selectedItems;
select.innerText = this.#selectedItems;
}
}
}
} else {
if (this.#checkItemStruct(item)) {
selected.innerText = item.title;
} else {
selected.innerText = item;
}
select.innerText = item.title;
this.#selectedItems = item;
options.forEach((option) => {
@ -329,57 +341,6 @@ export class DropDown {
});
}
#createBreadcrumb(value, index, id) {
const { placeholder } = this.#options;
const selected = this.#element.querySelector('.selected');
const li = document.createElement('li');
const text = document.createTextNode(value);
const svg = 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');
path1.setAttribute('d', 'M3,7 L7,3');
path2.setAttribute('d', 'M3,3 L7,7');
li.setAttribute('id', `tag-${index}`);
svg.classList.add('svg-icon');
svg.appendChild(path1);
svg.appendChild(path2);
li.appendChild(text);
li.appendChild(svg);
svg.addEventListener('click', (event) => {
event.stopPropagation();
const deleteIcon = this.#indexes.indexOf(index);
this.#indexes.splice(deleteIcon, 1);
this.#selectedItems.splice(deleteIcon, 1);
let checkBox = '';
if (id) {
checkBox = document.getElementById(`chbox-${id}`);
} else {
checkBox = document.getElementById(`chbox-${index}`);
}
checkBox.checked = false;
checkBox.parentElement.classList.remove('active');
if (!this.#selectedItems.length) {
selected.innerText = placeholder;
}
li.parentElement.removeChild(li);
});
return li;
}
#initEvent() {
const { event } = this.#options;
if (!event) {
@ -387,8 +348,6 @@ export class DropDown {
}
if (event) {
let list = this.#element.querySelectorAll('.list');
if (event === 'mouseenter') {
this.#element.addEventListener(event, () => {
this.#open();
@ -401,60 +360,6 @@ export class DropDown {
}
}
#customStyles(styles) {
if (!styles) {
return;
}
const { head, caret, placeholder } = styles;
const select = this.#element.querySelector('.cg-select');
const crt = this.#element.querySelector('.caret');
const placeh = this.#element.querySelector('.selected');
if (head) {
Object.entries(head).forEach(([key, value]) => {
select.style[key] = value;
});
}
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;
});
}
}
}
#createSelected(content, styles) {
if (content) {
this.#element.innerHTML = `
<div class="cg-select">
<p class="selected">${content}</p>
<div class="caret"></div>
</div>
`;
}
if (styles) {
this.#customStyles(styles);
this.#element.innerHTML = `
<div class="cg-select" style = "${styles}">
<span class="selected" style = "${styles}">${content}</span>
<div class="caret" style = "${styles}"></div>
</div>
`;
}
}
#checkItemStruct(item) {
if (item && typeof item !== 'object') {
return false;

View File

@ -0,0 +1,51 @@
export function createBreadcrumb(data, title, index, id) {
const { element, option, indexes, selectedItems } = data;
const { placeholder } = option;
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 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');
path1.setAttribute('d', 'M3,7 L7,3');
path2.setAttribute('d', 'M3,3 L7,7');
li.setAttribute('id', `tag-${index}`);
svg.classList.add('svg-icon');
svg.appendChild(path1);
svg.appendChild(path2);
li.appendChild(text);
li.appendChild(svg);
svg.addEventListener('click', (event) => {
event.stopPropagation();
const deleteIcon = indexes.indexOf(index);
indexes.splice(deleteIcon, 1);
selectedItems.splice(deleteIcon, 1);
let checkBox = '';
if (id) {
checkBox = document.getElementById(`chbox-${id}`);
} else {
checkBox = document.getElementById(`chbox-${index}`);
}
checkBox.checked = false;
checkBox.parentElement.classList.remove('active');
if (!selectedItems.length) {
selected.innerText = placeholder;
}
li.parentElement.removeChild(li);
});
return li;
}

53
src/components/utils.js Normal file
View File

@ -0,0 +1,53 @@
export function createSelected(element, content, styles) {
if (content) {
element.innerHTML = `
<div class="cg-select">
<p class="selected">${content}</p>
<div class="caret"></div>
</div>
`;
}
if (styles) {
customStyles(element, styles);
element.innerHTML = `
<div class="cg-select" style = "${styles}">
<span class="selected" style = "${styles}">${content}</span>
<div class="caret" style = "${styles}"></div>
</div>
`;
}
}
export function customStyles(element, styles) {
if (!styles) {
return;
}
const { head, caret, placeholder } = styles;
const select = element.querySelector('.cg-select');
const crt = element.querySelector('.caret');
const placeh = element.querySelector('.selected');
if (head) {
Object.entries(head).forEach(([key, value]) => {
select.style[key] = value;
});
}
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;
});
}
}
}

View File

@ -4,54 +4,70 @@ const dropdown = new DropDown({
selector: '.cg-dropdown',
placeholder: 'Выберите авто',
items: ['BMW', 'Opel', 'Mersedes', 'MAN', 'max'],
styles: {
head: {
background: 'red',
},
},
multiselect: true,
multiselectTag: true,
});
dropdown.addItem('ZAZ');
dropdown.addItem('LADA');
// dropdown.addItem('BMW');
dropdown.addItem('Kamaz 258');
dropdown.addItem('BMW');
const dropdown2 = new DropDown({
selector: '.cg-dropdown2',
placeholder: 'SELECT CAR',
items: [
{
id: 'addaw21',
title: 'BMW',
value: '1',
value: 1,
},
{
id: '2414q',
title: 'Opel',
value: '2',
value: 2,
},
{
id: '24qwds',
title: 'Kamaz 258',
value: '3',
value: 3,
},
{
id: '28wds',
title: 'MAN',
value: '4',
value: 4,
},
{
id: '28qwds',
title: 'BOOT',
value: '5',
value: 5,
},
],
multiselect: true,
multiselectTag: true,
event: 'mouseenter',
// multiselectTag: true,
});
dropdown2.addItem('LADA');
//ToDo: paste the desired url;
const dropdown3 = new DropDown({
selector: '.cg-dropdown3',
placeholder: 'URL',
url: 'http://jsonplaceholder.typicode.com/users',
styles: {
head: {
background: 'red',
},
},
multiselect: true,
multiselectTag: true,
});