@ag-grid-enterprise/clipboard
Version:
Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue
905 lines (900 loc) • 33.1 kB
JavaScript
// enterprise-modules/clipboard/src/clipboardModule.ts
import { ModuleNames, _defineModule } from "@ag-grid-community/core";
import { CsvExportModule } from "@ag-grid-community/csv-export";
import { EnterpriseCoreModule } from "@ag-grid-enterprise/core";
// enterprise-modules/clipboard/src/clipboard/clipboardApi.ts
function copyToClipboard(beans, params) {
beans.clipboardService?.copyToClipboard(params);
}
function cutToClipboard(beans, params) {
beans.clipboardService?.cutToClipboard(params);
}
function copySelectedRowsToClipboard(beans, params) {
beans.clipboardService?.copySelectedRowsToClipboard(params);
}
function copySelectedRangeToClipboard(beans, params) {
beans.clipboardService?.copySelectedRangeToClipboard(params);
}
function copySelectedRangeDown(beans) {
beans.clipboardService?.copyRangeDown();
}
function pasteFromClipboard(beans) {
beans.clipboardService?.pasteFromClipboard();
}
// enterprise-modules/clipboard/src/clipboard/clipboardService.ts
import {
BeanStub,
ChangedPath,
_exists,
_getActiveDomElement,
_getDocument,
_isClientSideRowModel,
_last,
_removeFromArray,
_warnOnce
} from "@ag-grid-community/core";
var SOURCE_PASTE = "paste";
var EXPORT_TYPE_DRAG_COPY = "dragCopy";
var EXPORT_TYPE_CLIPBOARD = "clipboard";
var apiError = (method) => `AG Grid: Unable to use the Clipboard API (navigator.clipboard.${method}()). The reason why it could not be used has been logged in the previous line. For this reason the grid has defaulted to using a workaround which doesn't perform as well. Either fix why Clipboard API is blocked, OR stop this message from appearing by setting grid property suppressClipboardApi=true (which will default the grid to using the workaround rather than the API.`;
var ClipboardService = class _ClipboardService extends BeanStub {
constructor() {
super(...arguments);
this.beanName = "clipboardService";
this.lastPasteOperationTime = 0;
this.navigatorApiFailed = false;
}
wireBeans(beans) {
this.csvCreator = beans.csvCreator;
this.selectionService = beans.selectionService;
this.rowModel = beans.rowModel;
this.ctrlsService = beans.ctrlsService;
this.valueService = beans.valueService;
this.focusService = beans.focusService;
this.rowRenderer = beans.rowRenderer;
this.visibleColsService = beans.visibleColsService;
this.funcColsService = beans.funcColsService;
this.cellNavigationService = beans.cellNavigationService;
this.cellPositionUtils = beans.cellPositionUtils;
this.rowPositionUtils = beans.rowPositionUtils;
this.rangeService = beans.rangeService;
}
postConstruct() {
if (_isClientSideRowModel(this.gos)) {
this.clientSideRowModel = this.rowModel;
}
this.ctrlsService.whenReady(this, (p) => {
this.gridCtrl = p.gridCtrl;
});
}
pasteFromClipboard() {
const allowNavigator = !this.gos.get("suppressClipboardApi");
if (allowNavigator && !this.navigatorApiFailed && navigator.clipboard && navigator.clipboard.readText) {
navigator.clipboard.readText().then(this.processClipboardData.bind(this)).catch((e) => {
_warnOnce(`${e}
${apiError("readText")}`);
this.navigatorApiFailed = true;
this.pasteFromClipboardLegacy();
});
} else {
this.pasteFromClipboardLegacy();
}
}
pasteFromClipboardLegacy() {
let defaultPrevented = false;
const handlePasteEvent = (e) => {
const currentPastOperationTime = (/* @__PURE__ */ new Date()).getTime();
if (currentPastOperationTime - this.lastPasteOperationTime < 50) {
defaultPrevented = true;
e.preventDefault();
}
this.lastPasteOperationTime = currentPastOperationTime;
};
this.executeOnTempElement(
(textArea) => {
textArea.addEventListener("paste", handlePasteEvent);
textArea.focus({ preventScroll: true });
},
(element) => {
const data = element.value;
if (!defaultPrevented) {
this.processClipboardData(data);
} else {
this.refocusLastFocusedCell();
}
element.removeEventListener("paste", handlePasteEvent);
}
);
}
refocusLastFocusedCell() {
const focusedCell = this.focusService.getFocusedCell();
if (focusedCell) {
this.focusService.setFocusedCell({
rowIndex: focusedCell.rowIndex,
column: focusedCell.column,
rowPinned: focusedCell.rowPinned,
forceBrowserFocus: true
});
}
}
getClipboardDelimiter() {
const delimiter = this.gos.get("clipboardDelimiter");
return _exists(delimiter) ? delimiter : " ";
}
processClipboardData(data) {
if (data == null) {
return;
}
let parsedData = _ClipboardService.stringToArray(data, this.getClipboardDelimiter());
const userFunc = this.gos.getCallback("processDataFromClipboard");
if (userFunc) {
parsedData = userFunc({ data: parsedData });
}
if (parsedData == null) {
return;
}
if (this.gos.get("suppressLastEmptyLineOnPaste")) {
this.removeLastLineIfBlank(parsedData);
}
const pasteOperation = (cellsToFlash, updatedRowNodes, focusedCell, changedPath) => {
const rangeActive = this.rangeService?.isMoreThanOneCell();
const pasteIntoRange = rangeActive && !this.hasOnlyOneValueToPaste(parsedData);
if (pasteIntoRange) {
this.pasteIntoActiveRange(this.rangeService, parsedData, cellsToFlash, updatedRowNodes, changedPath);
} else {
this.pasteStartingFromFocusedCell(parsedData, cellsToFlash, updatedRowNodes, focusedCell, changedPath);
}
};
this.doPasteOperation(pasteOperation);
}
// This will parse a delimited string into an array of arrays.
static stringToArray(strData, delimiter = ",") {
const data = [];
const isNewline = (char) => char === "\r" || char === "\n";
let insideQuotedField = false;
if (strData === "") {
return [[""]];
}
for (let row = 0, column = 0, position = 0; position < strData.length; position++) {
const previousChar = strData[position - 1];
const currentChar = strData[position];
const nextChar = strData[position + 1];
const ensureDataExists = () => {
if (!data[row]) {
data[row] = [];
}
if (!data[row][column]) {
data[row][column] = "";
}
};
ensureDataExists();
if (currentChar === '"') {
if (insideQuotedField) {
if (nextChar === '"') {
data[row][column] += '"';
position++;
} else {
insideQuotedField = false;
}
} else if (previousChar === void 0 || previousChar === delimiter || isNewline(previousChar)) {
insideQuotedField = true;
}
}
if (!insideQuotedField && currentChar !== '"') {
if (currentChar === delimiter) {
column++;
ensureDataExists();
continue;
} else if (isNewline(currentChar)) {
column = 0;
row++;
ensureDataExists();
if (currentChar === "\r" && nextChar === "\n") {
position++;
}
continue;
}
}
data[row][column] += currentChar;
}
return data;
}
// common code to paste operations, e.g. paste to cell, paste to range, and copy range down
doPasteOperation(pasteOperationFunc) {
const source = "clipboard";
this.eventService.dispatchEvent({
type: "pasteStart",
source
});
let changedPath;
if (this.clientSideRowModel) {
const onlyChangedColumns = this.gos.get("aggregateOnlyChangedColumns");
changedPath = new ChangedPath(onlyChangedColumns, this.clientSideRowModel.getRootNode());
}
const cellsToFlash = {};
const updatedRowNodes = [];
const focusedCell = this.focusService.getFocusedCell();
pasteOperationFunc(cellsToFlash, updatedRowNodes, focusedCell, changedPath);
const nodesToRefresh = [...updatedRowNodes];
if (changedPath) {
this.clientSideRowModel.doAggregate(changedPath);
changedPath.forEachChangedNodeDepthFirst((rowNode) => {
nodesToRefresh.push(rowNode);
});
}
this.rowRenderer.refreshCells({ rowNodes: nodesToRefresh });
this.dispatchFlashCells(cellsToFlash);
this.fireRowChanged(updatedRowNodes);
this.refocusLastFocusedCell();
this.eventService.dispatchEvent({
type: "pasteEnd",
source
});
}
pasteIntoActiveRange(rangeService, clipboardData, cellsToFlash, updatedRowNodes, changedPath) {
const abortRepeatingPasteIntoRows = this.getRangeSize(rangeService) % clipboardData.length != 0;
let indexOffset = 0;
let dataRowIndex = 0;
const rowCallback = (currentRow, rowNode, columns, index) => {
const atEndOfClipboardData = index - indexOffset >= clipboardData.length;
if (atEndOfClipboardData) {
if (abortRepeatingPasteIntoRows) {
return;
}
indexOffset += dataRowIndex;
dataRowIndex = 0;
}
const currentRowData = clipboardData[index - indexOffset];
updatedRowNodes.push(rowNode);
const processCellFromClipboardFunc = this.gos.getCallback("processCellFromClipboard");
columns.forEach((column, idx) => {
if (!column.isCellEditable(rowNode) || column.isSuppressPaste(rowNode)) {
return;
}
if (idx >= currentRowData.length) {
idx = idx % currentRowData.length;
}
const newValue = this.processCell(
rowNode,
column,
currentRowData[idx],
EXPORT_TYPE_DRAG_COPY,
processCellFromClipboardFunc,
true
);
rowNode.setDataValue(column, newValue, SOURCE_PASTE);
if (changedPath) {
changedPath.addParentNode(rowNode.parent, [column]);
}
const { rowIndex, rowPinned } = currentRow;
const cellId = this.cellPositionUtils.createIdFromValues({ rowIndex, column, rowPinned });
cellsToFlash[cellId] = true;
});
dataRowIndex++;
};
this.iterateActiveRanges(false, rowCallback);
}
getDisplayedColumnsStartingAt(column) {
let currentColumn = column;
const columns = [];
while (currentColumn != null) {
columns.push(currentColumn);
currentColumn = this.visibleColsService.getColAfter(currentColumn);
}
return columns;
}
pasteStartingFromFocusedCell(parsedData, cellsToFlash, updatedRowNodes, focusedCell, changedPath) {
if (!focusedCell) {
return;
}
const currentRow = { rowIndex: focusedCell.rowIndex, rowPinned: focusedCell.rowPinned };
const columnsToPasteInto = this.getDisplayedColumnsStartingAt(focusedCell.column);
if (this.isPasteSingleValueIntoRange(parsedData)) {
this.pasteSingleValueIntoRange(parsedData, updatedRowNodes, cellsToFlash, changedPath);
} else {
this.pasteMultipleValues(
parsedData,
currentRow,
updatedRowNodes,
columnsToPasteInto,
cellsToFlash,
EXPORT_TYPE_CLIPBOARD,
changedPath
);
}
}
// if range is active, and only one cell, then we paste this cell into all cells in the active range.
isPasteSingleValueIntoRange(parsedData) {
return this.hasOnlyOneValueToPaste(parsedData) && this.rangeService != null && !this.rangeService.isEmpty();
}
pasteSingleValueIntoRange(parsedData, updatedRowNodes, cellsToFlash, changedPath) {
const value = parsedData[0][0];
const rowCallback = (currentRow, rowNode, columns) => {
updatedRowNodes.push(rowNode);
columns.forEach(
(column) => this.updateCellValue(rowNode, column, value, cellsToFlash, EXPORT_TYPE_CLIPBOARD, changedPath)
);
};
this.iterateActiveRanges(false, rowCallback);
}
hasOnlyOneValueToPaste(parsedData) {
return parsedData.length === 1 && parsedData[0].length === 1;
}
copyRangeDown() {
if (!this.rangeService || this.rangeService.isEmpty()) {
return;
}
const firstRowValues = [];
const pasteOperation = (cellsToFlash, updatedRowNodes, focusedCell, changedPath) => {
const processCellForClipboardFunc = this.gos.getCallback("processCellForClipboard");
const processCellFromClipboardFunc = this.gos.getCallback("processCellFromClipboard");
const rowCallback = (currentRow, rowNode, columns) => {
if (!firstRowValues.length) {
columns.forEach((column) => {
const value = this.processCell(
rowNode,
column,
this.valueService.getValue(column, rowNode),
EXPORT_TYPE_DRAG_COPY,
processCellForClipboardFunc,
false,
true
);
firstRowValues.push(value);
});
} else {
updatedRowNodes.push(rowNode);
columns.forEach((column, index) => {
if (!column.isCellEditable(rowNode) || column.isSuppressPaste(rowNode)) {
return;
}
const firstRowValue = this.processCell(
rowNode,
column,
firstRowValues[index],
EXPORT_TYPE_DRAG_COPY,
processCellFromClipboardFunc,
true
);
rowNode.setDataValue(column, firstRowValue, SOURCE_PASTE);
if (changedPath) {
changedPath.addParentNode(rowNode.parent, [column]);
}
const { rowIndex, rowPinned } = currentRow;
const cellId = this.cellPositionUtils.createIdFromValues({ rowIndex, column, rowPinned });
cellsToFlash[cellId] = true;
});
}
};
this.iterateActiveRanges(true, rowCallback);
};
this.doPasteOperation(pasteOperation);
}
removeLastLineIfBlank(parsedData) {
const lastLine = _last(parsedData);
const lastLineIsBlank = lastLine && lastLine.length === 1 && lastLine[0] === "";
if (lastLineIsBlank) {
if (parsedData.length === 1) {
return;
}
_removeFromArray(parsedData, lastLine);
}
}
fireRowChanged(rowNodes) {
if (this.gos.get("editType") !== "fullRow") {
return;
}
rowNodes.forEach((rowNode) => {
this.eventService.dispatchEvent({
type: "rowValueChanged",
node: rowNode,
data: rowNode.data,
rowIndex: rowNode.rowIndex,
rowPinned: rowNode.rowPinned
});
});
}
pasteMultipleValues(clipboardGridData, currentRow, updatedRowNodes, columnsToPasteInto, cellsToFlash, type, changedPath) {
let rowPointer = currentRow;
const skipGroupRows = this.clientSideRowModel != null && !this.gos.get("enableGroupEdit") && !this.gos.get("treeData");
const getNextGoodRowNode = () => {
while (true) {
if (!rowPointer) {
return null;
}
const res = this.rowPositionUtils.getRowNode(rowPointer);
rowPointer = this.cellNavigationService.getRowBelow({
rowPinned: rowPointer.rowPinned,
rowIndex: rowPointer.rowIndex
});
if (res == null) {
return null;
}
const skipRow = res.detail || res.footer || skipGroupRows && res.group;
if (!skipRow) {
return res;
}
}
};
clipboardGridData.forEach((clipboardRowData) => {
const rowNode = getNextGoodRowNode();
if (!rowNode) {
return;
}
clipboardRowData.forEach(
(value, index) => this.updateCellValue(rowNode, columnsToPasteInto[index], value, cellsToFlash, type, changedPath)
);
updatedRowNodes.push(rowNode);
});
}
updateCellValue(rowNode, column, value, cellsToFlash, type, changedPath) {
if (!rowNode || !column || !column.isCellEditable(rowNode) || column.isSuppressPaste(rowNode)) {
return;
}
const processedValue = this.processCell(
rowNode,
column,
value,
type,
this.gos.getCallback("processCellFromClipboard"),
true
);
rowNode.setDataValue(column, processedValue, SOURCE_PASTE);
const { rowIndex, rowPinned } = rowNode;
const cellId = this.cellPositionUtils.createIdFromValues({ rowIndex, column, rowPinned });
cellsToFlash[cellId] = true;
if (changedPath) {
changedPath.addParentNode(rowNode.parent, [column]);
}
}
copyToClipboard(params = {}) {
this.copyOrCutToClipboard(params);
}
cutToClipboard(params = {}, source = "api") {
if (this.gos.get("suppressCutToClipboard")) {
return;
}
this.eventService.dispatchEvent({
type: "cutStart",
source
});
this.copyOrCutToClipboard(params, true);
this.eventService.dispatchEvent({
type: "cutEnd",
source
});
}
copyOrCutToClipboard(params, cut) {
let { includeHeaders, includeGroupHeaders } = params;
if (includeHeaders == null) {
includeHeaders = this.gos.get("copyHeadersToClipboard");
}
if (includeGroupHeaders == null) {
includeGroupHeaders = this.gos.get("copyGroupHeadersToClipboard");
}
const copyParams = { includeHeaders, includeGroupHeaders };
const rowSelection = this.gos.get("rowSelection");
const cellSelection = this.gos.get("cellSelection");
let cellClearType = null;
if (this.shouldCopyCells(cellSelection, rowSelection)) {
this.copySelectedRangeToClipboard(copyParams);
cellClearType = 0 /* CellRange */;
} else if (this.shouldCopyRows(rowSelection)) {
this.copySelectedRowsToClipboard(copyParams);
cellClearType = 1 /* SelectedRows */;
} else if (this.focusService.isAnyCellFocused()) {
this.copyFocusedCellToClipboard(copyParams);
cellClearType = 2 /* FocusedCell */;
}
if (cut && cellClearType !== null) {
this.clearCellsAfterCopy(cellClearType);
}
}
shouldCopyCells(cellSelection, rowSelection) {
if (!this.rangeService || this.rangeService.isEmpty()) {
return false;
}
if (cellSelection) {
const shouldCopyRowsInstead = typeof rowSelection === "object" && rowSelection.copySelectedRows && !this.selectionService.isEmpty();
return !shouldCopyRowsInstead;
} else {
const suppressCopySingleCellRanges = this.gos.get("suppressCopySingleCellRanges");
const shouldSkip = !this.rangeService.isMoreThanOneCell() && suppressCopySingleCellRanges;
return !shouldSkip;
}
}
shouldCopyRows(rowSelection) {
if (this.selectionService.isEmpty()) {
return false;
}
if (rowSelection && typeof rowSelection !== "string") {
return rowSelection.copySelectedRows ?? false;
} else {
return !this.gos.get("suppressCopyRowsToClipboard");
}
}
clearCellsAfterCopy(type) {
this.eventService.dispatchEvent({ type: "keyShortcutChangedCellStart" });
if (type === 0 /* CellRange */) {
this.rangeService.clearCellRangeCellValues({ cellEventSource: "clipboardService" });
} else if (type === 1 /* SelectedRows */) {
this.clearSelectedRows();
} else {
const focusedCell = this.focusService.getFocusedCell();
if (focusedCell == null) {
return;
}
const rowNode = this.rowPositionUtils.getRowNode(focusedCell);
if (rowNode) {
this.clearCellValue(rowNode, focusedCell.column);
}
}
this.eventService.dispatchEvent({ type: "keyShortcutChangedCellEnd" });
}
clearSelectedRows() {
const selected = this.selectionService.getSelectedNodes();
const columns = this.visibleColsService.getAllCols();
for (const row of selected) {
for (const col of columns) {
this.clearCellValue(row, col);
}
}
}
clearCellValue(rowNode, column) {
if (!column.isCellEditable(rowNode)) {
return;
}
const emptyValue = this.valueService.getDeleteValue(column, rowNode);
rowNode.setDataValue(column, emptyValue, "clipboardService");
}
iterateActiveRanges(onlyFirst, rowCallback, columnCallback) {
if (!this.rangeService || this.rangeService.isEmpty()) {
return;
}
const cellRanges = this.rangeService.getCellRanges();
if (onlyFirst) {
this.iterateActiveRange(cellRanges[0], rowCallback, columnCallback, true);
} else {
cellRanges.forEach(
(range, idx) => this.iterateActiveRange(range, rowCallback, columnCallback, idx === cellRanges.length - 1)
);
}
}
iterateActiveRange(range, rowCallback, columnCallback, isLastRange) {
if (!this.rangeService) {
return;
}
let currentRow = this.rangeService.getRangeStartRow(range);
const lastRow = this.rangeService.getRangeEndRow(range);
if (columnCallback && range.columns) {
columnCallback(range.columns);
}
let rangeIndex = 0;
let isLastRow = false;
while (!isLastRow && currentRow != null) {
const rowNode = this.rowPositionUtils.getRowNode(currentRow);
isLastRow = this.rowPositionUtils.sameRow(currentRow, lastRow);
rowCallback(currentRow, rowNode, range.columns, rangeIndex++, isLastRow && isLastRange);
currentRow = this.cellNavigationService.getRowBelow(currentRow);
}
}
copySelectedRangeToClipboard(params = {}) {
if (!this.rangeService || this.rangeService.isEmpty()) {
return;
}
const allRangesMerge = this.rangeService.areAllRangesAbleToMerge();
const { data, cellsToFlash } = allRangesMerge ? this.buildDataFromMergedRanges(this.rangeService, params) : this.buildDataFromRanges(this.rangeService, params);
this.copyDataToClipboard(data);
this.dispatchFlashCells(cellsToFlash);
}
buildDataFromMergedRanges(rangeService, params) {
const columnsSet = /* @__PURE__ */ new Set();
const ranges = rangeService.getCellRanges();
const rowPositionsMap = /* @__PURE__ */ new Map();
const allRowPositions = [];
const allCellsToFlash = {};
ranges.forEach((range) => {
range.columns.forEach((col) => columnsSet.add(col));
const { rowPositions, cellsToFlash } = this.getRangeRowPositionsAndCellsToFlash(rangeService, range);
rowPositions.forEach((rowPosition) => {
const rowPositionAsString = `${rowPosition.rowIndex}-${rowPosition.rowPinned || "null"}`;
if (!rowPositionsMap.get(rowPositionAsString)) {
rowPositionsMap.set(rowPositionAsString, true);
allRowPositions.push(rowPosition);
}
});
Object.assign(allCellsToFlash, cellsToFlash);
});
const allColumns = this.visibleColsService.getAllCols();
const exportedColumns = Array.from(columnsSet);
exportedColumns.sort((a, b) => {
const posA = allColumns.indexOf(a);
const posB = allColumns.indexOf(b);
return posA - posB;
});
const data = this.buildExportParams({
columns: exportedColumns,
rowPositions: allRowPositions,
includeHeaders: params.includeHeaders,
includeGroupHeaders: params.includeGroupHeaders
});
return { data, cellsToFlash: allCellsToFlash };
}
buildDataFromRanges(rangeService, params) {
const ranges = rangeService.getCellRanges();
const data = [];
const allCellsToFlash = {};
ranges.forEach((range) => {
const { rowPositions, cellsToFlash } = this.getRangeRowPositionsAndCellsToFlash(rangeService, range);
Object.assign(allCellsToFlash, cellsToFlash);
data.push(
this.buildExportParams({
columns: range.columns,
rowPositions,
includeHeaders: params.includeHeaders,
includeGroupHeaders: params.includeGroupHeaders
})
);
});
return { data: data.join("\n"), cellsToFlash: allCellsToFlash };
}
getRangeRowPositionsAndCellsToFlash(rangeService, range) {
const rowPositions = [];
const cellsToFlash = {};
const startRow = rangeService.getRangeStartRow(range);
const lastRow = rangeService.getRangeEndRow(range);
let node = startRow;
while (node) {
rowPositions.push(node);
range.columns.forEach((column) => {
const { rowIndex, rowPinned } = node;
const cellId = this.cellPositionUtils.createIdFromValues({ rowIndex, column, rowPinned });
cellsToFlash[cellId] = true;
});
if (this.rowPositionUtils.sameRow(node, lastRow)) {
break;
}
node = this.cellNavigationService.getRowBelow(node);
}
return { rowPositions, cellsToFlash };
}
getCellsToFlashFromRowNodes(rowNodes) {
const allDisplayedColumns = this.visibleColsService.getAllCols();
const cellsToFlash = {};
for (let i = 0; i < rowNodes.length; i++) {
const { rowIndex, rowPinned } = rowNodes[i];
if (rowIndex == null) {
continue;
}
for (let j = 0; j < allDisplayedColumns.length; j++) {
const column = allDisplayedColumns[j];
const cellId = this.cellPositionUtils.createIdFromValues({ rowIndex, column, rowPinned });
cellsToFlash[cellId] = true;
}
}
return cellsToFlash;
}
copyFocusedCellToClipboard(params = {}) {
const focusedCell = this.focusService.getFocusedCell();
if (focusedCell == null) {
return;
}
const cellId = this.cellPositionUtils.createId(focusedCell);
const currentRow = { rowPinned: focusedCell.rowPinned, rowIndex: focusedCell.rowIndex };
const column = focusedCell.column;
const data = this.buildExportParams({
columns: [column],
rowPositions: [currentRow],
includeHeaders: params.includeHeaders,
includeGroupHeaders: params.includeGroupHeaders
});
this.copyDataToClipboard(data);
this.dispatchFlashCells({ [cellId]: true });
}
copySelectedRowsToClipboard(params = {}) {
const { columnKeys, includeHeaders, includeGroupHeaders } = params;
const data = this.buildExportParams({
columns: columnKeys,
includeHeaders,
includeGroupHeaders
});
this.copyDataToClipboard(data);
const rowNodes = this.selectionService.getSelectedNodes() || [];
this.dispatchFlashCells(this.getCellsToFlashFromRowNodes(rowNodes));
}
buildExportParams(params) {
const { columns, rowPositions, includeHeaders = false, includeGroupHeaders = false } = params;
const exportParams = {
columnKeys: columns,
rowPositions,
skipColumnHeaders: !includeHeaders,
skipColumnGroupHeaders: !includeGroupHeaders,
suppressQuotes: true,
columnSeparator: this.getClipboardDelimiter(),
onlySelected: !rowPositions,
processCellCallback: this.gos.getCallback("processCellForClipboard"),
processRowGroupCallback: (params2) => this.processRowGroupCallback(params2),
processHeaderCallback: this.gos.getCallback("processHeaderForClipboard"),
processGroupHeaderCallback: this.gos.getCallback("processGroupHeaderForClipboard")
};
return this.csvCreator.getDataAsCsv(exportParams, true);
}
processRowGroupCallback(params) {
const { node, column } = params;
const isTreeData = this.gos.get("treeData");
const isSuppressGroupMaintainValueType = this.gos.get("suppressGroupMaintainValueType");
const getValueFromNode = () => {
if (isTreeData || isSuppressGroupMaintainValueType || !column) {
return node.key;
}
const value2 = node.groupData?.[column.getId()];
if (!value2 || !node.rowGroupColumn || node.rowGroupColumn.getColDef().useValueFormatterForExport === false) {
return value2;
}
return this.valueService.formatValue(node.rowGroupColumn, node, value2) ?? value2;
};
let value = getValueFromNode();
if (params.node.footer) {
let suffix = "";
if (value && value.length) {
suffix = ` ${value}`;
}
value = `Total${suffix}`;
}
const processCellForClipboard = this.gos.getCallback("processCellForClipboard");
if (processCellForClipboard) {
let column2 = node.rowGroupColumn;
if (!column2 && node.footer && node.level === -1) {
column2 = this.funcColsService.getRowGroupColumns()[0];
}
return processCellForClipboard({
value,
node,
column: column2,
type: "clipboard",
formatValue: (valueToFormat) => this.valueService.formatValue(column2, node, valueToFormat) ?? valueToFormat,
parseValue: (valueToParse) => this.valueService.parseValue(column2, node, valueToParse, this.valueService.getValue(column2, node))
});
}
return value;
}
// eslint-disable-next-line @typescript-eslint/ban-types
dispatchFlashCells(cellsToFlash) {
window.setTimeout(() => {
this.eventService.dispatchEvent({
type: "flashCells",
cells: cellsToFlash
});
}, 0);
}
processCell(rowNode, column, value, type, func, canParse, canFormat) {
if (func) {
const params = {
column,
node: rowNode,
value,
type,
formatValue: (valueToFormat) => this.valueService.formatValue(column, rowNode ?? null, valueToFormat) ?? valueToFormat,
parseValue: (valueToParse) => this.valueService.parseValue(
column,
rowNode ?? null,
valueToParse,
this.valueService.getValue(column, rowNode)
)
};
return func(params);
}
if (canParse && column.getColDef().useValueParserForImport !== false) {
return this.valueService.parseValue(
column,
rowNode ?? null,
value,
this.valueService.getValue(column, rowNode)
);
}
if (canFormat && column.getColDef().useValueFormatterForExport !== false) {
return this.valueService.formatValue(column, rowNode ?? null, value) ?? value;
}
return value;
}
copyDataToClipboard(data) {
const userProvidedFunc = this.gos.getCallback("sendToClipboard");
if (userProvidedFunc) {
userProvidedFunc({ data });
return;
}
const allowNavigator = !this.gos.get("suppressClipboardApi");
if (allowNavigator && navigator.clipboard) {
navigator.clipboard.writeText(data).catch((e) => {
_warnOnce(`${e}
${apiError("writeText")}`);
this.copyDataToClipboardLegacy(data);
});
return;
}
this.copyDataToClipboardLegacy(data);
}
copyDataToClipboardLegacy(data) {
this.executeOnTempElement((element) => {
const eDocument = _getDocument(this.gos);
const focusedElementBefore = _getActiveDomElement(this.gos);
element.value = data || " ";
element.select();
element.focus({ preventScroll: true });
const result = eDocument.execCommand("copy");
if (!result) {
_warnOnce(
"Browser did not allow document.execCommand('copy'). Ensure api.copySelectedRowsToClipboard() is invoked via a user event, i.e. button click, otherwise the browser will prevent it for security reasons."
);
}
if (focusedElementBefore != null && focusedElementBefore.focus != null) {
focusedElementBefore.focus({ preventScroll: true });
}
});
}
executeOnTempElement(callbackNow, callbackAfter) {
const eDoc = _getDocument(this.gos);
const eTempInput = eDoc.createElement("textarea");
eTempInput.style.width = "1px";
eTempInput.style.height = "1px";
eTempInput.style.top = eDoc.documentElement.scrollTop + "px";
eTempInput.style.left = eDoc.documentElement.scrollLeft + "px";
eTempInput.style.position = "absolute";
eTempInput.style.opacity = "0";
const guiRoot = this.gridCtrl.getGui();
guiRoot.appendChild(eTempInput);
try {
callbackNow(eTempInput);
} catch (err) {
_warnOnce("Browser does not support document.execCommand('copy') for clipboard operations");
}
if (callbackAfter) {
window.setTimeout(() => {
callbackAfter(eTempInput);
guiRoot.removeChild(eTempInput);
}, 100);
} else {
guiRoot.removeChild(eTempInput);
}
}
getRangeSize(rangeService) {
const ranges = rangeService.getCellRanges();
let startRangeIndex = 0;
let endRangeIndex = 0;
if (ranges.length > 0) {
startRangeIndex = rangeService.getRangeStartRow(ranges[0]).rowIndex;
endRangeIndex = rangeService.getRangeEndRow(ranges[0]).rowIndex;
}
return startRangeIndex - endRangeIndex + 1;
}
};
// enterprise-modules/clipboard/src/version.ts
var VERSION = "32.3.8";
// enterprise-modules/clipboard/src/clipboardModule.ts
var ClipboardCoreModule = _defineModule({
version: VERSION,
moduleName: `${ModuleNames.ClipboardModule}-core`,
beans: [ClipboardService],
dependantModules: [EnterpriseCoreModule, CsvExportModule]
});
var ClipboardApiModule = _defineModule({
version: VERSION,
moduleName: `${ModuleNames.ClipboardModule}-api`,
apiFunctions: {
copyToClipboard,
cutToClipboard,
copySelectedRowsToClipboard,
copySelectedRangeToClipboard,
copySelectedRangeDown,
pasteFromClipboard
},
dependantModules: [ClipboardCoreModule]
});
var ClipboardModule = _defineModule({
version: VERSION,
moduleName: ModuleNames.ClipboardModule,
dependantModules: [ClipboardCoreModule, ClipboardApiModule]
});
export {
ClipboardModule
};