UNPKG

vue-easytable

Version:
1,488 lines (1,378 loc) 146 kB
import { cloneDeep, debounce } from "lodash"; import { initGroupColumns, clsName, getNotFixedTotalWidthByColumnKey, recursiveRemoveColumnByKey, setHeaderContextmenuOptions, setBodyContextmenuOptions, createEmptyRowData, isContextmenuPanelClicked, getRowKey, getColKeysByHeaderColumn, getColumnByColkey, getLeftmostColKey, isCellInSelectionRange, isClearSelectionByBodyCellRightClick, cellAutofill, isOperationColumn, getSelectionRangeData, getSelectionRangeKeys, getSelectionRangeIndexes, setColumnFixed, cancelColumnFixed, } from "./util"; import { onBeforeCopy, onAfterCopy, onBeforePaste, onAfterPaste, onBeforeCut, onAfterCut, onBeforeDelete, onAfterDelete, } from "./util/clipboard"; import { getValByUnit, isFunction, isNumber, scrollTo, isEmptyValue, isEmptyArray, isBoolean, isDefined, createLocale, } from "../../src/utils/index.js"; import { KEY_CODES, MOUSE_EVENT_CLICK_TYPE } from "../../src/utils/constant"; import { getScrollbarWidth } from "../../src/utils/scroll-bar"; import { requestAnimationTimeout, cancelAnimationTimeout, } from "../../src/utils/request-animation-timeout"; import { isInputKeyCode } from "../../src/utils/event-key-codes"; import Hooks from "../../src/utils/hooks-manager"; import { getMouseEventClickType } from "../../src/utils/mouse-event"; import emitter from "../../src/mixins/emitter"; import { COMPS_NAME, HOOKS_NAME, EMIT_EVENTS, COMPS_CUSTOM_ATTRS, INSTANCE_METHODS, CELL_SELECTION_DIRECTION, LOCALE_COMP_NAME, CONTEXTMENU_TYPES, CONTEXTMENU_NODE_TYPES, AUTOFILLING_DIRECTION, CURRENT_CELL_SELECTION_TYPES, COLUMN_FIXED_TYPE, } from "./util/constant"; import Colgroup from "./colgroup"; import Header from "./header"; import Body from "./body"; import Footer from "./footer"; import EditInput from "./editor/index"; import Selection from "./selection/index"; import clickoutside from "../../src/directives/clickoutside"; import VueDomResizeObserver from "../../src/comps/resize-observer"; import VeContextmenu from "vue-easytable/packages/ve-contextmenu"; import ColumnResizer from "./column-resizer"; const t = createLocale(LOCALE_COMP_NAME); export default { name: COMPS_NAME.VE_TABLE, directives: { "click-outside": clickoutside, }, mixins: [emitter], props: { tableData: { required: true, type: Array, }, footerData: { type: Array, default: function () { return []; }, }, showHeader: { type: Boolean, default: true, }, columns: { type: Array, required: true, }, // row key field for row expand、row selection rowKeyFieldName: { type: String, default: null, }, // table scroll width scrollWidth: { type: [Number, String], default: null, }, // table max height maxHeight: { type: [Number, String], default: null, }, // fixed header fixedHeader: { type: Boolean, default: true, }, // fixed footer fixedFooter: { type: Boolean, default: true, }, // border around borderAround: { type: Boolean, default: true, }, // border horizontal borderX: { type: Boolean, default: true, }, // border vertical borderY: { type: Boolean, default: false, }, // event custom option eventCustomOption: { type: Object, default: function () { return null; }, }, // cell style option cellStyleOption: { type: Object, default: function () { return null; }, }, // cell span option cellSpanOption: { type: Object, default: function () { return null; }, }, // row style option rowStyleOption: { type: Object, default: function () { return null; }, }, /* virual scroll option { enable:true, bufferCount:10, // 缓冲的数据 minRowHeight:40, scrolling:(startRowIndex,visibleStartIndex,visibleEndIndex,visibleAboveCount,visibleBelowCount)=>{} } */ virtualScrollOption: { type: Object, default: null, }, // sort option sortOption: { type: Object, default: function () { return null; }, }, // expand row option expandOption: { type: Object, default: function () { return null; }, }, // checkbox option checkboxOption: { type: Object, default: function () { return null; }, }, // radio option radioOption: { type: Object, default: function () { return null; }, }, // cell selection option cellSelectionOption: { type: Object, default: function () { return null; }, }, // cell autofill option cellAutofillOption: { type: [Object, Boolean], default: function () { return null; }, }, // edit option editOption: { type: Object, default: function () { return null; }, }, // column hidden option columnHiddenOption: { type: Object, default: function () { return null; }, }, // contextmenu header option contextmenuHeaderOption: { type: Object, default: function () { return null; }, }, // contextmenu body option contextmenuBodyOption: { type: Object, default: function () { return null; }, }, // clipboard option clipboardOption: { type: Object, default: function () { return null; }, }, // column width resize option columnWidthResizeOption: { type: Object, default: function () { return null; }, }, }, data() { return { // Hooks instance hooks: {}, // is parent rendered parentRendered: false, // table viewport width except scroll bar width tableViewportWidth: 0, /* 列配置变化次数 依赖columns 配置渲染,都需要重新计算:粘性布局时,重新触发 on-dom-resize-change 事件 */ columnsOptionResetTime: 0, tableRootRef: "tableRootRef", tableContainerWrapperRef: "tableContainerWrapperRef", tableContainerRef: "tableContainerRef", tableRef: "tableRef", tableBodyRef: "tableBodyRef", tableContentWrapperRef: "tableContentWrapperRef", virtualPhantomRef: "virtualPhantomRef", editInputRef: "editInputRef", cellSelectionRef: "cellSelectionRef", contextmenuRef: "contextmenuRef", cloneColumns: [], // is group header isGroupHeader: false, /* header rows created by groupColumns */ headerRows: [ /* { rowHeight:40 } */ ], /* footer rows created by footerData */ footerRows: [ /* { rowHeight:40 } */ ], // colgroups colgroups: [], // groupColumns groupColumns: [], /* 存储当前隐藏列信息 hidden columns */ hiddenColumns: [], /* // virtual scroll positions(非响应式) virtualScrollPositions = [ { rowKey: "", // 当前行数据 rowKey top: 0, // 距离上一个项的高度 bottom: 100, // 距离下一个项的高度 height: 100 // 自身高度 } ], */ // virtual scroll visible data virtualScrollVisibleData: [], // virtual scroll visible indexs virtualScrollVisibleIndexs: { start: -1, end: -1, }, // default virtual scroll buffer scale defaultVirtualScrollBufferScale: 1, // default virtual scroll min row height defaultVirtualScrollMinRowHeight: 40, // default placeholder per scrolling row count defaultPlaceholderPerScrollingRowCount: 8, //起始索引 virtualScrollStartIndex: 0, // preview virtual scroll start index previewVirtualScrollStartIndex: 0, //结束索引 virtualScrollEndIndex: 0, // is scrolling showVirtualScrollingPlaceholder: false, // disable pointer events timeout id disablePointerEventsTimeoutId: null, // is scrolling left isLeftScrolling: false, // is scrolling right isRightScrolling: false, // is scrolling vertically isVerticalScrolling: false, // has horizontal scroll bar hasXScrollBar: false, // has vertical scroll bar hasYScrollBar: false, // scroll bar width scrollBarWidth: 0, // preview table container scrollLeft (处理左列或右列固定效果) previewTableContainerScrollLeft: null, // header cell selection colKeys headerIndicatorColKeys: { startColKey: "", startColKeyIndex: -1, endColKey: "", endColKeyIndex: -1, }, // body indicator rowKeys bodyIndicatorRowKeys: { startRowKey: "", startRowKeyIndex: -1, endRowKey: "", endRowKeyIndex: -1, }, // cell selection data cellSelectionData: { currentCell: { rowKey: "", colKey: "", rowIndex: -1, }, normalEndCell: { rowKey: "", colKey: "", rowIndex: -1, }, autoFillEndCell: { rowKey: "", colKey: "", }, }, // cell selection range data cellSelectionRangeData: { leftColKey: "", rightColKey: "", topRowKey: "", bottomRowKey: "", }, // is header cell mousedown isHeaderCellMousedown: false, // is body cell mousedown isBodyCellMousedown: false, // is body operation column mousedown isBodyOperationColumnMousedown: false, // is cell selection corner mousedown isAutofillStarting: false, // autofilling direction autofillingDirection: null, // current cell selection type currentCellSelectionType: "", /* table offest height(开启虚拟滚动时使用) 1、当 :max-height="500" 时使用 max-height 2、当 max-height="calc(100vh - 210px)" 或者 max-height="80%" 时使用 tableOffestHeight */ tableOffestHeight: 0, // table height tableHeight: 0, // highlight row key highlightRowKey: "", /* editing cell */ editingCell: { rowKey: "", colKey: "", row: null, column: null, }, // 编辑单元格每次开始编辑前的初始值 editorInputStartValue: "", /* 是否允许按下方向键时,停止编辑并移动选中单元格。当双击可编辑单元格或者点击输入文本框时设置为false值 像excel一样:如果直接在可编辑单元格上输入内容后,按下上、下、左、右按键可以直接选中其他单元格,并停止当前单元格编辑状态 like Excel:If you directly enter content in an editable cell, press the up, down, left and right buttons to directly select other cells and stop editing the current cell */ enableStopEditing: true, // contextmenu event target contextmenuEventTarget: "", // contextmenu options contextmenuOptions: [], // column resize cursor isColumnResizerHover: false, // is column resizing isColumnResizing: false, }; }, computed: { // actual render table data actualRenderTableData() { return this.isVirtualScroll ? this.virtualScrollVisibleData : this.tableData; }, // return row keys allRowKeys() { let result = []; const { tableData, rowKeyFieldName } = this; if (rowKeyFieldName) { result = tableData.map((x) => { return x[rowKeyFieldName]; }); } return result; }, // virtual scroll buffer count virtualScrollBufferCount() { let result = 0; const { virtualScrollOption, defaultVirtualScrollBufferScale, virtualScrollVisibleCount, } = this; if (virtualScrollOption) { const { bufferScale } = virtualScrollOption; let realBufferScale = isNumber(bufferScale) && bufferScale > 0 ? bufferScale : defaultVirtualScrollBufferScale; result = realBufferScale * virtualScrollVisibleCount; } return result; }, // virtual scroll visible count virtualScrollVisibleCount() { let result = 0; const { isVirtualScroll, virtualScrollOption, defaultVirtualScrollMinRowHeight, maxHeight, tableOffestHeight, } = this; if (isVirtualScroll && maxHeight) { const minRowHeight = isNumber(virtualScrollOption.minRowHeight) ? virtualScrollOption.minRowHeight : defaultVirtualScrollMinRowHeight; if (isNumber(maxHeight)) { result = Math.ceil(maxHeight / minRowHeight); } else if (tableOffestHeight) { // 修复当动态高度 当 max-height="calc(100vh - 210px)" 或者 max-height="80%" 时无法计算的问题 result = Math.ceil(tableOffestHeight / minRowHeight); } } return result; }, // table container wrapper style tableContainerWrapperStyle() { return { width: "100%", }; }, // table container style tableContainerStyle() { let maxHeight = getValByUnit(this.maxHeight); let tableContainerHeight = null; if (this.isVirtualScroll) { if (maxHeight) { tableContainerHeight = maxHeight; } else { console.error( "maxHeight prop is required when 'virtualScrollOption.enable = true'", ); } } else { /* fixed:虚拟滚动表格行展开的 ve-table 存在固定头时(sticky 冲突),表格样式错乱的问题 fixed:When there is a fixed header in the ve-table expanded by the row of the virtual rolling table(header sticky conflict),Incorrect table presentation */ const { tableHeight, hasXScrollBar } = this; tableContainerHeight = tableHeight; /* 有横向滚动条时,表格高度需要加上滚动条的宽度 When there is a horizontal scroll bar, the table height needs to be added with the width of the scroll bar */ if (hasXScrollBar) { tableContainerHeight += this.getScrollBarWidth(); } tableContainerHeight = getValByUnit(tableContainerHeight); } return { "max-height": maxHeight, // if virtual scroll height: tableContainerHeight, }; }, // table style tableStyle() { return { width: getValByUnit(this.scrollWidth), }; }, // table class tableClass() { return { [clsName("border-x")]: this.borderX, [clsName("border-y")]: this.borderY, }; }, // table container class tableContainerClass() { const { isVirtualScroll, isLeftScrolling, isRightScrolling, isVerticalScrolling, isCellEditing, isAutofillStarting, enableCellSelection, } = this; return { [clsName("container")]: true, [clsName("virtual-scroll")]: isVirtualScroll, [clsName("container-left-scrolling")]: isLeftScrolling, [clsName("container-right-scrolling")]: isRightScrolling, [clsName("container-vertical-scrolling")]: isVerticalScrolling, [clsName("is-cell-editing")]: isCellEditing, [clsName("autofilling")]: isAutofillStarting, // 如果开启单元格选择,则关闭 user-select [clsName("enable-cell-selection")]: enableCellSelection, }; }, // table body class tableBodyClass() { let result = null; const { rowStyleOption } = this; let hoverHighlight = true; let clickHighlight = true; let stripe = false; if (rowStyleOption) { hoverHighlight = rowStyleOption.hoverHighlight; clickHighlight = rowStyleOption.clickHighlight; stripe = rowStyleOption.stripe; } result = { [clsName("stripe")]: stripe === true, // 默认不开启 [clsName("row-hover")]: hoverHighlight !== false, // 默认开启 [clsName("row-highlight")]: clickHighlight !== false, // 默认开启 }; return result; }, // is virtual scroll isVirtualScroll() { const { virtualScrollOption } = this; return virtualScrollOption && virtualScrollOption.enable; }, // has fixed column hasFixedColumn() { return this.colgroups.some( (x) => x.fixed === COLUMN_FIXED_TYPE.LEFT || x.fixed === COLUMN_FIXED_TYPE.RIGHT, ); }, // has left fixed column hasLeftFixedColumn() { return this.colgroups.some( (x) => x.fixed === COLUMN_FIXED_TYPE.LEFT, ); }, // has right fixed column hasRightFixedColumn() { return this.colgroups.some( (x) => x.fixed === COLUMN_FIXED_TYPE.RIGHT, ); }, // is editing cell isCellEditing() { const { editingCell } = this; return ( !isEmptyValue(editingCell.rowKey) && !isEmptyValue(editingCell.colKey) ); }, // has edit column hasEditColumn() { return this.colgroups.some((x) => x.edit); }, // enable header contextmenu enableHeaderContextmenu() { let result = false; const { contextmenuHeaderOption } = this; if (contextmenuHeaderOption) { const { contextmenus } = contextmenuHeaderOption; if (Array.isArray(contextmenus) && contextmenus.length) { result = true; } } return result; }, // enable body contextmenu enableBodyContextmenu() { let result = false; const { contextmenuBodyOption } = this; if (contextmenuBodyOption) { const { contextmenus } = contextmenuBodyOption; if (Array.isArray(contextmenus) && contextmenus.length) { result = true; } } return result; }, // contextmenu type contextMenuType() { if (this.headerIndicatorColKeys.startColKeyIndex > -1) { return CONTEXTMENU_TYPES.HEADER_CONTEXTMENU; } else { return CONTEXTMENU_TYPES.BODY_CONTEXTMENU; } }, /* enable cell selection 单元格编辑、剪贴板都依赖单元格选择 */ enableCellSelection() { let result = true; const { cellSelectionOption, rowKeyFieldName } = this; if (isEmptyValue(rowKeyFieldName)) { result = false; } else if ( cellSelectionOption && isBoolean(cellSelectionOption.enable) && cellSelectionOption.enable === false ) { result = false; } return result; }, // enable clipboard enableClipboard() { return this.rowKeyFieldName; }, // eanble width resize enableColumnResize() { let result = false; const { columnWidthResizeOption } = this; if (columnWidthResizeOption) { const { enable } = columnWidthResizeOption; if (isBoolean(enable)) { result = enable; } } return result; }, // header total height headerTotalHeight() { let result = 0; if (this.showHeader) { result = this.headerRows.reduce((total, currentVal) => { return currentVal.rowHeight + total; }, 0); } return result; }, // footer total height footerTotalHeight() { return this.footerRows.reduce((total, currentVal) => { return currentVal.rowHeight + total; }, 0); }, }, watch: { // watch clone table data tableData: { handler(newVal, oldVal) { this.initVirtualScrollPositions(); // 第一次不需要触发,仅数据变更触发 if (oldVal) { this.initVirtualScroll(); } }, immediate: true, }, allRowKeys: { handler(newVal) { if (Array.isArray(newVal)) { const { currentCell } = this.cellSelectionData; // 行被移除,清空单元格选中 if (currentCell.rowIndex > -1) { if (newVal.indexOf(currentCell.rowKey) === -1) { this.clearCellSelectionCurrentCell(); } } } }, immediate: false, }, columns: { handler(newVal, oldVal) { this.initColumns(); this.initGroupColumns(); this.initColumnWidthByColumnResize(); // 排除首次 if (newVal != oldVal && oldVal) { this.columnsOptionResetTime++; // 需要等待 initColumns 和 initGroupColumns 先执行 this.initScrolling(); } }, immediate: true, }, cloneColumns: { handler() { this.initGroupColumns(); // 右键(取消)固定列会操作 cloneColumns this.initColumnWidthByColumnResize(); this.columnsOptionResetTime++; // 需要等待 initColumns 和 initGroupColumns 先执行 this.initScrolling(); }, immediate: false, }, // group columns change watch groupColumns: { handler(val) { if (!isEmptyArray(val)) { this.initHeaderRows(); } }, immediate: true, }, // footer data footerData: { handler(val) { if (!isEmptyArray(val)) { this.initFooterRows(); } }, immediate: true, }, /* watch virtualScrollOption enable 允许按需开启虚拟滚动 */ "virtualScrollOption.enable": { handler(newVal) { // enable virtual scroll if (newVal) { this.initVirtualScrollPositions(); this.initVirtualScroll(); } // disable virtual scroll else { // clear table content top value this.setTableContentTopValue({ top: 0 }); } }, immediate: false, }, // is auto fill starting isAutofillStarting: { handler(val) { if (!val) { this.setCellSelectionByAutofill(); this.clearCellSelectionAutofillEndCell(); } }, }, // watch current cell "cellSelectionData.currentCell": { handler: function () { this.setCurrentCellSelectionType(); }, deep: true, immediate: true, }, // watch normal end cell "cellSelectionData.normalEndCell": { handler: function () { this.setCurrentCellSelectionType(); }, deep: true, immediate: true, }, // watch header indicator colKeys headerIndicatorColKeys: { handler: function () { this.setRangeCellSelectionByHeaderIndicator(); }, deep: true, }, // watch body indicator rowKeys bodyIndicatorRowKeys: { handler: function () { this.setRangeCellSelectionByBodyIndicator(); }, deep: true, }, }, methods: { // int header rows initHeaderRows() { const { groupColumns } = this; if (Array.isArray(groupColumns)) { this.headerRows = groupColumns.map(() => { return { rowHeight: 0 }; }); } }, // int footer rows initFooterRows() { const { footerData } = this; if (Array.isArray(footerData)) { this.footerRows = footerData.map(() => { return { rowHeight: 0 }; }); } }, // header tr height resize headerRowHeightChange({ rowIndex, height }) { this.headerRows.splice(rowIndex, 1, { rowHeight: height }); }, // footer row height resize footRowHeightChange({ rowIndex, height }) { this.footerRows.splice(rowIndex, 1, { rowHeight: height }); }, // body cell width change bodyCellWidthChange(colWidths) { this.colgroups = this.colgroups.map((item) => { item._realTimeWidth = colWidths.get(item.key); return item; }); this.hooks.triggerHook(HOOKS_NAME.TABLE_CELL_WIDTH_CHANGE); }, // set column width for column resize setColumnWidth({ colKey, width }) { this.colgroups = this.colgroups.map((item) => { if (item.key === colKey) { item._columnResizeWidth = width; } return item; }); this.$nextTick(() => { this.setScrollBarStatus(); }); this.hooks.triggerHook(HOOKS_NAME.TABLE_CELL_WIDTH_CHANGE); }, // update colgroups by sort change updateColgroupsBySortChange(sortColumns) { this.colgroups = this.colgroups.map((item) => { // update colgroups by sort columns if (Object.keys(sortColumns).indexOf(item.field) > -1) { item.sortBy = sortColumns[item.field]; } return item; }); }, // init column width by column resize initColumnWidthByColumnResize() { const { enableColumnResize } = this; const columnDefaultWidth = 50; if (enableColumnResize) { this.colgroups = this.colgroups.map((item) => { let columnWidth = columnDefaultWidth; if (isNumber(item.width)) { columnWidth = item.width; } item._columnResizeWidth = columnWidth; return item; }); } }, // init columns initColumns() { const { columnHiddenOption } = this; if (columnHiddenOption) { const { defaultHiddenColumnKeys } = columnHiddenOption; if (!isEmptyArray(defaultHiddenColumnKeys)) { this.hiddenColumns = defaultHiddenColumnKeys; } } this.showOrHideColumns(); }, // show or hide columns showOrHideColumns() { let cloneColumns = cloneDeep(this.columns); cloneColumns = cloneColumns.map((col) => { // 操作列默认左固定 if (col.operationColumn) { col.fixed = COLUMN_FIXED_TYPE.LEFT; } return col; }); const { hiddenColumns } = this; if (!isEmptyArray(hiddenColumns)) { // recursive remove column key hiddenColumns.forEach((key) => { cloneColumns = recursiveRemoveColumnByKey( cloneColumns, key, ); }); } this.cloneColumns = cloneColumns; }, // 初始化分组表头 initGroupColumns() { const result = initGroupColumns(this.cloneColumns); // set is group header this.isGroupHeader = result.isGroupHeader; // set colgroups this.colgroups = result.colgroups; // set groupColumns this.groupColumns = result.groupColumns; }, // scroll bar width getScrollBarWidth() { let result = 0; const { scrollBarWidth } = this; if (scrollBarWidth) { result = scrollBarWidth; } else { result = getScrollbarWidth(); this.scrollBarWidth = result; } return result; }, /* * @selectedAllChange * @desc selected all change * @param {bool} isSelected - is selected */ selectedAllChange({ isSelected }) { this.broadcast( COMPS_NAME.VE_TABLE_BODY, EMIT_EVENTS.CHECKBOX_SELECTED_ALL_CHANGE, { isSelected, }, ); }, /* * @setSelectedAllInfo * @desc set selected all info * @param {bool} isSelected - is selected * @param {bool} isIndeterminate - is indeterminate */ setSelectedAllInfo({ isSelected, isIndeterminate }) { this.broadcast( COMPS_NAME.VE_TABLE_HEADER_CHECKBOX_CONTENT, EMIT_EVENTS.CHECKBOX_SELECTED_ALL_INFO, { isSelected, isIndeterminate, }, ); }, // cell selection current cell change cellSelectionCurrentCellChange({ rowKey, colKey }) { this.cellSelectionData.currentCell.colKey = colKey; this.cellSelectionData.currentCell.rowKey = rowKey; this.cellSelectionData.currentCell.rowIndex = this.allRowKeys.indexOf(rowKey); }, // cell selection end cell change cellSelectionNormalEndCellChange({ rowKey, colKey }) { this.cellSelectionData.normalEndCell.colKey = colKey; this.cellSelectionData.normalEndCell.rowKey = rowKey; this.cellSelectionData.normalEndCell.rowIndex = this.allRowKeys.indexOf(rowKey); }, // cell selection auto fill cell change cellSelectionAutofillCellChange({ rowKey, colKey }) { this.cellSelectionData.autoFillEndCell.colKey = colKey; this.cellSelectionData.autoFillEndCell.rowKey = rowKey; }, // clear cell selection current cell clearCellSelectionCurrentCell() { this.cellSelectionCurrentCellChange({ rowKey: "", colKey: "", rowIndex: -1, }); }, // clear cell selection normal end cell clearCellSelectionNormalEndCell() { this.cellSelectionNormalEndCellChange({ rowKey: "", colKey: "", rowIndex: -1, }); }, // clear cell selection autofill end cell clearCellSelectionAutofillEndCell() { this.cellSelectionAutofillCellChange({ rowKey: "", colKey: "" }); }, // header indicator colKeys change headerIndicatorColKeysChange({ startColKey, endColKey }) { const { colgroups } = this; this.headerIndicatorColKeys.startColKey = startColKey; this.headerIndicatorColKeys.startColKeyIndex = colgroups.findIndex( (x) => x.key === startColKey, ); this.headerIndicatorColKeys.endColKey = endColKey; this.headerIndicatorColKeys.endColKeyIndex = colgroups.findIndex( (x) => x.key === endColKey, ); }, // clear header indicator colKeys clearHeaderIndicatorColKeys() { this.headerIndicatorColKeys.startColKey = ""; this.headerIndicatorColKeys.startColKeyIndex = -1; this.headerIndicatorColKeys.endColKey = ""; this.headerIndicatorColKeys.endColKeyIndex = -1; }, // body indicator rowKeys change bodyIndicatorRowKeysChange({ startRowKey, endRowKey }) { const { allRowKeys } = this; this.bodyIndicatorRowKeys.startRowKey = startRowKey; this.bodyIndicatorRowKeys.startRowKeyIndex = allRowKeys.indexOf(startRowKey); this.bodyIndicatorRowKeys.endRowKey = endRowKey; this.bodyIndicatorRowKeys.endRowKeyIndex = allRowKeys.indexOf(endRowKey); }, // clear body indicator RowKeys clearBodyIndicatorRowKeys() { this.bodyIndicatorRowKeys.startRowKey = ""; this.bodyIndicatorRowKeys.startRowKeyIndex = -1; this.bodyIndicatorRowKeys.endRowKey = ""; this.bodyIndicatorRowKeys.endRowKeyIndex = -1; }, // set cell selection by autofill setCellSelectionByAutofill() { const { cellAutofillOption, cellSelectionRangeData, colgroups, allRowKeys, autofillingDirection, currentCellSelectionType, } = this; const { autoFillEndCell, currentCell } = this.cellSelectionData; const { rowKey, colKey } = autoFillEndCell; if (isEmptyValue(rowKey) || isEmptyValue(colKey)) { return false; } let currentCellData = {}; let normalEndCellData = {}; const { leftColKey, rightColKey, topRowKey, bottomRowKey } = cellSelectionRangeData; // cell selection range auto fill if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.RANGE ) { if ( !isCellInSelectionRange({ cellData: autoFillEndCell, cellSelectionRangeData, colgroups, allRowKeys, }) ) { if (autofillingDirection === AUTOFILLING_DIRECTION.RIGHT) { currentCellData = { rowKey: topRowKey, colKey: leftColKey, }; normalEndCellData = { rowKey: bottomRowKey, colKey }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.DOWN ) { currentCellData = { rowKey: topRowKey, colKey: leftColKey, }; normalEndCellData = { rowKey, colKey: rightColKey }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.UP ) { currentCellData = { rowKey, colKey: leftColKey, }; normalEndCellData = { rowKey: bottomRowKey, colKey: rightColKey, }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.LEFT ) { currentCellData = { rowKey: topRowKey, colKey }; normalEndCellData = { rowKey: bottomRowKey, colKey: rightColKey, }; } } else { // return if within the range return false; } } // cell selection single auto fill else if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE ) { if ( currentCell.rowKey !== rowKey || currentCell.colKey !== colKey ) { if (autofillingDirection === AUTOFILLING_DIRECTION.RIGHT) { currentCellData = { rowKey, colKey: leftColKey, }; normalEndCellData = { rowKey, colKey, }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.DOWN ) { currentCellData = { rowKey: topRowKey, colKey: leftColKey, }; normalEndCellData = { rowKey, colKey: leftColKey, }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.UP ) { currentCellData = { rowKey, colKey: leftColKey, }; normalEndCellData = { rowKey: bottomRowKey, colKey: leftColKey, }; } else if ( autofillingDirection === AUTOFILLING_DIRECTION.LEFT ) { currentCellData = { rowKey, colKey, }; normalEndCellData = { rowKey, colKey: rightColKey, }; } } else { // return if within the range return false; } } const cellAutofillParams = { tableData: this.tableData, allRowKeys: this.allRowKeys, colgroups: this.colgroups, rowKeyFieldName: this.rowKeyFieldName, direction: autofillingDirection, currentCellSelectionType, cellSelectionRangeData, nextCurrentCell: currentCellData, nextNormalEndCell: normalEndCellData, }; if (cellAutofillOption) { const { beforeAutofill, afterAutofill } = cellAutofillOption; if (isFunction(beforeAutofill)) { // before autofill const autofillResponse = cellAutofill({ isReplaceData: false, ...cellAutofillParams, }); const callback = beforeAutofill(autofillResponse); if (isBoolean(callback) && !callback) { return false; } } // after autofill const autofillResponse = cellAutofill({ isReplaceData: true, ...cellAutofillParams, }); if (isFunction(afterAutofill)) { afterAutofill(autofillResponse); } } if (!isEmptyValue(currentCellData.rowKey)) { this.cellSelectionCurrentCellChange({ rowKey: currentCellData.rowKey, colKey: currentCellData.colKey, }); } if (!isEmptyValue(normalEndCellData.rowKey)) { this.cellSelectionNormalEndCellChange({ rowKey: normalEndCellData.rowKey, colKey: normalEndCellData.colKey, }); } }, // cell selection range data change cellSelectionRangeDataChange(newData) { this.cellSelectionRangeData = Object.assign( this.cellSelectionRangeData, newData, ); }, // autofilling direction change autofillingDirectionChange(direction) { this.autofillingDirection = direction; }, // set current cell selection type setCurrentCellSelectionType() { const { currentCell, normalEndCell } = this.cellSelectionData; let result; if ( isEmptyValue(currentCell.rowKey) || isEmptyValue(currentCell.colKey) ) { result = ""; } else { if ( !isEmptyValue(normalEndCell.rowKey) && !isEmptyValue(normalEndCell.colKey) ) { result = CURRENT_CELL_SELECTION_TYPES.RANGE; } else { result = CURRENT_CELL_SELECTION_TYPES.SINGLE; } } this.currentCellSelectionType = result; }, // deal keydown event dealKeydownEvent(event) { const { colgroups, cellSelectionData, enableStopEditing, isCellEditing, } = this; const { keyCode, ctrlKey, shiftKey, altKey } = event; const { rowKey, colKey } = cellSelectionData.currentCell; const currentColumn = colgroups.find((x) => x.key === colKey); if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { switch (keyCode) { case KEY_CODES.TAB: { let direction; if (shiftKey) { direction = CELL_SELECTION_DIRECTION.LEFT; } else { direction = CELL_SELECTION_DIRECTION.RIGHT; } this.selectCellByDirection({ direction, }); this.clearCellSelectionNormalEndCell(); this[INSTANCE_METHODS.STOP_EDITING_CELL](); event.preventDefault(); break; } case KEY_CODES.ARROW_LEFT: { const direction = CELL_SELECTION_DIRECTION.LEFT; if (enableStopEditing) { this.selectCellByDirection({ direction, }); this.clearCellSelectionNormalEndCell(); this[INSTANCE_METHODS.STOP_EDITING_CELL](); event.preventDefault(); } break; } case KEY_CODES.ARROW_RIGHT: { const direction = CELL_SELECTION_DIRECTION.RIGHT; if (enableStopEditing) { this.selectCellByDirection({ direction, }); this.clearCellSelectionNormalEndCell(); this[INSTANCE_METHODS.STOP_EDITING_CELL](); event.preventDefault(); } break; } case KEY_CODES.ARROW_UP: { const direction = CELL_SELECTION_DIRECTION.UP; if (enableStopEditing) { this.selectCellByDirection({ direction, }); this.clearCellSelectionNormalEndCell(); this[INSTANCE_METHODS.STOP_EDITING_CELL](); event.preventDefault(); } break; } case KEY_CODES.ARROW_DOWN: { const direction = CELL_SELECTION_DIRECTION.DOWN; if (enableStopEditing) { this.selectCellByDirection({ direction, }); this.clearCellSelectionNormalEndCell(); this[INSTANCE_METHODS.STOP_EDITING_CELL](); event.preventDefault(); } break; } case KEY_CODES.ENTER: { let direction; // add new line if (altKey) { const editInputEditor = this.$refs[this.editInputRef];