fixed: column drag issue.
optimized: documentation.
This commit is contained in:
@ -17,7 +17,7 @@ const ColumnChangedType = {
|
||||
const RefreshInterval = isMobile() ? 32 : 0;
|
||||
const HoverInternal = 200;
|
||||
const RedumCount = 4;
|
||||
const MiniDragOffset = 4;
|
||||
const MiniDragOffset = 10;
|
||||
const MiniColumnWidth = 50;
|
||||
const FilterPanelWidth = 200;
|
||||
|
||||
@ -29,15 +29,6 @@ function getClientX(e) {
|
||||
return cx ?? e.clientX;
|
||||
}
|
||||
|
||||
function getOffsetLeftFromWindow(element) {
|
||||
let left = 0;
|
||||
while (element != null) {
|
||||
left += element.offsetLeft;
|
||||
element = element.offsetParent;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
function indexOfParent(target) {
|
||||
// return [...target.parentElement.children].indexOf(target);
|
||||
return Array.prototype.indexOf.call(target.parentElement.children, target);
|
||||
@ -127,7 +118,8 @@ export class Grid {
|
||||
this.langs = {
|
||||
all: r('allItem', '( All )'),
|
||||
ok: r('ok', 'OK'),
|
||||
reset: r('reset', 'Reset')
|
||||
reset: r('reset', 'Reset'),
|
||||
null: r('null', '( Null )')
|
||||
};
|
||||
}
|
||||
|
||||
@ -190,7 +182,7 @@ export class Grid {
|
||||
this._var.currentSource = list.filter(it => {
|
||||
for (let col of this.columns) {
|
||||
if (Array.isArray(col.filterValues)) {
|
||||
const v = this._getItemValue(it.values, col.key, col.filter);
|
||||
const v = this._getItemProp(it.values, false, col);
|
||||
if (col.filterValues.indexOf(v) < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -485,8 +477,8 @@ export class Grid {
|
||||
direction = 1;
|
||||
}
|
||||
comparer = (a, b) => {
|
||||
a = this._getItemValue(a.values, col.key, col.filter);
|
||||
b = this._getItemValue(b.values, col.key, col.filter);
|
||||
a = this._getItemProp(a.values, true, col);
|
||||
b = this._getItemProp(b.values, true, col);
|
||||
if (a == null && typeof b === 'number') {
|
||||
a = 0;
|
||||
} else if (typeof a === 'number' && b == null) {
|
||||
@ -533,7 +525,7 @@ export class Grid {
|
||||
let left = 0;
|
||||
for (let col of this.columns) {
|
||||
if (col.visible === false) {
|
||||
const hidden = createElement('th');
|
||||
const hidden = createElement('th', 'column');
|
||||
hidden.style.display = 'none';
|
||||
if (col.sortable !== false) {
|
||||
hidden.dataset.key = col.key;
|
||||
@ -544,7 +536,17 @@ export class Grid {
|
||||
}
|
||||
// style
|
||||
const isCheckbox = Grid.ColumnTypes.isCheckbox(col.type);
|
||||
if (col.width > 0) {
|
||||
let type = this._var.colTypes[col.key];
|
||||
if (type == null) {
|
||||
if (isNaN(col.type)) {
|
||||
type = col.type;
|
||||
} else {
|
||||
type = ColumnTypes[col.type];
|
||||
}
|
||||
type ??= GridColumn;
|
||||
this._var.colTypes[col.key] = type;
|
||||
}
|
||||
if (col.width > 0 || typeof type.createCaption === 'function') {
|
||||
// col.autoResize = false;
|
||||
} else {
|
||||
this._set(col.key, 'autoResize', true);
|
||||
@ -600,12 +602,19 @@ export class Grid {
|
||||
});
|
||||
wrapper.appendChild(check);
|
||||
}
|
||||
const caption = createElement('span');
|
||||
if (col.captionStyle != null) {
|
||||
caption.style.cssText = convertCssStyle(col.captionStyle);
|
||||
let caption;
|
||||
if (typeof type.createCaption === 'function') {
|
||||
caption = type.createCaption(col);
|
||||
} else {
|
||||
caption = createElement('span');
|
||||
caption.innerText = col.caption ?? '';
|
||||
}
|
||||
if (caption instanceof HTMLElement) {
|
||||
if (col.captionStyle != null) {
|
||||
caption.style.cssText = convertCssStyle(col.captionStyle);
|
||||
}
|
||||
wrapper.appendChild(caption);
|
||||
}
|
||||
caption.innerText = col.caption ?? '';
|
||||
wrapper.appendChild(caption);
|
||||
// order arrow
|
||||
if (col.sortable) {
|
||||
th.appendChild(createElement('layer', 'arrow'));
|
||||
@ -906,13 +915,15 @@ export class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
_changingColumnOrder(index, offset, x, offsetLeft, scrollLeft) {
|
||||
_changingColumnOrder(index, offset, mouse, draggerCellLeft) {
|
||||
const children = this._var.refs.header.children;
|
||||
let element = children[index];
|
||||
this._var.refs.dragger.style.cssText = `left: ${element.offsetLeft - offsetLeft + offset}px; width: ${element.style.width}; display: block`;
|
||||
offset = x + scrollLeft - element.offsetLeft; // getOffsetLeftFromWindow(element);
|
||||
this._var.refs.dragger.style.cssText = `left: ${element.offsetLeft - draggerCellLeft + offset}px; width: ${element.style.width}; display: block`;
|
||||
// offset = x + gridScrollLeft - element.offsetLeft; // getOffsetLeftFromWindow(element);
|
||||
offset += mouse;
|
||||
let idx;
|
||||
if (offset < 0) {
|
||||
const toLeft = offset < 0;
|
||||
if (toLeft) {
|
||||
offset = -offset;
|
||||
for (let i = index - 1; i >= 0 && offset >= 0; i -= 1) {
|
||||
element = children[i];
|
||||
@ -943,13 +954,27 @@ export class Grid {
|
||||
}
|
||||
idx ??= count - 1;
|
||||
}
|
||||
if (idx !== this._var.colAttrs.__orderIndex) {
|
||||
this._var.colAttrs.__orderIndex = idx;
|
||||
if (idx !== this._var.colAttrs.__orderIndex || this._var.refs.draggerCursor.style.display !== 'block') {
|
||||
element = children[idx];
|
||||
if (element == null) {
|
||||
return;
|
||||
}
|
||||
this._var.refs.draggerCursor.style.cssText = `left: ${element.offsetLeft - offsetLeft}px; display: block`;
|
||||
this._var.colAttrs.__orderIndex = idx;
|
||||
// avoid `offsetLeft` of hidden header to be 0
|
||||
let left;
|
||||
if (element.style.display === 'none') {
|
||||
left = 0;
|
||||
while (left === 0 && (element = children[++idx]) != null) {
|
||||
left = element.offsetLeft;
|
||||
}
|
||||
if (!toLeft && left === 0) {
|
||||
left = draggerCellLeft;
|
||||
}
|
||||
} else {
|
||||
left = element.offsetLeft;
|
||||
}
|
||||
// set position of dragger cursor
|
||||
this._var.refs.draggerCursor.style.cssText = `left: ${left - draggerCellLeft}px; display: block`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1057,14 +1082,21 @@ export class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
_getItemValue(item, key, filter) {
|
||||
_getItemProp(item, editing, col) {
|
||||
let value;
|
||||
if (typeof filter === 'function') {
|
||||
value = filter(item, false, this._var.refs.body);
|
||||
if (typeof col?.filter === 'function') {
|
||||
value = col.filter(item, editing, this._var.refs.body);
|
||||
} else {
|
||||
value = item[key];
|
||||
value = item[col.key];
|
||||
}
|
||||
return value?.Value ?? value;
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
const prop = editing ? 'Value' : 'DisplayValue';
|
||||
if (Object.prototype.hasOwnProperty.call(value, prop)) {
|
||||
return value[prop];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
_getRowTarget(target) {
|
||||
@ -1174,19 +1206,35 @@ export class Grid {
|
||||
} else {
|
||||
const dict = Object.create(null);
|
||||
for (let item of this._var.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] = {
|
||||
let displayValue = this._getItemProp(item.values, false, col);
|
||||
if (displayValue == null) {
|
||||
displayValue = this.langs.null;
|
||||
}
|
||||
if (!Object.hasOwnProperty.call(dict, displayValue)) {
|
||||
const val = this._getItemProp(item.values, true, col);
|
||||
dict[displayValue] = {
|
||||
Value: val,
|
||||
DisplayValue: typeof col.filter === 'function' ? col.filter(item.values) : v?.DisplayValue ?? v
|
||||
DisplayValue: displayValue
|
||||
};
|
||||
}
|
||||
}
|
||||
array = Object.values(dict)
|
||||
.sort((a, b) => {
|
||||
a = a?.Value ?? a;
|
||||
b = b?.Value ?? b;
|
||||
if (a == null && b == null) {
|
||||
return 0;
|
||||
}
|
||||
if (a == null && b != null) {
|
||||
return -1;
|
||||
}
|
||||
if (a != null && b == null) {
|
||||
return 1;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(a, 'Value')) {
|
||||
a = a.Value;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(b, 'Value')) {
|
||||
b = b.Value;
|
||||
}
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
});
|
||||
}
|
||||
@ -1197,7 +1245,7 @@ export class Grid {
|
||||
}
|
||||
return {
|
||||
Value: i,
|
||||
DisplayValue: i == null ? '' : i
|
||||
DisplayValue: i == null ? this.langs.null : i
|
||||
};
|
||||
});
|
||||
this._fillFilterList(col, itemlist, array, itemall);
|
||||
@ -1207,8 +1255,16 @@ export class Grid {
|
||||
searchbox.addEventListener('input', e => {
|
||||
const key = e.currentTarget.value.toLowerCase();
|
||||
const items = key.length === 0 ? array : array.filter(i => {
|
||||
const displayValue = i?.DisplayValue ?? i;
|
||||
return String(displayValue ?? '').toLowerCase().includes(key);
|
||||
let displayValue;
|
||||
if (i != null && Object.prototype.hasOwnProperty.call(i, 'DisplayValue')) {
|
||||
displayValue = i.DisplayValue;
|
||||
} else {
|
||||
displayValue = i;
|
||||
}
|
||||
if (displayValue == null) {
|
||||
displayValue = this.langs.null;
|
||||
}
|
||||
return String(displayValue).toLowerCase().includes(key);
|
||||
});
|
||||
this._fillFilterList(col, itemlist, items, itemall);
|
||||
});
|
||||
@ -1223,7 +1279,7 @@ export class Grid {
|
||||
if (typeof col.onFilterOk === 'function') {
|
||||
col.onFilterOk.call(this, col, array);
|
||||
} else {
|
||||
col.filterValues = array.map(a => a.Value);
|
||||
col.filterValues = array.map(a => a.DisplayValue);
|
||||
}
|
||||
this._var.colAttrs.__filtered = true;
|
||||
this._refreshSource();
|
||||
@ -1268,7 +1324,8 @@ export class Grid {
|
||||
content.style.top = `${rowHeight}px`;
|
||||
this._set(col.key, 'filterSource', array);
|
||||
for (let item of array) {
|
||||
item.__checked = !Array.isArray(col.filterValues) || col.filterValues.includes(item.Value ?? item);
|
||||
const v = Object.prototype.hasOwnProperty.call(item, 'DisplayValue') ? item.DisplayValue : item;
|
||||
item.__checked = !Array.isArray(col.filterValues) || col.filterValues.includes(v);
|
||||
}
|
||||
if (array.length > 12) {
|
||||
array = array.slice(0, 12);
|
||||
@ -1282,7 +1339,7 @@ export class Grid {
|
||||
const div = createElement('div', 'filter-item');
|
||||
div.appendChild(createCheckbox({
|
||||
checked: item.__checked,
|
||||
label: item?.DisplayValue ?? item,
|
||||
label: Object.prototype.hasOwnProperty.call(item, 'DisplayValue') ? item.DisplayValue : item,
|
||||
onchange: e => {
|
||||
item.__checked = e.target.checked;
|
||||
all.querySelector('input').checked = ![...content.querySelectorAll('input')].some(i => !i.checked);
|
||||
@ -1333,7 +1390,7 @@ export class Grid {
|
||||
const cx = getClientX(e);
|
||||
const clearEvents = attr => {
|
||||
for (let event of ['mousemove', 'mouseup']) {
|
||||
if (attr.hasOwnProperty(event)) {
|
||||
if (Object.prototype.hasOwnProperty.call(attr, event)) {
|
||||
window.removeEventListener(event, attr[event]);
|
||||
delete attr[event];
|
||||
}
|
||||
@ -1346,20 +1403,28 @@ export class Grid {
|
||||
clearEvents(attr);
|
||||
}
|
||||
attr.dragging = true;
|
||||
const offsetLeft = this._var.refs.header.querySelector('th:last-child').offsetLeft;
|
||||
const scrollLeft = this._var.el.scrollLeft;
|
||||
const draggerCellLeft = this._var.refs.header.querySelector('th:last-child').offsetLeft;
|
||||
// const gridScrollLeft = this._var.el.scrollLeft;
|
||||
let p = this._var.el;
|
||||
let gridLeftFromWindow = p.offsetLeft;
|
||||
while ((p = p.offsetParent) != null) {
|
||||
gridLeftFromWindow += p.offsetLeft + p.clientLeft;
|
||||
}
|
||||
const mouse = cx - e.currentTarget.offsetLeft + this._var.el.scrollLeft - gridLeftFromWindow;
|
||||
const dragmove = e => {
|
||||
const cx2 = getClientX(e);
|
||||
const offset = cx2 - cx;
|
||||
let pos = attr.offset;
|
||||
let dragging;
|
||||
if (pos == null && (offset > MiniDragOffset || offset < -MiniDragOffset)) {
|
||||
dragging = true;
|
||||
if (pos == null) {
|
||||
if (offset > MiniDragOffset || offset < -MiniDragOffset) {
|
||||
dragging = true;
|
||||
}
|
||||
} else if (pos !== offset) {
|
||||
dragging = true;
|
||||
}
|
||||
if (dragging) {
|
||||
this._changingColumnOrder(index, offset, cx2, offsetLeft, scrollLeft);
|
||||
this._changingColumnOrder(index, offset, mouse, draggerCellLeft);
|
||||
attr.offset = offset;
|
||||
}
|
||||
};
|
||||
@ -1386,7 +1451,7 @@ export class Grid {
|
||||
const window = this.window ?? global;
|
||||
const clearEvents = attr => {
|
||||
for (let event of ['mousemove', 'mouseup']) {
|
||||
if (attr.hasOwnProperty(event)) {
|
||||
if (Object.prototype.hasOwnProperty.call(attr, event)) {
|
||||
window.removeEventListener(event, attr[event]);
|
||||
delete attr[event];
|
||||
}
|
||||
@ -1648,7 +1713,7 @@ export class Grid {
|
||||
if (enabled !== false) {
|
||||
const val = item[col.key];
|
||||
let oldValue;
|
||||
if (val?.Value != null) {
|
||||
if (val != null && Object.prototype.hasOwnProperty.call(val, 'Value') != null) {
|
||||
oldValue = val.Value;
|
||||
val.Value = value;
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user