sync
This commit is contained in:
@ -3,6 +3,10 @@ import { createElement } from "../functions";
|
||||
import { createIcon } from "./icon";
|
||||
|
||||
function fillCheckbox(container, type = 'fa-regular', label, tabindex = -1, charactor = 'check', title) {
|
||||
const checkIcon = createIcon(type, charactor);
|
||||
checkIcon.classList.add('ui-check-icon');
|
||||
const indeterminateIcon = createIcon(type, 'grip-lines');
|
||||
indeterminateIcon.classList.add('ui-indeterminate-icon')
|
||||
container.appendChild(
|
||||
createElement('layer', layer => {
|
||||
layer.className = 'ui-check-inner';
|
||||
@ -18,7 +22,7 @@ function fillCheckbox(container, type = 'fa-regular', label, tabindex = -1, char
|
||||
if (tabindex >= 0) {
|
||||
layer.tabIndex = tabindex;
|
||||
}
|
||||
}, createIcon(type, charactor))
|
||||
}, checkIcon, indeterminateIcon)
|
||||
);
|
||||
if (label instanceof Element) {
|
||||
container.appendChild(label);
|
||||
@ -68,6 +72,9 @@ export function createCheckbox(opts = {}) {
|
||||
if (opts.checked === true) {
|
||||
input.checked = true;
|
||||
}
|
||||
if (opts.indeterminate === true) {
|
||||
input.indeterminate = true;
|
||||
}
|
||||
if (opts.enabled === false) {
|
||||
input.disabled = true;
|
||||
}
|
||||
|
@ -185,9 +185,20 @@ $listMaxHeight: 210px;
|
||||
background-color: var(--hover-bg-color);
|
||||
}
|
||||
|
||||
>.ui-check-wrapper {
|
||||
height: $dropItemHeight;
|
||||
>.li-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
>.ui-expandor {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
>.ui-check-wrapper {
|
||||
height: $dropItemHeight;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,22 @@
|
||||
border-color: var(--link-color);
|
||||
background-color: var(--link-color);
|
||||
|
||||
>svg {
|
||||
>.ui-check-icon {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:indeterminate+.ui-check-inner {
|
||||
border-color: var(--secondary-color);
|
||||
background-color: var(--secondary-color);
|
||||
|
||||
>.ui-check-icon {
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
>.ui-indeterminate-icon {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -178,6 +178,7 @@ export function getFormatter(date, utc) {
|
||||
* @param {Date | number | string} date - 需要格式化的日期值,支持的格式如下:
|
||||
*
|
||||
* * `"2024-01-26"`
|
||||
* * `"2024/1/26"`
|
||||
* * `"2024-01-26T00:00:00"`
|
||||
* * `"1/26/2024"`
|
||||
* * `"638418240000000000"`
|
||||
@ -214,7 +215,7 @@ export function formatDate(date, formatter) {
|
||||
if (isNaN(date)) {
|
||||
let e = /^(\d{4})-(\d{2})-(\d{2})/.exec(date);
|
||||
if (e == null) {
|
||||
e = /^(\d{4})\/(\d{2})\/(\d{2})/.exec(date);
|
||||
e = /^(\d{4})\/(\d{1,2})\/(\d{1,2})/.exec(date);
|
||||
}
|
||||
if (e != null) {
|
||||
date = new Date(e[1], parseInt(e[2]) - 1, e[3]);
|
||||
|
@ -302,7 +302,14 @@ export class Dropdown {
|
||||
if (!Array.isArray(list)) {
|
||||
return;
|
||||
}
|
||||
this._var.source = list;
|
||||
const valuekey = this._var.options.valueKey;
|
||||
function reduceItems(list, id, level = 0) {
|
||||
if (!Array.isArray(list)) {
|
||||
return [];
|
||||
}
|
||||
return list.reduce((array, item) => [...array, { __p: id, __level: level, ...item }, ...reduceItems(item.children, item[valuekey], level + 1)], []);
|
||||
}
|
||||
this._var.source = reduceItems(list);
|
||||
if (this._expanded) {
|
||||
setTimeout(() => this._dropdown(), 120);
|
||||
}
|
||||
@ -422,6 +429,7 @@ export class Dropdown {
|
||||
const search = createElement('div', 'ui-drop-search');
|
||||
const input = createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'ui-input';
|
||||
isPositive(options.tabIndex) && input.setAttribute('tabindex', options.tabIndex);
|
||||
!nullOrEmpty(options.searchPlaceholder) && input.setAttribute('placeholder', options.searchPlaceholder);
|
||||
input.addEventListener('input', e => {
|
||||
@ -579,7 +587,14 @@ export class Dropdown {
|
||||
}
|
||||
if (multiselect) {
|
||||
const selected = selectedlist.some(s => String(getValue(s, valuekey, textkey)) === val);
|
||||
item.__checked = allchecked || selected;
|
||||
if (allchecked || selected) {
|
||||
item.__checked = 1;
|
||||
} else {
|
||||
const indeterminate = selectedlist.some(s => this._contains(String(getValue(s, valuekey, textkey)), item, valuekey, textkey));
|
||||
if (indeterminate) {
|
||||
item.__checked = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (source.length > 20) {
|
||||
@ -592,6 +607,20 @@ export class Dropdown {
|
||||
}
|
||||
}
|
||||
|
||||
_contains(it, item, valuekey, textkey) {
|
||||
if (item.children?.length > 0) {
|
||||
for (let t of item.children) {
|
||||
if (it === getValue(t, valuekey, textkey)) {
|
||||
return true;
|
||||
}
|
||||
if (this._contains(it, t, valuekey, textkey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_dofilllist(content, array) {
|
||||
const multiselect = this.multiSelect;
|
||||
const valuekey = this._var.options.valueKey;
|
||||
@ -608,6 +637,18 @@ export class Dropdown {
|
||||
const li = createElement('li');
|
||||
li.dataset.value = val;
|
||||
li.title = item[textkey];
|
||||
if (item.__level > 0) {
|
||||
li.style.marginLeft = `${item.__level * 24}px`;
|
||||
}
|
||||
const wrapper = createElement('span', 'li-wrapper',
|
||||
createElement('span', span => {
|
||||
// events
|
||||
span.className = 'ui-expandor';
|
||||
},
|
||||
createIcon('fa-light', 'caret-down')
|
||||
)
|
||||
);
|
||||
li.appendChild(wrapper);
|
||||
let label;
|
||||
let html;
|
||||
if (typeof template === 'function') {
|
||||
@ -628,20 +669,21 @@ export class Dropdown {
|
||||
}
|
||||
const box = createCheckbox({
|
||||
label,
|
||||
checked: item.__checked,
|
||||
checked: item.__checked === 1,
|
||||
indeterminate: item.__checked === 2,
|
||||
customAttributes: {
|
||||
'class': 'dataitem',
|
||||
'data-value': val
|
||||
},
|
||||
onchange: e => this._triggerselect(e.target, item)
|
||||
});
|
||||
li.appendChild(box);
|
||||
wrapper.appendChild(box);
|
||||
} else {
|
||||
if (label == null) {
|
||||
li.innerText = item[textkey];
|
||||
} else {
|
||||
li.appendChild(label);
|
||||
label = createElement('span');
|
||||
label.innerHTML = item[textkey];
|
||||
}
|
||||
wrapper.appendChild(label);
|
||||
if (selected != null && String(selected[valuekey]) === val) {
|
||||
scrolled = DropdownItemHeight * i;
|
||||
li.classList.add('selected');
|
||||
@ -664,7 +706,7 @@ export class Dropdown {
|
||||
boxes.forEach(box => box.checked = allchecked);
|
||||
list = [];
|
||||
} else {
|
||||
item.__checked = checkbox.checked;
|
||||
item.__checked = checkbox.indeterminate ? 2 : checkbox.checked ? 1 : 0;
|
||||
const all = this._var.container.querySelector('input[isall="1"]');
|
||||
if (checkbox.checked) {
|
||||
const source = this.source;
|
||||
|
@ -1431,12 +1431,21 @@ export class Grid {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
grid.addEventListener('mousedown', e => {
|
||||
grid.addEventListener('mousedown', async e => {
|
||||
if (e.target === this._var.el) {
|
||||
if (e.offsetX < 0 || e.offsetX > e.target.clientWidth || e.offsetY < 0 || e.offsetY > e.target.clientHeight) {
|
||||
// except scroll bars
|
||||
return;
|
||||
}
|
||||
if (typeof this.willSelect === 'function') {
|
||||
let result = this.willSelect(-1, -1);
|
||||
if (result instanceof Promise) {
|
||||
result = await result;
|
||||
}
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// cancel selections
|
||||
const selectedIndexes = this._var.selectedIndexes;
|
||||
if (selectedIndexes?.length > 0) {
|
||||
@ -1525,7 +1534,7 @@ export class Grid {
|
||||
holder.classList.remove('active');
|
||||
this._clearHolder(holder);
|
||||
}
|
||||
return this._onRowClicked(e, row, col);
|
||||
this._onRowClicked(e, row, col);
|
||||
});
|
||||
holder.addEventListener('dblclick', e => this._onRowDblClicked(e));
|
||||
wrapper.appendChild(holder);
|
||||
@ -2107,6 +2116,7 @@ export class Grid {
|
||||
// FIXME: 清除缓存会导致选中状态下动态数据源下拉列表显示为空
|
||||
// delete it.source;
|
||||
it.values = item;
|
||||
this._var.colAttrs.__filtered = false;
|
||||
if (this.sortArray?.length > 0) {
|
||||
this.sort();
|
||||
} else if (this.sortIndex >= 0) {
|
||||
@ -2148,6 +2158,7 @@ export class Grid {
|
||||
this._var.source.push(newIt);
|
||||
}
|
||||
}
|
||||
this._var.colAttrs.__filtered = false;
|
||||
if (this.sortArray?.length > 0) {
|
||||
this.sort(true);
|
||||
} else if (this.sortIndex >= 0) {
|
||||
@ -2195,6 +2206,7 @@ export class Grid {
|
||||
this._var.source.push(...items);
|
||||
}
|
||||
}
|
||||
this._var.colAttrs.__filtered = false;
|
||||
if (this.sortArray?.length > 0) {
|
||||
this.sort(true);
|
||||
} else if (this.sortIndex >= 0) {
|
||||
@ -3926,6 +3938,8 @@ export class Grid {
|
||||
return String(displayValue).toLowerCase().includes(key);
|
||||
});
|
||||
this._fillFilterList(col, itemlist, items, itemall);
|
||||
this._set(col.key, 'filterTop', -1);
|
||||
itemlist.dispatchEvent(new Event('scroll'));
|
||||
});
|
||||
}
|
||||
// function
|
||||
@ -4405,12 +4419,9 @@ export class Grid {
|
||||
* @param {number} index
|
||||
* @param {number} colIndex
|
||||
*/
|
||||
_onRowClicked(e, index, colIndex) {
|
||||
_afterRowChanged(e, index, colIndex) {
|
||||
const startIndex = this._var.startIndex;
|
||||
const selectedIndex = startIndex + index;
|
||||
if (typeof this.willSelect === 'function' && !this.willSelect(selectedIndex, colIndex)) {
|
||||
return;
|
||||
}
|
||||
// multi-select
|
||||
let flag = false;
|
||||
const selectedIndexes = this._var.selectedIndexes;
|
||||
@ -4471,6 +4482,26 @@ export class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
* @param {number} index
|
||||
* @param {number} colIndex
|
||||
*/
|
||||
async _onRowClicked(e, index, colIndex) {
|
||||
if (typeof this.willSelect === 'function') {
|
||||
const selectedIndex = this._var.startIndex + index;
|
||||
let result = this.willSelect(selectedIndex, colIndex);
|
||||
if (result instanceof Promise) {
|
||||
result = await result;
|
||||
}
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._afterRowChanged(e, index, colIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
|
Reference in New Issue
Block a user