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.
318 lines • 9.62 kB
JavaScript
function generateShortUUID() {
return 'xxxxxxxxxxxxxxxxxx'.replace(/[x]/g, function (c) {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function throttle(func, delay) {
let lastCalledTime = 0;
let timeoutId;
return function (...args) {
const now = new Date().getTime();
const elapsedTime = now - lastCalledTime;
if (!lastCalledTime || elapsedTime >= delay) {
func.apply(this, args);
lastCalledTime = now;
}
else if (!timeoutId) {
timeoutId = setTimeout(() => {
func.apply(this, args);
lastCalledTime = new Date().getTime();
timeoutId = undefined;
}, delay - elapsedTime);
}
return undefined;
};
}
/**
* 根据children获取最大深度
* @param data
* @returns
*/
function getMaxRow(data = []) {
if (data.length) {
return data.map((item) => getMaxRow(item.children) + 1).sort((a, b) => b - a)[0];
}
return 0;
}
function sortFixed(arr = []) {
let lefts = [];
let centers = [];
let right = [];
arr.forEach((item) => {
if (item.fixed === 'left') {
lefts.push(item);
}
else if (item.fixed === 'right') {
right.push(item);
}
else {
centers.push(item);
}
});
return [
...lefts.sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)),
...centers.sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)),
...right.sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)),
];
}
function calCrossSpan(arr = [], maxRow = 1, level = 0) {
return arr.map((config) => {
if (config.children) {
let colspan = 0;
let fixed = config.fixed;
config.children.forEach((item) => {
item.fixed = fixed;
});
const children = calCrossSpan(config.children, maxRow - 1, level + 1);
if (children) {
children.forEach((item) => {
colspan += item.colspan ?? 0;
});
}
return {
...config,
width: config.width,
level,
rowspan: 1,
colspan,
children,
};
}
return {
...config,
level,
rowspan: maxRow,
colspan: 1,
};
});
}
function toLeaf(arr = []) {
let tmp = [];
arr.forEach((item) => {
if (item.children) {
tmp = tmp.concat(toLeaf(item.children));
}
else {
tmp.push(item);
}
});
return tmp;
}
function debounce(func, delay) {
let timeoutId = null;
return function (...args) {
if (timeoutId !== null) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}
const regUniversalNewLine = /^(\r\n|\n\r|\r|\n)/;
const regNextCellNoQuotes = /^[^\t\r\n]+/;
const regNextEmptyCell = /^\t/;
/**
* @decodeSpreadsheetStr
* @desc Decode spreadsheet string into array. refer from http://github.com/warpech/sheetclip/
* @param {string} str The string to parse.
* @returns {array}
*/
function decodeSpreadsheetStr(str) {
let arr = [['']];
if (str.length === 0) {
return arr;
}
let column = 0;
let row = 0;
let lastLength;
while (str.length > 0) {
if (lastLength === str.length) {
// In the case If in last cycle we didn't match anything, we have to leave the infinite loop
break;
}
lastLength = str.length;
if (str.match(regNextEmptyCell)) {
str = str.replace(regNextEmptyCell, '');
column += 1;
arr[row][column] = '';
}
else if (str.match(regUniversalNewLine)) {
str = str.replace(regUniversalNewLine, '');
column = 0;
row += 1;
arr[row] = [''];
}
else {
let nextCell = '';
if (str.startsWith('"')) {
let quoteNo = 0;
let isStillCell = true;
while (isStillCell) {
const nextChar = str.slice(0, 1);
if (nextChar === '"') {
quoteNo += 1;
}
nextCell += nextChar;
str = str.slice(1);
if (str.length === 0 || (str.match(/^[\t\r\n]/) && quoteNo % 2 === 0)) {
isStillCell = false;
}
}
nextCell = nextCell
.replace(/^"/, '')
.replace(/"$/, '')
.replace(/["]*/g, (match) => new Array(Math.floor(match.length / 2)).fill('"').join(''));
}
else {
const matchedText = str.match(regNextCellNoQuotes);
nextCell = matchedText ? matchedText[0] : '';
str = str.slice(nextCell.length);
}
arr[row][column] = nextCell;
}
}
// 去除 excel 最后一个多余的换行数据
if (Array.isArray(arr) && arr.length > 1) {
if (arr[arr.length - 1].length === 1 && arr[arr.length - 1][0] === '') {
arr = arr.slice(0, arr.length - 1);
}
}
return arr;
}
/**
* @decodeSpreadsheetStr
* @desc encode array to spreadsheet string. refer from http://github.com/warpech/sheetclip/
* @param {array} str The string to parse.
* @returns {string}
*/
function encodeToSpreadsheetStr(arr) {
let r;
let rLen;
let c;
let cLen;
let str = '';
let val;
for (r = 0, rLen = arr.length; r < rLen; r += 1) {
cLen = arr[r].length;
for (c = 0; c < cLen; c += 1) {
if (c > 0) {
str += '\t';
}
val = arr[r][c];
if (typeof val === 'string') {
if (val.indexOf('\n') > -1) {
str += `"${val.replace(/"/g, '""')}"`;
}
else {
str += val;
}
}
else if (val === null || val === void 0) {
// void 0 resolves to undefined
str += '';
}
else {
str += val;
}
}
if (r !== rLen - 1) {
str += '\n';
}
}
return str;
}
// 获取合并单元格的spanArr,针对行数据相同key合并
function getSpanArrByRow(list, key, relationRowKeys = []) {
let contactDot = 0;
const spanArr = [];
list.forEach((item, index) => {
if (index === 0) {
spanArr.push(1);
}
else {
const curValue = relationRowKeys.reduce((acc, key) => `${acc}${item[key] ?? ''}`, '') || item[key];
const pValue = relationRowKeys.reduce((acc, key) => `${acc}${list[index - 1][key] ?? ''}`, '') || list[index - 1][key];
if (curValue === pValue) {
spanArr[contactDot] += 1;
spanArr.push(0);
}
else {
spanArr.push(1);
contactDot = index;
}
}
});
return spanArr;
}
function getSpanObjByColumn(row, columns) {
let keyPre = '';
let keyDot = '';
const spanObj = {};
columns.forEach((item, index) => {
if (index === 0) {
keyPre = item.key;
keyDot = item.key;
spanObj[item.key] = 1;
}
else {
// eslint-disable-next-line no-undef
if (row[item.key] === row[keyPre]) {
spanObj[item.key] = 0;
spanObj[keyDot] += 1;
}
else {
spanObj[item.key] = 1;
keyPre = item.key;
keyDot = item.key;
}
}
});
return spanObj;
}
// 合并行单元格
function mergeRowCell(params, mergeRowkey, relationRowKeys = []) {
// 合并单元格
const { visibleRows, rowIndex, headIndex } = params;
const spanArr = getSpanArrByRow(visibleRows, mergeRowkey, relationRowKeys);
if (spanArr[rowIndex - headIndex] === 0) {
return {
rowspan: 0,
colspan: 0,
relationRowKeys,
mergeRow: true,
};
}
return {
rowspan: spanArr[rowIndex - headIndex],
colspan: 1,
relationRowKeys,
mergeRow: true,
};
}
function mergeColCell(params, mergeColKeys = []) {
const { column, row, visibleLeafColumns } = params;
const columns = visibleLeafColumns.filter((item) => mergeColKeys.includes(item.key));
// 合并动态列单元格
if (mergeColKeys.includes(column.key)) {
const spanObj = getSpanObjByColumn(row, columns);
if (spanObj[column.key] === 0) {
return {
rowspan: 0,
colspan: 0,
relationColKeys: mergeColKeys,
mergeCol: true,
};
}
return {
rowspan: 1,
colspan: spanObj[column.key],
relationColKeys: mergeColKeys,
mergeCol: true,
};
}
}
export { debounce, throttle, generateShortUUID, toLeaf, sortFixed, calCrossSpan, getMaxRow, decodeSpreadsheetStr, encodeToSpreadsheetStr, mergeRowCell, mergeColCell, getSpanArrByRow, getSpanObjByColumn, };
//# sourceMappingURL=util.js.map