e-virt-table
Version:
A powerful data table based on canvas. You can use it as data grid、Microsoft Excel or Google sheets. It supports virtual scroll、cell edit etc.
640 lines • 22.5 kB
JavaScript
import { generateShortUUID } from './util';
import BaseCell from './BaseCell';
export default class CellHeader extends BaseCell {
constructor(ctx, colIndex, x, y, width, height, column) {
super(ctx, x, y, width, height, 'header', column.fixed);
Object.defineProperty(this, "align", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "hideHeaderSelection", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "verticalAlign", {
enumerable: true,
configurable: true,
writable: true,
value: 'middle'
});
Object.defineProperty(this, "fixed", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "minWidth", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "maxWidth", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "widthFillDisable", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "type", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "operation", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "editorType", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "level", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "text", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "hide", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "displayText", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "colspan", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rowspan", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "row", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "key", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "required", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "readonly", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "ellipsis", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "overflowTooltipShow", {
enumerable: true,
configurable: true,
writable: true,
value: true
});
Object.defineProperty(this, "children", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "column", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "colIndex", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rowKey", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rules", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "hasChildren", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "render", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "style", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(this, "drawX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawY", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "sortIconName", {
enumerable: true,
configurable: true,
writable: true,
value: 'sort-default'
});
Object.defineProperty(this, "sortAscIconName", {
enumerable: true,
configurable: true,
writable: true,
value: 'sort-asc'
});
Object.defineProperty(this, "sortDescIconName", {
enumerable: true,
configurable: true,
writable: true,
value: 'sort-desc'
});
Object.defineProperty(this, "visibleWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "visibleHeight", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "maxLineClampHeader", {
enumerable: true,
configurable: true,
writable: true,
value: 'auto'
});
Object.defineProperty(this, "domDataset", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(this, "drawTextX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawTextY", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawTextWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawTextHeight", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawCellBgColor", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "drawTextColor", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "drawTextFont", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "drawSelectionImageX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSelectionImageY", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSelectionImageWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSelectionImageHeight", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSelectionImageName", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "drawSelectionImageSource", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
// 排序相关
Object.defineProperty(this, "drawSortImageX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSortImageY", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSortImageWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSortImageHeight", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "drawSortImageName", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "drawSortImageSource", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.ctx = ctx;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.visibleWidth = width;
this.visibleHeight = height;
this.colIndex = colIndex;
this.key = column.key;
this.minWidth = column.minWidth;
this.maxWidth = column.maxWidth;
this.hide = (typeof column.hide === 'function' ? column.hide(column) : column.hide) || false;
this.type = column.type || '';
this.editorType = column.editorType || 'text';
this.hideHeaderSelection = column.hideHeaderSelection || false;
this.align = column.headerAlign || column.align || this.ctx.config.COLUMNS_ALIGN;
this.verticalAlign =
column.headerVerticalAlign || column.verticalAlign || this.ctx.config.COLUMNS_VERTICAL_ALIGN;
this.fixed = column.fixed || '';
this.level = column.level || 0;
this.operation = column.operation || false;
this.text = column.title;
this.column = column;
this.colspan = column.colspan || 1;
this.widthFillDisable = column.widthFillDisable || false;
this.rowspan = column.rowspan || 1;
this.rules = column.rules;
this.readonly = column.readonly || false;
this.required = column.required || false;
this.sortIconName = column.sortIconName || 'sort-default';
this.sortAscIconName = column.sortAscIconName || 'sort-asc';
this.sortDescIconName = column.sortDescIconName || 'sort-desc';
this.rowKey = generateShortUUID();
this.overflowTooltipShow = column.overflowTooltipHeaderShow === false ? false : true;
this.hasChildren = (column.children && column.children.length > 0) || false; // 是否有子
this.render = column.renderHeader;
this.maxLineClampHeader = column.maxLineClampHeader || 'auto';
}
/**
* 是否可见,覆盖基类方法,表头是跟y滚动条没有关系的所以不需要加滚动参数
* @returns
*/
isVerticalVisible() {
const { stageHeight } = this.ctx;
const offsetHeight = stageHeight;
return !(this.y + this.height <= 0 || this.y >= offsetHeight);
}
/**
* 更新样式
*/
updateStyle() {
this.style = this.getOverlayerViewsStyle();
}
updateContainer() {
const { HEADER_CELL_STYLE_METHOD, HEADER_BG_COLOR, HEADER_TEXT_COLOR } = this.ctx.config;
let bgColor = HEADER_BG_COLOR;
let textColor = HEADER_TEXT_COLOR;
if (typeof HEADER_CELL_STYLE_METHOD === 'function') {
const headerCellStyleMethod = HEADER_CELL_STYLE_METHOD;
const { backgroundColor, color, font } = headerCellStyleMethod({
colIndex: this.colIndex,
column: this.column,
}) || {};
if (backgroundColor) {
bgColor = backgroundColor;
}
// 文字颜色
if (color) {
textColor = color;
}
if (font) {
this.drawTextFont = font;
}
}
// 高亮查找结果
const { colKey, type } = this.ctx.finderBar;
if (type === 'header' && colKey === this.key) {
bgColor = this.ctx.config.FINDER_CELL_BG_COLOR;
}
this.drawCellBgColor = bgColor;
this.drawTextColor = textColor;
}
update() {
this.updateContainer();
this.displayText = this.getText();
this.drawX = this.getDrawX();
this.drawY = this.getDrawY();
this.drawTextX = this.drawX;
this.drawTextY = this.drawY;
this.drawTextWidth = this.width;
this.drawTextHeight = this.height;
this.updateStyle();
}
draw() {
this.drawEdge();
this.drawSelection();
this.drawText();
this.drawBg();
this.drawSortIcon();
}
drawEdge() {
const { paint, config: { BORDER_COLOR, BORDER }, } = this.ctx;
// 有边框的情况下,绘制边框
paint.drawRect(this.drawX, this.drawY, this.width, this.height, {
borderColor: BORDER ? BORDER_COLOR : 'transparent',
fillColor: this.drawCellBgColor,
});
}
drawText() {
const { paint, config: { HEADER_FONT, CELL_PADDING, REQUIRED_COLOR }, } = this.ctx;
const cacheTextKey = `${this.displayText}_${this.drawTextWidth}_${this.drawTextFont}`;
this.ellipsis = paint.drawText(this.displayText, this.drawTextX, this.drawTextY, this.drawTextWidth, this.drawTextHeight, {
font: this.drawTextFont || HEADER_FONT,
padding: CELL_PADDING,
color: this.drawTextColor,
align: this.align,
verticalAlign: this.verticalAlign,
maxLineClamp: this.maxLineClampHeader,
offsetRight: this.column.sortBy ? 16 : 0, // 排序图标占位
offsetLeft: this.required ? 12 : 0, // 必填星号占位
cacheTextKey,
textCallback: (textInfo) => {
// 排序图标位置,需要跟随文字变化
if (this.column.sortBy) {
this.drawSortImageX = textInfo.right + 4;
this.drawSortImageY = textInfo.top + (textInfo.height - 16) / 2;
}
if (this.required) {
paint.drawText('*', textInfo.left - 18, textInfo.top + (textInfo.height - 12) / 2, 24, 24, {
color: REQUIRED_COLOR,
font: '18px Arial',
align: 'center',
verticalAlign: 'middle',
padding: 0,
});
}
},
});
}
drawBg() {
if (this.ctx.dragHeaderIng) {
return;
}
// 选择区背景颜色
const { ENABLE_SELECTOR, ENABLE_SELECTOR_SINGLE } = this.ctx.config;
let minX = -1;
let maxX = -1;
if (this.ctx.focusCellHeader) {
minX = this.ctx.focusCellHeader.colIndex;
maxX = this.ctx.focusCellHeader.colIndex + this.ctx.focusCellHeader.colspan - 1;
}
// 启用选择器且不是单选
if (ENABLE_SELECTOR && !ENABLE_SELECTOR_SINGLE) {
const { xArr } = this.ctx.selector;
minX = xArr[0];
maxX = xArr[1];
}
const colSpanMaxIndex = this.colspan + this.colIndex - 1;
if (this.colIndex >= minX && this.colIndex <= maxX && colSpanMaxIndex <= maxX) {
this.ctx.paint.drawRect(this.drawX, this.drawY, this.width, this.height, {
borderColor: 'transparent',
fillColor: this.ctx.config.SELECT_ROW_COL_BG_COLOR || 'transparent',
});
}
}
drawSelection() {
if (this.hideHeaderSelection) {
return;
}
// 选中框类型
if (['index-selection', 'selection', 'selection-tree', 'tree-selection'].includes(this.type)) {
const { indeterminate, check, selectable } = this.ctx.database.getCheckedState();
const { CHECKBOX_SIZE = 0, CELL_PADDING } = this.ctx.config;
// 默认居中
let iconX = this.drawX + (this.width - CHECKBOX_SIZE) / 2;
let iconY = this.drawY + (this.height - CHECKBOX_SIZE) / 2;
this.drawTextX = iconX + CHECKBOX_SIZE - CELL_PADDING / 2;
this.drawTextWidth = this.drawX + this.visibleWidth - this.drawTextX;
if (this.align === 'left' || this.align === 'right') {
iconX = this.drawX + CELL_PADDING;
this.drawTextX = iconX + CHECKBOX_SIZE - CELL_PADDING / 2;
this.drawTextWidth = this.drawX + this.visibleWidth - this.drawTextX;
}
if (this.verticalAlign === 'top') {
iconY = this.drawY + CELL_PADDING / 2;
}
else if (this.verticalAlign === 'bottom') {
iconY = this.drawY + this.height - CHECKBOX_SIZE - CELL_PADDING / 2;
}
let checkboxImage = this.ctx.icons.get('checkbox-uncheck');
let checkboxName = 'checkbox-uncheck';
if (indeterminate) {
checkboxImage = this.ctx.icons.get('checkbox-indeterminate');
checkboxName = 'checkbox-indeterminate';
}
else if (check && selectable) {
checkboxImage = this.ctx.icons.get('checkbox-check');
checkboxName = 'checkbox-check';
}
else if (check && !selectable) {
checkboxImage = this.ctx.icons.get('checkbox-check-disabled');
checkboxName = 'checkbox-check-disabled';
}
else if (!check && selectable) {
checkboxImage = this.ctx.icons.get('checkbox-uncheck');
checkboxName = 'checkbox-uncheck';
}
else {
checkboxImage = this.ctx.icons.get('checkbox-disabled');
checkboxName = 'checkbox-disabled';
}
if (checkboxImage) {
this.drawSelectionImageX = iconX;
this.drawSelectionImageY = iconY;
this.drawSelectionImageWidth = CHECKBOX_SIZE;
this.drawSelectionImageHeight = CHECKBOX_SIZE;
this.drawSelectionImageName = checkboxName;
this.drawSelectionImageSource = checkboxImage;
this.ctx.paint.drawImage(this.drawSelectionImageSource, this.drawSelectionImageX, this.drawSelectionImageY, this.drawSelectionImageWidth, this.drawSelectionImageHeight);
}
// 不再需要保存文本位置信息,直接在 draw 方法中计算
}
}
drawSortIcon() {
// 如果没有sortBy配置且不是后端排序,不显示排序图标
if (!this.column.sortBy) {
return;
}
const iconSize = 16;
let iconName = this.sortIconName;
// 前端排序
const sortState = this.ctx.database.getSortState(this.key);
if (sortState.direction === 'asc') {
iconName = this.sortAscIconName;
}
else if (sortState.direction === 'desc') {
iconName = this.sortDescIconName;
}
const icon = this.ctx.icons.get(iconName);
if (!icon) {
return;
}
this.drawSortImageWidth = iconSize;
this.drawSortImageHeight = iconSize;
this.drawSortImageName = iconName;
this.drawSortImageSource = icon;
// 绘制图标
this.ctx.paint.drawImage(this.drawSortImageSource, this.drawSortImageX, this.drawSortImageY, this.drawSortImageWidth, this.drawSortImageHeight);
}
getText() {
if (this.render) {
return '';
}
if (['', null, undefined].includes(this.text)) {
return '';
}
return `${this.text}`;
}
/**
* 获取样式
*/
getOverlayerViewsStyle() {
let left = '';
if (this.fixed === 'left') {
left = `${this.drawX}px`;
}
else if (this.fixed === 'right') {
left = `${this.drawX - (this.ctx.stageWidth - this.ctx.fixedRightWidth)}px`;
}
else {
// 中间的,需要减去左边固定列的宽度
left = `${this.drawX - this.ctx.fixedLeftWidth}px`;
}
return {
position: 'absolute',
overflow: 'hidden',
left: left,
top: `${this.drawY + 1}px`,
width: `${this.width}px`,
height: `${this.height - 2}px`,
pointerEvents: 'initial',
userSelect: 'none',
};
}
}
//# sourceMappingURL=CellHeader.js.map