grid filter
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import '../css/grid.scss';
|
||||
import { global, isPositive, isMobile, throttle, truncate, distinct } from "../../utility";
|
||||
import { global, isPositive, isMobile, throttle, truncate } from "../../utility";
|
||||
import { r } from "../../utility/lgres";
|
||||
import { createElement } from "../../functions";
|
||||
import { createIcon } from "../icon";
|
||||
@ -125,12 +125,17 @@ class Grid {
|
||||
}
|
||||
list = list.map(i => { return { values: i } });
|
||||
this.#source = list;
|
||||
this.#refreshSource(list);
|
||||
}
|
||||
|
||||
#refreshSource(list) {
|
||||
list ??= this.#source;
|
||||
if (this.#colAttrs.__filtered === true) {
|
||||
this.#currentSource = list.filter(it => {
|
||||
for (let col of this.columns) {
|
||||
const f = this.#get(col.key, 'filter');
|
||||
if (Array.isArray(f)) {
|
||||
const v = this.#getItemValue(it, col.key, col.filter);
|
||||
const v = this.#getItemValue(it.values, col.key, col.filter);
|
||||
if (f.indexOf(v) < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -375,8 +380,8 @@ class Grid {
|
||||
direction = 1;
|
||||
}
|
||||
comparer = (a, b) => {
|
||||
a = this.#getItemValue(a, col.key, col.filter);
|
||||
b = this.#getItemValue(b, col.key, col.filter);
|
||||
a = this.#getItemValue(a.values, col.key, col.filter);
|
||||
b = this.#getItemValue(b.values, col.key, col.filter);
|
||||
if (a == null && typeof b === 'number') {
|
||||
a = 0;
|
||||
} else if (typeof a === 'number' && b == null) {
|
||||
@ -936,7 +941,7 @@ class Grid {
|
||||
if (typeof filter === 'function') {
|
||||
value = filter(item);
|
||||
} else {
|
||||
value = item.values[key];
|
||||
value = item[key];
|
||||
}
|
||||
return value?.value ?? value;
|
||||
}
|
||||
@ -1005,7 +1010,8 @@ class Grid {
|
||||
document.addEventListener('mousedown', close);
|
||||
const panel = createElement('div', 'filter-panel');
|
||||
panel.addEventListener('mousedown', e => e.stopPropagation());
|
||||
const th = e.currentTarget.parentElement;
|
||||
const filter = e.currentTarget;
|
||||
const th = filter.parentElement;
|
||||
const width = th.offsetWidth;
|
||||
panel.style.top = `${th.offsetHeight}px`;
|
||||
panel.style.left = (th.offsetLeft + (width > FilterPanelWidth ? width - FilterPanelWidth : 0)) + 'px';
|
||||
@ -1044,7 +1050,18 @@ class Grid {
|
||||
} else if (typeof col.filterSource === 'function') {
|
||||
array = col.filterSource.call(this, col);
|
||||
} else {
|
||||
array = distinct(this.#currentSource, col.key, col.filter)
|
||||
const dict = Object.create(null);
|
||||
for (let item of this.#source) {
|
||||
const val = this.#getItemValue(item.values, col.key, col.filter);
|
||||
if (!Object.hasOwnProperty.call(dict, val)) {
|
||||
const v = item.values[col.key];
|
||||
dict[val] = {
|
||||
value: val,
|
||||
displayValue: typeof col.filter === 'function' ? col.filter(item.values) : v?.displayValue ?? v
|
||||
};
|
||||
}
|
||||
}
|
||||
array = Object.values(dict)
|
||||
.sort((a, b) => {
|
||||
a = a?.value ?? a;
|
||||
b = b?.value ?? b;
|
||||
@ -1062,7 +1079,7 @@ class Grid {
|
||||
};
|
||||
});
|
||||
this.#fillFilterList(col, itemlist, array, itemall);
|
||||
// TODO: check status
|
||||
itemall.querySelector('input').checked = ![...itemlist.querySelectorAll('.filter-content input')].some(i => !i.checked);
|
||||
panel.appendChild(itemlist);
|
||||
if (searchbox != null) {
|
||||
searchbox.addEventListener('input', e => {
|
||||
@ -1074,16 +1091,52 @@ class Grid {
|
||||
this.#fillFilterList(col, itemlist, items, itemall);
|
||||
});
|
||||
}
|
||||
// function
|
||||
const functions = createElement('div', 'filter-function');
|
||||
functions.append(
|
||||
createElement('button', ok => {
|
||||
ok.innerText = this.langs.ok;
|
||||
ok.addEventListener('click', () => {
|
||||
const array = this.#get(col.key, 'filterSource').filter(i => i.__checked !== false);
|
||||
if (typeof col.onFilterOk === 'function') {
|
||||
col.onFilterOk.call(this, col, array);
|
||||
} else {
|
||||
this.#set(col.key, 'filter', array.map(a => a.value));
|
||||
}
|
||||
this.#colAttrs.__filtered = true;
|
||||
this.#refreshSource();
|
||||
if (typeof col.onFiltered === 'function') {
|
||||
col.onFiltered.call(this, col);
|
||||
}
|
||||
filter.classList.add('active');
|
||||
this.#onCloseFilter();
|
||||
});
|
||||
}),
|
||||
createElement('button', reset => {
|
||||
reset.innerText = this.langs.reset;
|
||||
reset.addEventListener('click', () => {
|
||||
this.#set(col.key, 'filter', null);
|
||||
// TODO: change __filtered
|
||||
this.#refreshSource();
|
||||
if (typeof col.onFiltered === 'function') {
|
||||
col.onFiltered.call(this, col);
|
||||
}
|
||||
filter.classList.remove('active');
|
||||
this.#onCloseFilter();
|
||||
});
|
||||
})
|
||||
);
|
||||
panel.appendChild(functions);
|
||||
|
||||
this.#el.appendChild(panel);
|
||||
setTimeout(() => panel.classList.add('active'), 0);
|
||||
this.#colAttrs.__filtering = e.currentTarget;
|
||||
e.currentTarget.classList.add('hover');
|
||||
this.#colAttrs.__filtering = filter;
|
||||
filter.classList.add('hover');
|
||||
}
|
||||
|
||||
#fillFilterList(col, list, array, all) {
|
||||
list.querySelector('.filter-holder').remove();
|
||||
list.querySelector('.filter-content').remove();
|
||||
list.querySelector('.filter-holder')?.remove();
|
||||
list.querySelector('.filter-content')?.remove();
|
||||
const rowHeight = this.filterRowHeight;
|
||||
const height = array.length * rowHeight;
|
||||
this.#set(col.key, 'filterHeight', height);
|
||||
@ -1094,17 +1147,28 @@ class Grid {
|
||||
this.#set(col.key, 'filterSource', array);
|
||||
const filter = this.#get(col.key, 'filter');
|
||||
for (let item of array) {
|
||||
item.__checked = !Array.isArray(filter) || filter.indexOf(item.value ?? item);
|
||||
item.__checked = !Array.isArray(filter) || filter.indexOf(item.value ?? item) >= 0;
|
||||
}
|
||||
if (array.length > 12) {
|
||||
array = array.slice(0, 12);
|
||||
}
|
||||
this.#doFillFilterList(col, content, array, all);
|
||||
this.#doFillFilterList(content, array, all);
|
||||
list.append(holder, content);
|
||||
}
|
||||
|
||||
#doFillFilterList(col, content, array, all) {
|
||||
|
||||
#doFillFilterList(content, array, all) {
|
||||
for (let item of array) {
|
||||
const div = createElement('div', 'filter-item');
|
||||
div.appendChild(createCheckbox({
|
||||
checked: item.__checked,
|
||||
label: item?.displayValue ?? item,
|
||||
onchange: e => {
|
||||
item.__checked = e.target.checked;
|
||||
all.querySelector('input').checked = ![...content.querySelectorAll('input')].some(i => !i.checked);
|
||||
}
|
||||
}));
|
||||
content.appendChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
#onFilterScroll(col, list, top) {
|
||||
@ -1132,7 +1196,7 @@ class Grid {
|
||||
}
|
||||
const content = list.querySelector('.filter-content');
|
||||
content.replaceChildren();
|
||||
this.#doFillFilterList(col, content, array, list.querySelector('.filter-all>input'));
|
||||
this.#doFillFilterList(content, array, list.querySelector('.filter-all>input'));
|
||||
content.style.top = `${top + rowHeight}px`;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user