add dropdown document

This commit is contained in:
2023-04-01 14:02:11 +08:00
parent 067d6252b2
commit c3a9fa7ba3
7 changed files with 283 additions and 124 deletions

View File

@ -62,6 +62,23 @@ function selectItems(label, itemlist, htmlkey, textkey) {
}
}
function filterSource(searchkeys, textkey, key, source) {
if (!Array.isArray(searchkeys) || searchkeys.length === 0) {
searchkeys = [textkey];
}
if (key.length > 0) {
source = source.filter(it => {
for (let k of searchkeys) {
if (contains(it[k].toLowerCase(), key)) {
return true;
}
}
return false;
});
}
return source;
}
class Dropdown {
#options;
@ -120,29 +137,16 @@ class Dropdown {
// label or input
let label;
let searchkeys = options.searchkeys;
if (!Array.isArray(searchkeys) || searchkeys.length === 0) {
searchkeys = [options.textkey];
}
if (options.input) {
label = document.createElement('input');
label.className = 'dropdown-text';
label.setAttribute('type', 'text');
options.placeholder && label.setAttribute('placeholder', options.placeholder);
isPositive(options.maxlength) && label.setAttribute('maxlength', options.maxlength);
isPositive(options.tabindex) && label.setAttribute('tabindex', options.tabindex);
label.addEventListener('input', e => {
const key = e.target.value.toLowerCase();
let source = this.source;
if (key.length > 0) {
source = source.filter(it => {
for (let k of searchkeys) {
if (contains(it[k].toLowerCase(), key)) {
return true;
}
}
return false;
});
}
const source = filterSource(options.searchkeys, options.textkey, key, this.source);
this.#filllist(source);
this.#container.classList.add('active');
});
@ -217,7 +221,7 @@ class Dropdown {
get selectedlist() { return this.#selectedList || [] }
select(selected, init) {
select(selected, silence) {
if (this.#lastSelected === selected) {
return false;
}
@ -250,12 +254,12 @@ class Dropdown {
}
}
this.#selected = item;
if (!init && typeof this.onselected === 'function') {
if (!silence && typeof this.onselected === 'function') {
this.onselected(item);
}
}
selectlist(selectedlist, init) {
selectlist(selectedlist, silence) {
const source = this.source;
const valuekey = this.#options.valuekey;
const textkey = this.#options.textkey;
@ -276,7 +280,7 @@ class Dropdown {
}
selectItems(this.#label, itemlist, htmlkey, textkey);
this.#selectedList = itemlist;
if (!init && typeof this.onselectedlist === 'function') {
if (!silence && typeof this.onselectedlist === 'function') {
this.onselectedlist(itemlist);
}
}
@ -293,10 +297,6 @@ class Dropdown {
panel.className = 'dropdown-panel';
// search box
if (!options.input && options.search) {
let searchkeys = options.searchkeys;
if (!Array.isArray(searchkeys) || searchkeys.length === 0) {
searchkeys = [textkey];
}
const search = document.createElement('div');
search.className = 'dropdown-search';
const input = document.createElement('input');
@ -305,17 +305,7 @@ class Dropdown {
!nullOrEmpty(options.searchplaceholder) && input.setAttribute('placeholder', options.searchplaceholder);
input.addEventListener('input', e => {
const key = e.target.value.toLowerCase();
let source = this.source;
if (key.length > 0) {
source = source.filter(it => {
for (let k of searchkeys) {
if (contains(it[k].toLowerCase(), key)) {
return true;
}
}
return false;
});
}
const source = filterSource(options.searchkeys, options.textkey, key, this.source);
this.#filllist(source);
})
search.appendChild(input);
@ -345,32 +335,29 @@ class Dropdown {
this.#wrapper.appendChild(panel);
}
if (flag) {
let source = this.source;
if (!options.input && options.search) {
const search = panel.querySelector('.dropdown-search > input');
if (!nullOrEmpty(search?.value)) {
source = filterSource(options.searchkeys, options.textkey, search.value, source);
}
}
this.#filllist(source);
// slide direction
if (!options.slidefixed) {
let parent = options.parent ?? document.body;
const height = panel.offsetHeight;
if (this.#wrapper.offsetTop - parent.offsetTop + DropdownTitleHeight + height >= parent.offsetHeight) {
panel.style.marginTop = -height - DropdownTitleHeight - 2;
let p = this.#wrapper;
let top = p.offsetTop;
while ((p = p.parentElement) != null && p !== parent) {
top -= p.scrollTop;
}
if (top - parent.offsetTop + DropdownTitleHeight + panel.offsetHeight >= parent.offsetHeight) {
panel.classList.add('slide-up');
} else {
panel.style.marginTop = null;
panel.classList.remove('slide-up');
}
}
panel.classList.add('active');
// search input
// const inputSearch = panel.querySelector('.dropdown-search > input');
// if (!nullOrEmpty(inputSearch.value)) {
// const event = new InputEvent('type');
// inputSearch.dispatchEvent(event);
// }
if (!options.input && options.search) {
const search = panel.querySelector('.dropdown-search > input');
if (!nullOrEmpty(search?.value)) {
search.dispatchEvent(new InputEvent('type'));
return;
}
}
this.#filllist(this.source);
} else {
panel.classList.remove('active');
}
@ -489,15 +476,13 @@ class Dropdown {
dom ??= document.body;
const selects = dom.querySelectorAll('select');
for (let sel of selects) {
let selected;
const source = [...sel.children].map(it => {
if (it.selected) {
selected = it.value;
}
return { value: it.value, text: it.innerText }
});
const drop = new Dropdown({
selected
selected: sel.value,
disabled: sel.disabled,
tabindex: sel.tabIndex
});
drop.source = source;
sel.parentElement.replaceChild(drop.create(), sel);