From bed5c1aca12c23bfc2ff76533a8605c6937de80d Mon Sep 17 00:00:00 2001 From: Tsanie Date: Fri, 2 Feb 2024 16:02:34 +0800 Subject: [PATCH] add more comments --- jsdoc/grid/assets/column-refresh.jpg | Bin 0 -> 36420 bytes lib/ui/css/grid.scss | 1 + lib/ui/grid/column.js | 62 +++++- lib/ui/grid/grid.js | 297 ++++++++++++++++----------- package.json | 2 +- 5 files changed, 237 insertions(+), 125 deletions(-) create mode 100644 jsdoc/grid/assets/column-refresh.jpg diff --git a/jsdoc/grid/assets/column-refresh.jpg b/jsdoc/grid/assets/column-refresh.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1263fbafbba3afa029deefa5522168505d454194 GIT binary patch literal 36420 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 Uw%I@FO8@S3`2YAd;_qMo4@v3v^8f$< literal 0 HcmV?d00001 diff --git a/lib/ui/css/grid.scss b/lib/ui/css/grid.scss index 4ad6e27..d5c8335 100644 --- a/lib/ui/css/grid.scss +++ b/lib/ui/css/grid.scss @@ -338,6 +338,7 @@ .ui-check-wrapper { display: inline-flex; justify-content: center; + height: var(--row-height); .ui-check-inner { diff --git a/lib/ui/grid/column.js b/lib/ui/grid/column.js index 0551703..106899c 100644 --- a/lib/ui/grid/column.js +++ b/lib/ui/grid/column.js @@ -9,7 +9,11 @@ import { createDateInput, formatDate, setDateValue, getDateValue } from "../date /** * 列定义基类 + * + * _函数调用流程图示_
+ * Column Refresh * @class + * @static */ export class GridColumn { /** @@ -26,6 +30,8 @@ export class GridColumn { /** * 创建显示单元格时调用的方法 * @param {GridColumnDefinition} col - 列定义对象 + * @param {number} index - 行元素索引(需要配合 [startIndex]{@linkcode Grid#startIndex} 相加得到真实数据索引) + * @param {Grid} grid - Grid 实例 * @returns {HTMLElement} 返回创建的单元格元素 * @virtual */ @@ -93,6 +99,16 @@ export class GridColumn { element.style.cssText = convertCssStyle(style); } + /** + * 设置单元格类名时调用的方法 + * @param {HTMLElement} element - 单元格元素 + * @param {string} name - 要设置的类名 + * @virtual + */ + static setClass(element, name) { + element.className = name ?? ''; + } + /** * 设置单元格可用性时调用的方法 * @param {HTMLElement} element - 单元格元素 @@ -297,6 +313,14 @@ export class GridDropdownColumn extends GridColumn { return e[col.dropOptions?.valueKey ?? 'value']; } + static setClass(element, name) { + if (element.tagName === 'DIV') { + element.className = `ui-drop-wrapper ${name ?? ''}`; + } else { + super.setClass(element, name); + } + } + static setEnabled(element, enabled) { super.setEnabled(element, enabled); const drop = this._getDrop(element); @@ -336,6 +360,14 @@ export class GridCheckboxColumn extends GridColumn { static getValue(e) { return e.target.checked } + static setClass(element, name) { + if (element.tagName === 'LABEL') { + element.className = `ui-check-wrapper ${name ?? ''}`; + } else { + super.setClass(element, name); + } + } + static setEnabled(element, enabled) { super.setEnabled(element, enabled); element.querySelector('input').disabled = enabled === false; @@ -346,15 +378,15 @@ export class GridIconColumn extends GridColumn { static create() { return createElement('span', 'col-icon') } static setValue(element, val, item, col) { - let className = col.iconClassName; - if (typeof className === 'function') { - className = className.call(col, item.values); - } - if (className == null) { - element.className = 'col-icon'; - } else { - element.className = `col-icon ${className}`; - } + // let className = col.iconClassName; + // if (typeof className === 'function') { + // className = className.call(col, item.values); + // } + // if (className == null) { + // element.className = 'col-icon'; + // } else { + // element.className = `col-icon ${className}`; + // } let type = col.iconType; if (typeof type === 'function') { type = type.call(col, item.values); @@ -370,6 +402,10 @@ export class GridIconColumn extends GridColumn { } } + static setClass(element, name) { + element.className = `col-icon ${name ?? ''}`; + } + static setEnabled(element, enabled) { super.setEnabled(element, enabled); if (enabled === false) { @@ -405,6 +441,14 @@ export class GridDateColumn extends GridColumn { return getDateValue(e.target, col.dateValueFormatter); } + static setClass(element, name) { + if (element.tagName === 'INPUT') { + element.className = `ui-date-cell ${name ?? ''}`; + } else { + super.setClass(element, name); + } + } + static setEnabled(element, enabled) { element.disabled = enabled === false; } diff --git a/lib/ui/grid/grid.js b/lib/ui/grid/grid.js index 3790c84..3b1ec21 100644 --- a/lib/ui/grid/grid.js +++ b/lib/ui/grid/grid.js @@ -128,55 +128,6 @@ let r = lang; * @returns {GridSourceItem[]} 行下拉列表数据源 */ -/** - * 列头复选框改变时的回调函数 - * @callback GridColumnCheckedCallback - * @param {GridColumnDefinition} col - 列定义对象 - * @param {boolean} flag - 是否选中 - * @this Grid - */ - -/** - * 单元格发生变化时的回调函数 - * @callback GridCellChangedCallback - * @param {GridItem} item - 行数据对象 - * @param {(boolean | string | number)} value - 修改后的值 - * @param {(boolean | string | number)} oldValue - 修改前的值 - * @param {any} [e] - 列修改事件传递过来的任意对象 - * @this Grid - */ - -/** - * 文本单元格输入完成时的回调函数 - * @callback GridCellInputEndedCallback - * @param {GridColumnDefinition} col - 列定义对象 - * @param {string} value - 修改后的文本框值 - * @this Grid - */ - -/** - * 列过滤点 `OK` 时的回调函数 - * @callback GridColumnFilterOkCallback - * @param {GridColumnDefinition} col - 列定义对象 - * @param {GridItem[]} selected - 选中的过滤项 - * @this Grid - */ - -/** - * 列过滤后的回调函数 - * @callback GridColumnFilteredCallback - * @param {GridColumnDefinition} col - 列定义对象 - * @this Grid - */ - -/** - * 下拉框列表展开时的回调函数 - * @callback GridColumnDropExpandedCallback - * @param {GridItem} item - 行数据对象 - * @param {Dropdown} drop - 拉框对象 - * @this GridColumnDefinition - */ - /** * 下拉列表参数对象 * @typedef DropdownOptions @@ -207,7 +158,7 @@ let r = lang; /** * 列定义接口 - * @typedef {object} GridColumnDefinition + * @class * @property {string} key - 列关键字,默认以该关键字从行数据中提取单元格值,行数据的关键字属性值里包含 DisplayValue 则优先显示此值 * @property {(GridColumnTypeEnum | GridColumn)} [type=Grid.ColumnTypes.Common] - 列的类型,可以为 {@linkcode GridColumn} 的子类,或者如下内置类型 {@linkcode Grid.ColumnTypes} * @property {number} type.Common=0 - 通用列(只读) @@ -241,15 +192,19 @@ let r = lang; * @property {boolean} [sortable=true] - 列是否允许排序 * @property {boolean} [orderable=true] - 列是否允许重排顺序 * @property {boolean} [allcheck=false] - 列为复选框类型时是否在列头增加全选复选框 + * @property {boolean} [shrink=false] - 列为收缩列,禁用自动调整大小 + * @property {string} [class] - 单元格元素的额外样式类型字符串(仅在重建行元素时读取) * @property {object} [css] - 单元格css样式对象(仅在重建行元素时读取) - * @property {GridItemObjectCallback} [styleFilter] - 根据返回值填充单元格样式(填充行列数据时读取) - * @property {GridColumnDefinition} styleFilter.{this} - 上下文为列定义对象 - * @property {GridItem} styleFilter.item - 行数据对象 - * @property {object} styleFilter.{returns} - 返回样式对象 - * @property {GridItemStringCallback} [bgFilter] - 根据返回值设置单元格背景色 - * @property {GridColumnDefinition} bgFilter.{this} - 上下文为列定义对象 - * @property {GridItem} bgFilter.item - 行数据对象 - * @property {string} bgFilter.{returns} - 返回单元格背景色字符串 + * @property {(object | GridItemObjectCallback)} [style] - 单元格样式(填充行列数据时读取),支持直接返回样式对象或调用函数返回(若赋值则忽略 [styleFilter)]{@linkcode GridColumnDefinition#styleFilter}) + * @property {GridColumnDefinition} style.{this} - 上下文为列定义对象 + * @property {GridItem} style.item - 行数据对象 + * @property {object} style.{returns} - 返回样式对象 + * @property {(@deprecated)} [styleFilter] - **已过时**
_根据返回值填充单元格样式(填充行列数据时读取)_ + * @property {(string | GridItemStringCallback)} [background] - 设置单元格背景色(填充行列数据时读取),支持直接设置颜色字符串或调用函数返回(若赋值则忽略 [bgFilter]{@linkcode GridColumnDefinition#bgFilter}) + * @property {GridColumnDefinition} background.{this} - 上下文为列定义对象 + * @property {GridItem} background.item - 行数据对象 + * @property {string} background.{returns} - 返回单元格背景色字符串 + * @property {(@deprecated)} [bgFilter] - **已过时**
_根据返回值设置单元格背景色_ * @property {object} [events] - 给单元格元素附加事件(事件函数上下文为数据行对象) * @property {Function} events.{event} - 事件回调函数 * @property {(object | GridItemObjectCallback)} [attrs] - 根据返回值设置单元格元素的附加属性,允许直接设置对象也支持调用如下函数返回对象 @@ -271,10 +226,6 @@ let r = lang; * @property {GridSourceItem[]} source.{returns} - 返回行下拉列表数据源 * @property {boolean} [sourceCache=false] - 下拉列表数据源是否缓存结果(即行数据未发生变化时仅从source属性获取一次值) * @property {("fa-light" | "fa-regular" | "fa-solid")} [iconType=fa-light] - 列为图标类型时以该值设置图标样式 - * @property {(string | GridItemStringCallback)} [iconClassName] - 列为图标类型时以该值作为单元格元素的额外样式类型,支持直接使用字符串或者调用如下函数 - * @property {GridColumnDefinition} iconClassName.{this} - 上下文为列定义对象 - * @property {GridItem} iconClassName.item - 行数据对象 - * @property {string} iconClassName.{returns} - 返回额外样式类型字符串 * @property {string} [dateMin] - 列为日期类型时以该值作为最小可选日期值 * @property {string} [dateMax] - 列为日期类型时以该值作为最大可选日期值 * @property {DateFormatterCallback} [dateValueFormatter] - 列为日期类型时自定义日期格式化函数 @@ -284,32 +235,59 @@ let r = lang; * @property {GridColumnDefinition} tooltip.{this} - 上下文为列定义对象 * @property {GridItem} tooltip.item - 行数据对象 * @property {string} tooltip.{returns} - 返回额外 tooltip 字符串 - * @property {GridColumnCheckedCallback} [onAllChecked] - 列头复选框改变时触发 - * @property {Grid} onAllChecked.{this} - 上下文为 Grid - * @property {GridColumnDefinition} onAllChecked.col - 列定义对象 - * @property {boolean} onAllChecked.flag - 是否选中 - * @property {GridCellChangedCallback} [onChanged] - 单元格发生变化时触发 - * @property {Grid} onChanged.{this} - 上下文为 Grid - * @property {GridItem} onChanged.item - 行数据对象 - * @property {(boolean | string | number)} onChanged.value - 修改后的值 - * @property {(boolean | string | number)} onChanged.oldValue - 修改前的值 - * @property {any} [onChanged.e] - 列修改事件传递过来的任意对象 - * @property {GridCellInputEndedCallback} [onInputEnded] - 文本单元格在输入完成时触发的事件 - * @property {Grid} onInputEnded.{this} - 上下文为 Grid - * @property {GridColumnDefinition} onInputEnded.col - 列定义对象 - * @property {string} onInputEnded.value - 修改后的文本框值 - * @property {GridColumnFilterOkCallback} [onFilterOk] - 列过滤点击 `OK` 时触发的事件 - * @property {Grid} onFilterOk.{this} - 上下文为 Grid - * @property {GridColumnDefinition} onFilterOk.col - 列定义对象 - * @property {GridItem[]} onFilterOk.selected - 选中的过滤项 - * @property {GridColumnFilteredCallback} [onFiltered] - 列过滤后触发的事件 - * @property {Grid} onFiltered.{this} - 上下文为 Grid - * @property {GridColumnDefinition} onFiltered.col - 列定义对象 - * @property {GridColumnDropExpandedCallback} [onDropExpanded] - 列为下拉框类型时在下拉列表展开时触发的事件 - * @property {GridColumnDefinition} onDropExpanded.{this} - 上下文为列定义对象 - * @property {GridItem} onDropExpanded.item - 行数据对象 - * @property {Dropdown} onDropExpanded.drop - 拉框对象 */ +class GridColumnDefinition { + /** + * 列头复选框改变时触发 + * @type {Function} + * @event + * @param {GridColumnDefinition} col - 列定义对象 + * @param {boolean} flag - 是否选中 + * @this Grid + */ + onAllChecked; + /** + * 单元格发生变化时触发 + * @event + * @param {GridItem} item - 行数据对象 + * @param {(boolean | string | number)} value - 修改后的值 + * @param {(boolean | string | number)} oldValue - 修改前的值 + * @param {any} [e] - 列修改事件传递过来的任意对象 + * @this Grid + */ + onChanged; + /** + * 文本单元格在输入完成时触发的事件 + * @event + * @param {GridColumnDefinition} col - 列定义对象 + * @param {string} value - 修改后的文本框值 + * @this Grid + */ + onInputEnded; + /** + * 列过滤点击 `OK` 时触发的事件 + * @event + * @param {GridColumnDefinition} col - 列定义对象 + * @param {GridItem[]} selected - 选中的过滤项 + * @this Grid + */ + onFilterOk; + /** + * 列过滤后触发的事件 + * @event + * @param {GridColumnDefinition} col - 列定义对象 + * @this Grid + */ + onFiltered; + /** + * 列为下拉框类型时在下拉列表展开时触发的事件 + * @event + * @param {GridItem} item - 行数据对象 + * @param {Dropdown} drop - 拉框对象 + * @this GridColumnDefinition + */ + onDropExpanded; +} /** * 判断复选框列的回调函数 @@ -424,73 +402,92 @@ const GridColumnDirection = { * ]; */ export class Grid { + /** + * 内部引用变量 + * @private + */ _var = { /** * 父容器元素 * @type {HTMLElement} + * @private */ parent: null, /** * Grid 元素 - `div.ui-grid` * @type {HTMLDivElement} + * @private */ el: null, /** * 全部数据数组 * @type {GridItemWrapper[]} + * @private */ source: null, /** * 当前已过滤显示的数据数组 * @type {GridItemWrapper[]} + * @private */ currentSource: null, /** * 当前选中的列索引 * @type {number} + * @private */ selectedColumnIndex: -1, /** * 当前选中的行索引数组 * @type {number[]} + * @private */ selectedIndexes: null, /** * 虚模式头部索引 * @type {number} + * @private */ startIndex: 0, /** * 旧选择索引数组 * @type {number[]} + * @private */ oldSelectedIndexes: null, /** * 旧虚模式头部索引 + * @type {number} + * @private */ oldIndex: null, /** * 当前滚动上边距 + * @private * @type {number} */ scrollTop: 0, /** * 当前滚动左边距 + * @private * @type {number} */ scrollLeft: 0, /** * 一页高度可显示的行数 + * @private * @type {number} */ rowCount: -1, /** * 列类型缓存字典 + * @private * @property {GridColumn} {key} - 关键字对应列的类型缓存对象 */ colTypes: {}, /** * 列属性字典 + * @private * @property {object} {key} - 关键字对应列的拖拽、调整大小暂存对象 * @property {boolean} {key}.dragging - 列正在拖拽 * @property {number} {key}.offset - 列拖拽偏移 @@ -508,81 +505,103 @@ export class Grid { /** * 有已过滤的列 * @type {boolean} + * @private */ __filtered: false, /** * 过滤面板已打开 * @type {boolean} + * @private */ __filtering: false, /** * 上一个目标排序列索引 * @type {number} + * @private */ __orderIndex: -1, }, /** * 是否处于渲染中 * @type {boolean} + * @private */ rendering: false, + /** + * 头部高度 + * @type {number} + * @private + */ + headerHeight: null, /** * 正文高度 * @type {number} + * @private */ containerHeight: null, /** * 正文宽度 * @type {number} + * @private */ bodyClientWidth: null, /** * 是否需要 resize * @type {boolean} + * @private */ needResize: null, /** * 页面元素引用 + * @private */ refs: { /** * 表格引用 - table.ui-grid-table * @type {HTMLTableElement} + * @private */ table: null, /** * 表格正文引用 - tbody * @type {HTMLTableSectionElement} + * @private */ body: null, /** * 表格头部引用 - thead>tr * @type {HTMLTableSectionElement} + * @private */ header: null, /** * 加载状态元素引用 - div.ui-grid-loading * @type {HTMLDivElement} + * @private */ loading: null, /** * 大小计算元素引用 - span.ui-grid-sizer * @type {HTMLSpanElement} + * @private */ sizer: null, /** * 包装元素引用 - div.ui-grid-wrapper * @type {HTMLDivElement} + * @private */ wrapper: null, /** * 拖拽块引用 - div.dragger * @type {HTMLDivElement} + * @private */ dragger: null, /** * 拖拽光标引用 - layer.dragger-cursor * @type {HTMLElement} + * @private */ draggerCursor: null, } @@ -955,9 +974,9 @@ export class Grid { } } if (this.sortIndex >= 0) { - this.sortColumn(); + this.sortColumn(true); } else if (this.sortArray?.length > 0) { - this.sort(); + this.sort(true); } else { this.reload(); } @@ -998,9 +1017,9 @@ export class Grid { } } if (this.sortIndex >= 0) { - this.sortColumn(); + this.sortColumn(true); } else if (this.sortArray?.length > 0) { - this.sort(); + this.sort(true); } else { this.reload(); } @@ -1109,12 +1128,15 @@ export class Grid { this._var.scrollLeft = 0; this._var.rowCount = -1; - if (this.sortIndex >= 0) { - this.sortColumn(); - } else if (this.sortArray?.length > 0) { - this.sort(); - } - this.resize(); + this.resize(true, null, () => { + if (this.sortIndex >= 0) { + this.sortColumn(true); + } else if (this.sortArray?.length > 0) { + this.sort(true); + } else { + this.reload(); + } + }); } /** @@ -1145,6 +1167,13 @@ export class Grid { return Array.prototype.slice.call(this._var.refs.header.querySelectorAll('&>th.column')); } + /** + * 获取虚模式起始索引 + * @readonly + * @type {number} + */ + get startIndex() { return this._var.startIndex } + /** * 获取或设置当前选中的行索引的数组,设置后会刷新列表 * @type {number[]} @@ -1331,9 +1360,9 @@ export class Grid { this._var.rendering = false; if (this._var.source != null) { if (this.sortIndex >= 0) { - this.sortColumn(); + this.sortColumn(true); } else if (this.sortArray?.length > 0) { - this.sort(); + this.sort(true); } } } @@ -1359,8 +1388,10 @@ export class Grid { * 调整 Grid 元素的大小,一般需要在宽度变化时(如页面大小发生变化时)调用 * @param {boolean} [force] - 是否强制 [reload]{@linkcode Grid#reload},默认只有待渲染的行数发生变化时才会调用 * @param {boolean} [keep] - 是否保持当前滚动位置 + * @param {Function} [callback] - 计算大小后的回调函数 + * @param {Grid} callback.{this} - 上下文为 Grid */ - resize(force, keep) { + resize(force, keep, callback) { if (this._var.rendering || this._var.el == null) { return; } @@ -1376,7 +1407,11 @@ export class Grid { const count = truncate((height - 1) / (this.rowHeight + 1)) + (RedumCount * 2) + 1; if (force || count !== this._var.rowCount) { this._var.rowCount = count; - this.reload(keep); + if (typeof callback === 'function') { + callback.call(this); + } else { + this.reload(keep); + } } this._var.bodyClientWidth = body.clientWidth; } @@ -1408,13 +1443,14 @@ export class Grid { if (this.extraRows > 0) { length += this.extraRows; } - this._var.containerHeight = (length + 1) * (this.rowHeight + 1); + this._var.containerHeight = length * (this.rowHeight + 1); if (!keep) { this._var.el.scrollTop = 0; // this._var.el.scrollLeft = 0; this._var.refs.table.style.top = '0px'; } - this._var.refs.wrapper.style.height = `${this._var.containerHeight}px`; + const headerHeight = this._var.headerHeight || this.rowHeight; + this._var.refs.wrapper.style.height = `${this._var.containerHeight + headerHeight}px`; this._adjustRows(this._var.refs.body); this.refresh(); } @@ -1442,6 +1478,8 @@ export class Grid { this._changeColumnWidth(i, width); } }); + } else { + this._var.headerHeight = this._var.refs.table.children[0].offsetHeight; } } @@ -1825,7 +1863,7 @@ export class Grid { type ??= GridColumn; this._var.colTypes[col.key] = type; } - if (col.width > 0 || typeof type.createCaption === 'function') { + if (col.width > 0 || col.shrink || typeof type.createCaption === 'function') { // col.autoResize = false; } else { this._set(col.key, 'autoResize', true); @@ -1847,13 +1885,18 @@ export class Grid { if (col.sortable !== false) { col.sortable = true; } - const w = `${col.width}px`; - const style = { - 'width': w, - 'max-width': w, - 'min-width': w, - 'text-align': col.align - }; + let style; + if (col.shrink) { + style = { 'text-align': col.align }; + } else { + const w = `${col.width}px`; + style = { + 'width': w, + 'max-width': w, + 'min-width': w, + 'text-align': col.align + }; + } this._set(col.key, 'style', style); // element const th = createElement('th', 'column'); @@ -2015,7 +2058,11 @@ export class Grid { type ??= GridColumn; this._var.colTypes[col.key] = type; } - cell.appendChild(type.create(col)); + const element = type.create(col, i, this); + if (typeof col.class === 'string') { + type.setClass(element, col.class); + } + cell.appendChild(element); } } else { cell.style.display = 'none'; @@ -2135,7 +2182,13 @@ export class Grid { } val ??= ''; // fill - if (typeof col.bgFilter === 'function') { + let bg = col.background; + if (bg != null) { + if (typeof bg === 'function') { + bg = col.background(item); + } + cell.style.backgroundColor = bg ?? ''; + } else if (typeof col.bgFilter === 'function') { const bgColor = col.bgFilter(item); cell.style.backgroundColor = bgColor ?? ''; } @@ -2155,7 +2208,10 @@ export class Grid { if (stateChanged) { element = selected ? type.createEdit(e => this._onRowChanged(e, i, col, type.getValue(e, col), cell), col, this._var.el, vals) : - type.create(col); + type.create(col, i, this); + if (typeof col.class === 'string') { + type.setClass(element, col.class); + } cell.replaceChildren(element); } else { element = cell.children[0]; @@ -2195,7 +2251,17 @@ export class Grid { widths.flag = true; } } - if (typeof col.styleFilter === 'function') { + let style = col.style; + if (style != null) { + if (typeof style === 'function') { + style = col.style(item); + } + if (style != null) { + type.setStyle(element, style); + } else { + element.style.cssText = ''; + } + } else if (typeof col.styleFilter === 'function') { const style = col.styleFilter(item); if (style != null) { type.setStyle(element, style); @@ -2273,6 +2339,7 @@ export class Grid { } } } + this._var.headerHeight = this._var.refs.table.children[0].offsetHeight; } _changingColumnOrder(index, offset, mouse, draggerCellLeft) { diff --git a/package.json b/package.json index b860176..ad973ca 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ ], "scripts": { "dev": "vite", - "build": "node ./vite.build.js && typedoc", + "build": "node ./vite.build.js", "doc": "typedoc", "jsdoc": "jsdoc -c jsdoc.json", "jsdoc-date": "jsdoc -c jsdoc-date.json"