vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
411 lines (410 loc) • 20.9 kB
JavaScript
import XEUtils from 'xe-utils';
import { browse, hasClass, getAbsolutePos, addClass, removeClass, getEventTargetNode } from '../../tools/dom';
function getTargetOffset(target, container) {
var offsetTop = 0;
var offsetLeft = 0;
var triggerCheckboxLabel = !browse.firefox && hasClass(target, 'vxe-checkbox--label');
if (triggerCheckboxLabel) {
var checkboxLabelStyle = getComputedStyle(target);
offsetTop -= XEUtils.toNumber(checkboxLabelStyle.paddingTop);
offsetLeft -= XEUtils.toNumber(checkboxLabelStyle.paddingLeft);
}
while (target && target !== container) {
offsetTop += target.offsetTop;
offsetLeft += target.offsetLeft;
target = target.offsetParent;
if (triggerCheckboxLabel) {
var checkboxStyle = getComputedStyle(target);
offsetTop -= XEUtils.toNumber(checkboxStyle.paddingTop);
offsetLeft -= XEUtils.toNumber(checkboxStyle.paddingLeft);
}
}
return { offsetTop: offsetTop, offsetLeft: offsetLeft };
}
var tableKeyboardHook = {
setupTable: function ($xetable) {
var props = $xetable.props, reactData = $xetable.reactData, internalData = $xetable.internalData;
var refElem = $xetable.getRefMaps().refElem;
var _a = $xetable.getComputeMaps(), computeEditOpts = _a.computeEditOpts, computeCheckboxOpts = _a.computeCheckboxOpts, computeMouseOpts = _a.computeMouseOpts, computeTreeOpts = _a.computeTreeOpts;
function getCheckboxRangeRows(params, targetTrElem, moveRange) {
var countHeight = 0;
var rangeRows = [];
var isDown = moveRange > 0;
var moveSize = moveRange > 0 ? moveRange : (Math.abs(moveRange) + targetTrElem.offsetHeight);
var scrollYLoad = reactData.scrollYLoad;
var afterFullData = internalData.afterFullData, scrollYStore = internalData.scrollYStore;
if (scrollYLoad) {
var _rowIndex = $xetable.getVTRowIndex(params.row);
if (isDown) {
rangeRows = afterFullData.slice(_rowIndex, _rowIndex + Math.ceil(moveSize / scrollYStore.rowHeight));
}
else {
rangeRows = afterFullData.slice(_rowIndex - Math.floor(moveSize / scrollYStore.rowHeight) + 1, _rowIndex + 1);
}
}
else {
var siblingProp = isDown ? 'next' : 'previous';
while (targetTrElem && countHeight < moveSize) {
var rowNodeRest = $xetable.getRowNode(targetTrElem);
if (rowNodeRest) {
rangeRows.push(rowNodeRest.item);
countHeight += targetTrElem.offsetHeight;
targetTrElem = targetTrElem["".concat(siblingProp, "ElementSibling")];
}
}
}
return rangeRows;
}
var handleCheckboxRangeEvent = function (evnt, params) {
var column = params.column, cell = params.cell;
if (column.type === 'checkbox') {
var el_1 = refElem.value;
var elemStore = internalData.elemStore;
var disX_1 = evnt.clientX;
var disY_1 = evnt.clientY;
var bodyWrapperRef = elemStore["".concat(column.fixed || 'main', "-body-wrapper")] || elemStore['main-body-wrapper'];
var bodyWrapperElem_1 = bodyWrapperRef ? bodyWrapperRef.value : null;
if (!bodyWrapperElem_1) {
return;
}
var checkboxRangeElem_1 = bodyWrapperElem_1.querySelector('.vxe-table--checkbox-range');
var domMousemove_1 = document.onmousemove;
var domMouseup_1 = document.onmouseup;
var trElem_1 = cell.parentNode;
var selectRecords_1 = $xetable.getCheckboxRecords();
var lastRangeRows_1 = [];
var marginSize_1 = 1;
var offsetRest = getTargetOffset(evnt.target, bodyWrapperElem_1);
var startTop_1 = offsetRest.offsetTop + evnt.offsetY;
var startLeft_1 = offsetRest.offsetLeft + evnt.offsetX;
var startScrollTop_1 = bodyWrapperElem_1.scrollTop;
var rowHeight_1 = trElem_1.offsetHeight;
var mouseScrollTimeout_1 = null;
var isMouseScrollDown_1 = false;
var mouseScrollSpaceSize_1 = 1;
var triggerEvent_1 = function (type, evnt) {
$xetable.dispatchEvent("checkbox-range-".concat(type), { records: $xetable.getCheckboxRecords(), reserves: $xetable.getCheckboxReserveRecords() }, evnt);
};
var handleChecked_1 = function (evnt) {
var clientX = evnt.clientX, clientY = evnt.clientY;
var offsetLeft = clientX - disX_1;
var offsetTop = clientY - disY_1 + (bodyWrapperElem_1.scrollTop - startScrollTop_1);
var rangeHeight = Math.abs(offsetTop);
var rangeWidth = Math.abs(offsetLeft);
var rangeTop = startTop_1;
var rangeLeft = startLeft_1;
if (offsetTop < marginSize_1) {
// 向上
rangeTop += offsetTop;
if (rangeTop < marginSize_1) {
rangeTop = marginSize_1;
rangeHeight = startTop_1;
}
}
else {
// 向下
rangeHeight = Math.min(rangeHeight, bodyWrapperElem_1.scrollHeight - startTop_1 - marginSize_1);
}
if (offsetLeft < marginSize_1) {
// 向左
rangeLeft += offsetLeft;
if (rangeWidth > startLeft_1) {
rangeLeft = marginSize_1;
rangeWidth = startLeft_1;
}
}
else {
// 向右
rangeWidth = Math.min(rangeWidth, bodyWrapperElem_1.clientWidth - startLeft_1 - marginSize_1);
}
checkboxRangeElem_1.style.height = "".concat(rangeHeight, "px");
checkboxRangeElem_1.style.width = "".concat(rangeWidth, "px");
checkboxRangeElem_1.style.left = "".concat(rangeLeft, "px");
checkboxRangeElem_1.style.top = "".concat(rangeTop, "px");
checkboxRangeElem_1.style.display = 'block';
var rangeRows = getCheckboxRangeRows(params, trElem_1, offsetTop < marginSize_1 ? -rangeHeight : rangeHeight);
// 至少滑动 10px 才能有效匹配
if (rangeHeight > 10 && rangeRows.length !== lastRangeRows_1.length) {
lastRangeRows_1 = rangeRows;
if (evnt.ctrlKey) {
rangeRows.forEach(function (row) {
$xetable.handleSelectRow({ row: row }, selectRecords_1.indexOf(row) === -1);
});
}
else {
$xetable.setAllCheckboxRow(false);
$xetable.handleCheckedCheckboxRow(rangeRows, true, false);
}
triggerEvent_1('change', evnt);
}
};
// 停止鼠标滚动
var stopMouseScroll_1 = function () {
clearTimeout(mouseScrollTimeout_1);
mouseScrollTimeout_1 = null;
};
// 开始鼠标滚动
var startMouseScroll_1 = function (evnt) {
stopMouseScroll_1();
mouseScrollTimeout_1 = setTimeout(function () {
if (mouseScrollTimeout_1) {
var scrollLeft = bodyWrapperElem_1.scrollLeft, scrollTop = bodyWrapperElem_1.scrollTop, clientHeight = bodyWrapperElem_1.clientHeight, scrollHeight = bodyWrapperElem_1.scrollHeight;
var topSize = Math.ceil(mouseScrollSpaceSize_1 * 50 / rowHeight_1);
if (isMouseScrollDown_1) {
if (scrollTop + clientHeight < scrollHeight) {
$xetable.scrollTo(scrollLeft, scrollTop + topSize);
startMouseScroll_1(evnt);
handleChecked_1(evnt);
}
else {
stopMouseScroll_1();
}
}
else {
if (scrollTop) {
$xetable.scrollTo(scrollLeft, scrollTop - topSize);
startMouseScroll_1(evnt);
handleChecked_1(evnt);
}
else {
stopMouseScroll_1();
}
}
}
}, 50);
};
addClass(el_1, 'drag--range');
document.onmousemove = function (evnt) {
evnt.preventDefault();
evnt.stopPropagation();
var clientY = evnt.clientY;
var boundingTop = getAbsolutePos(bodyWrapperElem_1).boundingTop;
// 如果超过可视区,触发滚动
if (clientY < boundingTop) {
isMouseScrollDown_1 = false;
mouseScrollSpaceSize_1 = boundingTop - clientY;
if (!mouseScrollTimeout_1) {
startMouseScroll_1(evnt);
}
}
else if (clientY > boundingTop + bodyWrapperElem_1.clientHeight) {
isMouseScrollDown_1 = true;
mouseScrollSpaceSize_1 = clientY - boundingTop - bodyWrapperElem_1.clientHeight;
if (!mouseScrollTimeout_1) {
startMouseScroll_1(evnt);
}
}
else if (mouseScrollTimeout_1) {
stopMouseScroll_1();
}
handleChecked_1(evnt);
};
document.onmouseup = function (evnt) {
stopMouseScroll_1();
removeClass(el_1, 'drag--range');
checkboxRangeElem_1.removeAttribute('style');
document.onmousemove = domMousemove_1;
document.onmouseup = domMouseup_1;
triggerEvent_1('end', evnt);
};
triggerEvent_1('start', evnt);
}
};
var handleCellMousedownEvent = function (evnt, params) {
var editConfig = props.editConfig, checkboxConfig = props.checkboxConfig, mouseConfig = props.mouseConfig;
var checkboxOpts = computeCheckboxOpts.value;
var mouseOpts = computeMouseOpts.value;
var editOpts = computeEditOpts.value;
if (mouseConfig && mouseOpts.area && $xetable.handleCellAreaEvent) {
return $xetable.handleCellAreaEvent(evnt, params);
}
else {
if (checkboxConfig && checkboxOpts.range) {
handleCheckboxRangeEvent(evnt, params);
}
if (mouseConfig && mouseOpts.selected) {
if (!editConfig || editOpts.mode === 'cell') {
$xetable.handleSelected(params, evnt);
}
}
}
};
var keyboardMethods = {
// 处理 Tab 键移动
moveTabSelected: function (args, isLeft, evnt) {
var editConfig = props.editConfig;
var afterFullData = internalData.afterFullData, visibleColumn = internalData.visibleColumn;
var editOpts = computeEditOpts.value;
var targetRow;
var targetRowIndex;
var targetColumnIndex;
var params = Object.assign({}, args);
var _rowIndex = $xetable.getVTRowIndex(params.row);
var _columnIndex = $xetable.getVTColumnIndex(params.column);
evnt.preventDefault();
if (isLeft) {
// 向左
if (_columnIndex <= 0) {
// 如果已经是第一列,则移动到上一行
if (_rowIndex > 0) {
targetRowIndex = _rowIndex - 1;
targetRow = afterFullData[targetRowIndex];
targetColumnIndex = visibleColumn.length - 1;
}
}
else {
targetColumnIndex = _columnIndex - 1;
}
}
else {
if (_columnIndex >= visibleColumn.length - 1) {
// 如果已经是第一列,则移动到上一行
if (_rowIndex < afterFullData.length - 1) {
targetRowIndex = _rowIndex + 1;
targetRow = afterFullData[targetRowIndex];
targetColumnIndex = 0;
}
}
else {
targetColumnIndex = _columnIndex + 1;
}
}
var targetColumn = visibleColumn[targetColumnIndex];
if (targetColumn) {
if (targetRow) {
params.rowIndex = targetRowIndex;
params.row = targetRow;
}
else {
params.rowIndex = _rowIndex;
}
params.columnIndex = targetColumnIndex;
params.column = targetColumn;
params.cell = $xetable.getCell(params.row, params.column);
if (editConfig) {
if (editOpts.trigger === 'click' || editOpts.trigger === 'dblclick') {
if (editOpts.mode === 'row') {
$xetable.handleActived(params, evnt);
}
else {
$xetable.scrollToRow(params.row, params.column)
.then(function () { return $xetable.handleSelected(params, evnt); });
}
}
}
else {
$xetable.scrollToRow(params.row, params.column)
.then(function () { return $xetable.handleSelected(params, evnt); });
}
}
},
// 处理当前行方向键移动
moveCurrentRow: function (isUpArrow, isDwArrow, evnt) {
var treeConfig = props.treeConfig;
var currentRow = reactData.currentRow;
var afterFullData = internalData.afterFullData;
var treeOpts = computeTreeOpts.value;
var childrenField = treeOpts.children || treeOpts.childrenField;
var targetRow;
evnt.preventDefault();
if (currentRow) {
if (treeConfig) {
var _a = XEUtils.findTree(afterFullData, function (item) { return item === currentRow; }, { children: childrenField }), index = _a.index, items = _a.items;
if (isUpArrow && index > 0) {
targetRow = items[index - 1];
}
else if (isDwArrow && index < items.length - 1) {
targetRow = items[index + 1];
}
}
else {
var _rowIndex = $xetable.getVTRowIndex(currentRow);
if (isUpArrow && _rowIndex > 0) {
targetRow = afterFullData[_rowIndex - 1];
}
else if (isDwArrow && _rowIndex < afterFullData.length - 1) {
targetRow = afterFullData[_rowIndex + 1];
}
}
}
else {
targetRow = afterFullData[0];
}
if (targetRow) {
var params_1 = {
$table: $xetable,
row: targetRow,
rowIndex: $xetable.getRowIndex(targetRow),
$rowIndex: $xetable.getVMRowIndex(targetRow)
};
$xetable.scrollToRow(targetRow)
.then(function () { return $xetable.triggerCurrentRowEvent(evnt, params_1); });
}
},
// 处理可编辑方向键移动
moveSelected: function (args, isLeftArrow, isUpArrow, isRightArrow, isDwArrow, evnt) {
var afterFullData = internalData.afterFullData, visibleColumn = internalData.visibleColumn;
var params = Object.assign({}, args);
var _rowIndex = $xetable.getVTRowIndex(params.row);
var _columnIndex = $xetable.getVTColumnIndex(params.column);
evnt.preventDefault();
if (isUpArrow && _rowIndex > 0) {
// 移动到上一行
params.rowIndex = _rowIndex - 1;
params.row = afterFullData[params.rowIndex];
}
else if (isDwArrow && _rowIndex < afterFullData.length - 1) {
// 移动到下一行
params.rowIndex = _rowIndex + 1;
params.row = afterFullData[params.rowIndex];
}
else if (isLeftArrow && _columnIndex) {
// 移动到左侧单元格
params.columnIndex = _columnIndex - 1;
params.column = visibleColumn[params.columnIndex];
}
else if (isRightArrow && _columnIndex < visibleColumn.length - 1) {
// 移动到右侧单元格
params.columnIndex = _columnIndex + 1;
params.column = visibleColumn[params.columnIndex];
}
$xetable.scrollToRow(params.row, params.column).then(function () {
params.cell = $xetable.getCell(params.row, params.column);
$xetable.handleSelected(params, evnt);
});
},
/**
* 表头单元格按下事件
*/
triggerHeaderCellMousedownEvent: function (evnt, params) {
var mouseConfig = props.mouseConfig;
var mouseOpts = computeMouseOpts.value;
if (mouseConfig && mouseOpts.area && $xetable.handleHeaderCellAreaEvent) {
var cell = evnt.currentTarget;
var triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag;
var triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag;
$xetable.handleHeaderCellAreaEvent(evnt, Object.assign({ cell: cell, triggerSort: triggerSort, triggerFilter: triggerFilter }, params));
}
$xetable.focus();
if ($xetable.closeMenu) {
$xetable.closeMenu();
}
},
/**
* 单元格按下事件
*/
triggerCellMousedownEvent: function (evnt, params) {
var cell = evnt.currentTarget;
params.cell = cell;
handleCellMousedownEvent(evnt, params);
$xetable.focus();
$xetable.closeFilter();
if ($xetable.closeMenu) {
$xetable.closeMenu();
}
}
};
return keyboardMethods;
}
};
export default tableKeyboardHook;