如何用JavaScript和jQuery实现Kendo TreeList带结构的复制粘贴?
实现Kendo TreeList多单元格结构化复制粘贴功能
完全可以通过JavaScript和jQuery实现该需求,以下是包含结构化复制到剪贴板和粘贴到TreeList指定位置的完整实现方案:
核心实现逻辑
1. 收集选中单元格的结构化数据
通过Kendo TreeList API获取选中单元格,按视觉行列顺序整理数据,同时关联对应列的字段信息,确保粘贴时能匹配数据字段。
2. 绑定复制快捷键(Ctrl+C)
监听键盘复制事件,将整理好的结构化数据转换为制表符分隔文本(兼容文本文件粘贴)和HTML表格格式(兼容富文本工具粘贴),写入系统剪贴板。
3. 绑定粘贴快捷键(Ctrl+V)
监听键盘粘贴事件,解析剪贴板数据,以当前选中的单元格为起始位置,批量更新TreeList数据源,支持自动填充现有行或新增行。
完整代码示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Kendo TreeList 复制粘贴示例</title> <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2023.1.117/styles/kendo.default-v2.min.css"/> <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://kendo.cdn.telerik.com/2023.1.117/js/kendo.all.min.js"></script> </head> <body> <div id="treeList"></div> <script> // 初始化TreeList const treeList = $("#treeList").kendoTreeList({ columns: [ { field: "name", title: "姓名" }, { field: "age", title: "年龄" } ], selectable: "multiple, cell", editable:"incell", dataSource: [ { id: 1, parentId: null, name: "Jane Doe", age: 22 }, { id: 2, parentId: 1, name: "John Doe", age: 24 }, { id: 3, parentId: 1, name: "Jenny Doe", age: 3 }, { id: 4, parentId: null, name: "Tom Smith", age: 30 }, { id: 5, parentId: 4, name: "Amy Smith", age: 5 } ] }).data("kendoTreeList"); // 收集选中单元格的结构化数据 function getSelectedCellsData() { const selectedCells = treeList.select(); if (selectedCells.length === 0) return null; // 按行分组,确保数据顺序正确 const rows = {}; selectedCells.each(function() { const cell = $(this); const row = cell.closest("tr"); const rowIndex = row.index(); const colIndex = cell.index(); const field = treeList.columns[colIndex].field; const value = cell.text().trim(); if (!rows[rowIndex]) rows[rowIndex] = []; rows[rowIndex].push({ field, value, colIndex }); }); // 转换为有序的行数据数组 return Object.values(rows).map(rowCells => { // 按列索引排序,确保列顺序正确 rowCells.sort((a, b) => a.colIndex - b.colIndex); return rowCells; }); } // 绑定复制事件(Ctrl+C) $(document).on("keydown", function(e) { if ((e.ctrlKey || e.metaKey) && e.key === "c") { const selectedData = getSelectedCellsData(); if (!selectedData) return; // 转换为制表符分隔文本(用于粘贴到文本文件) const textContent = selectedData.map(row => { return row.map(cell => cell.value).join("\t"); }).join("\n"); // 转换为HTML表格(用于富文本粘贴) const htmlContent = `<table><tbody>${selectedData.map(row => { return `<tr>${row.map(cell => `<td>${cell.value}</td>`).join("")}</tr>`; }).join("")}</tbody></table>`; // 写入剪贴板,同时支持文本和HTML格式 navigator.clipboard.write([ new ClipboardItem({ "text/plain": new Blob([textContent], { type: "text/plain" }), "text/html": new Blob([htmlContent], { type: "text/html" }) }) ]); e.preventDefault(); } }); // 绑定粘贴事件(Ctrl+V) $(document).on("keydown", function(e) { if ((e.ctrlKey || e.metaKey) && e.key === "v") { const targetCells = treeList.select(); if (targetCells.length === 0) return; // 获取粘贴起始位置的单元格 const firstTargetCell = $(targetCells[0]); const targetRow = firstTargetCell.closest("tr"); const targetRowUid = targetRow.data("uid"); const targetColIndex = firstTargetCell.index(); // 获取剪贴板数据 navigator.clipboard.read().then(items => { for (const item of items) { if (item.types.includes("text/plain")) { item.getType("text/plain").then(blob => { blob.text().then(text => { // 解析制表符分隔的文本为二维数组 const pastedData = text.split("\n").map(line => line.split("\t")); if (pastedData.length === 0) return; // 从起始位置开始批量更新数据 const dataSource = treeList.dataSource; const targetItem = dataSource.getByUid(targetRowUid); if (!targetItem) return; // 获取目标行在数据源中的位置 const targetIndex = dataSource.indexOf(targetItem); let currentRowIndex = targetIndex; pastedData.forEach((rowData, rowIdx) => { // 确保数据源中有足够的行,超出则新增(可根据需求调整层级逻辑) let currentItem = dataSource.at(currentRowIndex); if (!currentItem) { // 默认新增为根节点,可修改parentId调整层级 currentItem = { id: Date.now() + rowIdx, parentId: null }; dataSource.add(currentItem); } // 更新当前行的对应列数据 rowData.forEach((cellValue, colOffset) => { const targetCol = treeList.columns[targetColIndex + colOffset]; if (targetCol && cellValue) { currentItem[targetCol.field] = cellValue; } }); currentRowIndex++; }); // 刷新TreeList dataSource.sync(); }); }); } } }); e.preventDefault(); } }); </script> </body> </html>
功能说明
- 复制功能:选中任意多单元格后按Ctrl+C,数据会以制表符分隔格式存入剪贴板,粘贴到记事本、Excel等工具时会自动保留表格结构。
- 粘贴功能:选中目标起始单元格后按Ctrl+V,复制的数据会从该位置开始批量填充到TreeList中,超出现有行时会自动新增行(可修改代码调整新增行的层级逻辑)。
- 兼容性:支持现代浏览器的Clipboard API,如需兼容旧版浏览器可替换为
document.execCommand方案。
内容的提问来源于stack exchange,提问作者Sonic
相关产品推荐
相关产品推荐

