Files
railwaysystem/RuoYi-Vue/ruoyi-ui/node_modules1/handsontable/plugins/copyPaste/copyPaste.js
T
2026-09-10 15:40:10 +08:00

764 lines
30 KiB
JavaScript

"use strict";
exports.__esModule = true;
require("core-js/modules/es.array.push.js");
require("core-js/modules/es.error.cause.js");
var _base = require("../base");
var _pluginHooks = _interopRequireDefault(require("../../pluginHooks"));
var _SheetClip = require("../../3rdparty/SheetClip");
var _array = require("../../helpers/array");
var _string = require("../../helpers/string");
var _element = require("../../helpers/dom/element");
var _copy = _interopRequireDefault(require("./contextMenuItem/copy"));
var _copyColumnHeadersOnly = _interopRequireDefault(require("./contextMenuItem/copyColumnHeadersOnly"));
var _copyWithColumnGroupHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnGroupHeaders"));
var _copyWithColumnHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnHeaders"));
var _cut = _interopRequireDefault(require("./contextMenuItem/cut"));
var _pasteEvent = _interopRequireDefault(require("./pasteEvent"));
var _focusableElement = require("./focusableElement");
var _copyableRanges = require("./copyableRanges");
var _parseTable = require("../../utils/parseTable");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
_pluginHooks.default.getSingleton().register('afterCopyLimit');
_pluginHooks.default.getSingleton().register('modifyCopyableRange');
_pluginHooks.default.getSingleton().register('beforeCut');
_pluginHooks.default.getSingleton().register('afterCut');
_pluginHooks.default.getSingleton().register('beforePaste');
_pluginHooks.default.getSingleton().register('afterPaste');
_pluginHooks.default.getSingleton().register('beforeCopy');
_pluginHooks.default.getSingleton().register('afterCopy');
const PLUGIN_KEY = 'copyPaste';
exports.PLUGIN_KEY = PLUGIN_KEY;
const PLUGIN_PRIORITY = 80;
exports.PLUGIN_PRIORITY = PLUGIN_PRIORITY;
const SETTING_KEYS = ['fragmentSelection'];
const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
/* eslint-disable jsdoc/require-description-complete-sentence */
/**
* @description
* Copy, cut, and paste data by using the `CopyPaste` plugin.
*
* Control the `CopyPaste` plugin programmatically through its [API methods](#methods).
*
* The user can access the copy-paste features through:
* - The [context menu](@/guides/cell-features/clipboard.md#context-menu).
* - The [keyboard shortcuts](@/guides/cell-features/clipboard.md#related-keyboard-shortcuts).
* - The browser's menu bar.
*
* Read more:
* - [Guides: Clipboard](@/guides/cell-features/clipboard.md)
* - [Configuration options: `copyPaste`](@/api/options.md#copypaste)
*
* @example
* ```js
* // enable the plugin with the default configuration
* copyPaste: true,
*
* // or, enable the plugin with a custom configuration
* copyPaste: {
* columnsLimit: 25,
* rowsLimit: 50,
* pasteMode: 'shift_down',
* copyColumnHeaders: true,
* copyColumnGroupHeaders: true,
* copyColumnHeadersOnly: true,
* uiContainer: document.body,
* },
* ```
* @class CopyPaste
* @plugin CopyPaste
*/
var _enableCopyColumnHeaders = /*#__PURE__*/new WeakMap();
var _enableCopyColumnGroupHeaders = /*#__PURE__*/new WeakMap();
var _enableCopyColumnHeadersOnly = /*#__PURE__*/new WeakMap();
var _copyMode = /*#__PURE__*/new WeakMap();
var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
class CopyPaste extends _base.BasePlugin {
constructor() {
super(...arguments);
/**
* Counts how many column headers will be copied based on the passed range.
*
* @private
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
* @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
* information with the number of copied headers.
*/
_classPrivateMethodInitSpec(this, _countCopiedHeaders);
/**
* The maximum number of columns than can be copied to the clipboard.
*
* @type {number}
* @default Infinity
*/
_defineProperty(this, "columnsLimit", Infinity);
/**
* The maximum number of rows than can be copied to the clipboard.
*
* @type {number}
* @default Infinity
*/
_defineProperty(this, "rowsLimit", Infinity);
/**
* When pasting:
* - `'overwrite'`: overwrite the currently-selected cells
* - `'shift_down'`: move currently-selected cells down
* - `'shift_right'`: move currently-selected cells to the right
*
* @type {string}
* @default 'overwrite'
*/
_defineProperty(this, "pasteMode", 'overwrite');
/**
* The UI container for the secondary focusable element.
*
* @type {HTMLElement}
*/
_defineProperty(this, "uiContainer", this.hot.rootDocument.body);
/**
* Shows the "Copy with headers" item in the context menu and extends the context menu with the
* `'copy_with_column_headers'` option that can be used for creating custom menus arrangements.
*
* @type {boolean}
* @default false
*/
_classPrivateFieldInitSpec(this, _enableCopyColumnHeaders, {
writable: true,
value: false
});
/**
* Shows the "Copy with group headers" item in the context menu and extends the context menu with the
* `'copy_with_column_group headers'` option that can be used for creating custom menus arrangements.
*
* @type {boolean}
* @default false
*/
_classPrivateFieldInitSpec(this, _enableCopyColumnGroupHeaders, {
writable: true,
value: false
});
/**
* Shows the "Copy headers only" item in the context menu and extends the context menu with the
* `'copy_column_headers_only'` option that can be used for creating custom menus arrangements.
*
* @type {boolean}
* @default false
*/
_classPrivateFieldInitSpec(this, _enableCopyColumnHeadersOnly, {
writable: true,
value: false
});
/**
* Defines the data range to copy. Possible values:
* * `'cells-only'` Copy selected cells only;
* * `'column-headers-only'` Copy column headers only;
* * `'with-column-group-headers'` Copy cells with all column headers;
* * `'with-column-headers'` Copy cells with column headers;
*
* @type {'cells-only' | 'column-headers-only' | 'with-column-group-headers' | 'with-column-headers'}
*/
_classPrivateFieldInitSpec(this, _copyMode, {
writable: true,
value: 'cells-only'
});
/**
* Flag that is used to prevent copying when the native shortcut was not pressed.
*
* @type {boolean}
*/
_classPrivateFieldInitSpec(this, _isTriggeredByCopy, {
writable: true,
value: false
});
/**
* Flag that is used to prevent cutting when the native shortcut was not pressed.
*
* @type {boolean}
*/
_classPrivateFieldInitSpec(this, _isTriggeredByCut, {
writable: true,
value: false
});
/**
* Class that helps generate copyable ranges based on the current selection for different copy mode
* types.
*
* @type {CopyableRangesFactory}
*/
_classPrivateFieldInitSpec(this, _copyableRangesFactory, {
writable: true,
value: new _copyableRanges.CopyableRangesFactory({
countRows: () => this.hot.countRows(),
countColumns: () => this.hot.countCols(),
rowsLimit: () => this.rowsLimit,
columnsLimit: () => this.columnsLimit,
countColumnHeaders: () => this.hot.view.getColumnHeadersCount()
})
});
/**
* Ranges of the cells coordinates, which should be used to copy/cut/paste actions.
*
* @private
* @type {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>}
*/
_defineProperty(this, "copyableRanges", []);
/**
* Provides focusable element to support IME and copy/paste/cut actions.
*
* @private
* @type {FocusableWrapper}
*/
_defineProperty(this, "focusableElement", void 0);
}
static get PLUGIN_KEY() {
return PLUGIN_KEY;
}
static get SETTING_KEYS() {
return [PLUGIN_KEY, ...SETTING_KEYS];
}
static get PLUGIN_PRIORITY() {
return PLUGIN_PRIORITY;
}
/**
* Checks if the [`CopyPaste`](#copypaste) plugin is enabled.
*
* This method gets called by Handsontable's [`beforeInit`](@/api/hooks.md#beforeinit) hook.
* If it returns `true`, the [`enablePlugin()`](#enableplugin) method gets called.
*
* @returns {boolean}
*/
isEnabled() {
return !!this.hot.getSettings()[PLUGIN_KEY];
}
/**
* Enables the [`CopyPaste`](#copypaste) plugin for your Handsontable instance.
*/
enablePlugin() {
if (this.enabled) {
return;
}
const {
[PLUGIN_KEY]: settings
} = this.hot.getSettings();
if (typeof settings === 'object') {
var _settings$pasteMode, _settings$uiContainer;
this.pasteMode = (_settings$pasteMode = settings.pasteMode) !== null && _settings$pasteMode !== void 0 ? _settings$pasteMode : this.pasteMode;
this.rowsLimit = isNaN(settings.rowsLimit) ? this.rowsLimit : settings.rowsLimit;
this.columnsLimit = isNaN(settings.columnsLimit) ? this.columnsLimit : settings.columnsLimit;
_classPrivateFieldSet(this, _enableCopyColumnHeaders, !!settings.copyColumnHeaders);
_classPrivateFieldSet(this, _enableCopyColumnGroupHeaders, !!settings.copyColumnGroupHeaders);
_classPrivateFieldSet(this, _enableCopyColumnHeadersOnly, !!settings.copyColumnHeadersOnly);
this.uiContainer = (_settings$uiContainer = settings.uiContainer) !== null && _settings$uiContainer !== void 0 ? _settings$uiContainer : this.uiContainer;
}
this.addHook('afterContextMenuDefaultOptions', options => this.onAfterContextMenuDefaultOptions(options));
this.addHook('afterOnCellMouseUp', () => this.onAfterOnCellMouseUp());
this.addHook('afterSelectionEnd', () => this.onAfterSelectionEnd());
this.addHook('beforeKeyDown', () => this.onBeforeKeyDown());
this.focusableElement = (0, _focusableElement.createElement)(this.uiContainer);
this.focusableElement.addLocalHook('copy', event => this.onCopy(event)).addLocalHook('cut', event => this.onCut(event)).addLocalHook('paste', event => this.onPaste(event));
super.enablePlugin();
}
/**
* Updates the state of the [`CopyPaste`](#copypaste) plugin.
*
* Gets called when [`updateSettings()`](@/api/core.md#updatesettings)
* is invoked with any of the following configuration options:
* - [`copyPaste`](@/api/options.md#copypaste)
* - [`fragmentSelection`](@/api/options.md#fragmentselection)
*/
updatePlugin() {
this.disablePlugin();
this.enablePlugin();
this.getOrCreateFocusableElement();
super.updatePlugin();
}
/**
* Disables the [`CopyPaste`](#copypaste) plugin for your Handsontable instance.
*/
disablePlugin() {
if (this.focusableElement) {
(0, _focusableElement.destroyElement)(this.focusableElement);
}
super.disablePlugin();
}
/**
* Copies the contents of the selected cells (and/or their related column headers) to the system clipboard.
*
* Takes an optional parameter (`copyMode`) that defines the scope of copying:
*
* | `copyMode` value | Description |
* | ----------------------------- | --------------------------------------------------------------- |
* | `'cells-only'` (default) | Copy the selected cells |
* | `'with-column-headers'` | - Copy the selected cells<br>- Copy the nearest column headers |
* | `'with-column-group-headers'` | - Copy the selected cells<br>- Copy all related columns headers |
* | `'column-headers-only'` | Copy the nearest column headers (without copying cells) |
*
* @param {string} [copyMode='cells-only'] Copy mode.
*/
copy() {
let copyMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'cells-only';
_classPrivateFieldSet(this, _copyMode, copyMode);
_classPrivateFieldSet(this, _isTriggeredByCopy, true);
this.getOrCreateFocusableElement();
this.focusableElement.focus();
this.hot.rootDocument.execCommand('copy');
}
/**
* Copies the contents of the selected cells.
*/
copyCellsOnly() {
this.copy('cells-only');
}
/**
* Copies the contents of column headers that are nearest to the selected cells.
*/
copyColumnHeadersOnly() {
this.copy('column-headers-only');
}
/**
* Copies the contents of the selected cells and all their related column headers.
*/
copyWithAllColumnHeaders() {
this.copy('with-column-group-headers');
}
/**
* Copies the contents of the selected cells and their nearest column headers.
*/
copyWithColumnHeaders() {
this.copy('with-column-headers');
}
/**
* Cuts the contents of the selected cells to the system clipboard.
*/
cut() {
_classPrivateFieldSet(this, _isTriggeredByCut, true);
this.getOrCreateFocusableElement();
this.focusableElement.focus();
this.hot.rootDocument.execCommand('cut');
}
/**
* Converts the contents of multiple ranges (`ranges`) into a single string.
*
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `endRow`, `startCol` and `endCol`.
* @returns {string} A string that will be copied to the clipboard.
*/
getRangedCopyableData(ranges) {
return (0, _SheetClip.stringify)(this.getRangedData(ranges));
}
/**
* Converts the contents of multiple ranges (`ranges`) into an array of arrays.
*
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
* @returns {Array[]} An array of arrays that will be copied to the clipboard.
*/
getRangedData(ranges) {
const data = [];
const {
rows,
columns
} = (0, _copyableRanges.normalizeRanges)(ranges);
// concatenate all rows and columns data defined in ranges into one copyable string
(0, _array.arrayEach)(rows, row => {
const rowSet = [];
(0, _array.arrayEach)(columns, column => {
if (row < 0) {
// `row` as the second argument acts here as the `headerLevel` argument
rowSet.push(this.hot.getColHeader(column, row));
} else {
rowSet.push(this.hot.getCopyableData(row, column));
}
});
data.push(rowSet);
});
return data;
}
/**
* Simulates the paste action.
*
* For security reasons, modern browsers don't allow reading from the system clipboard.
*
* @param {string} pastableText The value to paste, as a raw string.
* @param {string} [pastableHtml=''] The value to paste, as HTML.
*/
paste() {
let pastableText = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
let pastableHtml = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : pastableText;
if (!pastableText && !pastableHtml) {
return;
}
const pasteData = new _pasteEvent.default();
if (pastableText) {
pasteData.clipboardData.setData('text/plain', pastableText);
}
if (pastableHtml) {
pasteData.clipboardData.setData('text/html', pastableHtml);
}
this.getOrCreateFocusableElement();
this.onPaste(pasteData);
}
/**
* Prepares copyable text from the cells selection in the invisible textarea.
*/
setCopyableText() {
const selectionRange = this.hot.getSelectedRangeLast();
if (!selectionRange) {
return;
}
_classPrivateFieldGet(this, _copyableRangesFactory).setSelectedRange(selectionRange);
const groupedRanges = new Map([['headers', null], ['cells', null]]);
if (_classPrivateFieldGet(this, _copyMode) === 'column-headers-only') {
groupedRanges.set('headers', _classPrivateFieldGet(this, _copyableRangesFactory).getMostBottomColumnHeadersRange());
} else {
if (_classPrivateFieldGet(this, _copyMode) === 'with-column-headers') {
groupedRanges.set('headers', _classPrivateFieldGet(this, _copyableRangesFactory).getMostBottomColumnHeadersRange());
} else if (_classPrivateFieldGet(this, _copyMode) === 'with-column-group-headers') {
groupedRanges.set('headers', _classPrivateFieldGet(this, _copyableRangesFactory).getAllColumnHeadersRange());
}
groupedRanges.set('cells', _classPrivateFieldGet(this, _copyableRangesFactory).getCellsRange());
}
this.copyableRanges = Array.from(groupedRanges.values()).filter(range => range !== null).map(_ref => {
let {
startRow,
startCol,
endRow,
endCol
} = _ref;
return {
startRow,
startCol,
endRow,
endCol
};
});
this.copyableRanges = this.hot.runHooks('modifyCopyableRange', this.copyableRanges);
const cellsRange = groupedRanges.get('cells');
if (cellsRange !== null && cellsRange.isRangeTrimmed) {
const {
startRow,
startCol,
endRow,
endCol
} = cellsRange;
this.hot.runHooks('afterCopyLimit', endRow - startRow + 1, endCol - startCol + 1, this.rowsLimit, this.columnsLimit);
}
}
/**
* Force focus on editable element.
*
* @private
*/
getOrCreateFocusableElement() {
var _this$hot$getActiveEd;
const editableElement = (_this$hot$getActiveEd = this.hot.getActiveEditor()) === null || _this$hot$getActiveEd === void 0 ? void 0 : _this$hot$getActiveEd.TEXTAREA;
if (editableElement) {
this.focusableElement.setFocusableElement(editableElement);
} else {
this.focusableElement.useSecondaryElement();
}
}
/**
* Verifies if editor exists and is open.
*
* @private
* @returns {boolean}
*/
isEditorOpened() {
var _this$hot$getActiveEd2;
return (_this$hot$getActiveEd2 = this.hot.getActiveEditor()) === null || _this$hot$getActiveEd2 === void 0 ? void 0 : _this$hot$getActiveEd2.isOpened();
}
/**
* Prepares new values to populate them into datasource.
*
* @private
* @param {Array} inputArray An array of the data to populate.
* @param {Array} [selection] The selection which indicates from what position the data will be populated.
* @returns {Array} Range coordinates after populate data.
*/
populateValues(inputArray) {
let selection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.hot.getSelectedRangeLast();
if (!inputArray.length) {
return;
}
const populatedRowsLength = inputArray.length;
const populatedColumnsLength = inputArray[0].length;
const newRows = [];
const {
row: startRow,
col: startColumn
} = selection.getTopStartCorner();
const {
row: endRowFromSelection,
col: endColumnFromSelection
} = selection.getBottomEndCorner();
let visualRowForPopulatedData = startRow;
let visualColumnForPopulatedData = startColumn;
let lastVisualRow = startRow;
let lastVisualColumn = startColumn;
// We try to populate just all copied data or repeat copied data within a selection. Please keep in mind that we
// don't know whether populated data is bigger than selection on start as there are some cells for which values
// should be not inserted (it's known right after getting cell meta).
while (newRows.length < populatedRowsLength || visualRowForPopulatedData <= endRowFromSelection) {
const {
skipRowOnPaste,
visualRow
} = this.hot.getCellMeta(visualRowForPopulatedData, startColumn);
visualRowForPopulatedData = visualRow + 1;
if (skipRowOnPaste === true) {
/* eslint-disable no-continue */
continue;
}
lastVisualRow = visualRow;
visualColumnForPopulatedData = startColumn;
const newRow = [];
const insertedRow = newRows.length % populatedRowsLength;
while (newRow.length < populatedColumnsLength || visualColumnForPopulatedData <= endColumnFromSelection) {
const {
skipColumnOnPaste,
visualCol
} = this.hot.getCellMeta(startRow, visualColumnForPopulatedData);
visualColumnForPopulatedData = visualCol + 1;
if (skipColumnOnPaste === true) {
/* eslint-disable no-continue */
continue;
}
lastVisualColumn = visualCol;
const insertedColumn = newRow.length % populatedColumnsLength;
newRow.push(inputArray[insertedRow][insertedColumn]);
}
newRows.push(newRow);
}
this.hot.populateFromArray(startRow, startColumn, newRows, void 0, void 0, 'CopyPaste.paste', this.pasteMode);
return [startRow, startColumn, lastVisualRow, lastVisualColumn];
}
/**
* `copy` event callback on textarea element.
*
* @param {Event} event ClipboardEvent.
* @private
*/
onCopy(event) {
if (!this.hot.isListening() && !_classPrivateFieldGet(this, _isTriggeredByCopy) || this.isEditorOpened()) {
return;
}
this.setCopyableText();
_classPrivateFieldSet(this, _isTriggeredByCopy, false);
const data = this.getRangedData(this.copyableRanges);
const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
if (allowCopying) {
const textPlain = (0, _SheetClip.stringify)(data);
if (event && event.clipboardData) {
const textHTML = (0, _parseTable._dataToHTML)(data, this.hot.rootDocument);
event.clipboardData.setData('text/plain', textPlain);
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
} else if (typeof ClipboardEvent === 'undefined') {
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
}
this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
}
_classPrivateFieldSet(this, _copyMode, 'cells-only');
event.preventDefault();
}
/**
* `cut` event callback on textarea element.
*
* @param {Event} event ClipboardEvent.
* @private
*/
onCut(event) {
if (!this.hot.isListening() && !_classPrivateFieldGet(this, _isTriggeredByCut) || this.isEditorOpened()) {
return;
}
this.setCopyableText();
_classPrivateFieldSet(this, _isTriggeredByCut, false);
const rangedData = this.getRangedData(this.copyableRanges);
const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
if (allowCuttingOut) {
const textPlain = (0, _SheetClip.stringify)(rangedData);
if (event && event.clipboardData) {
const textHTML = (0, _parseTable._dataToHTML)(rangedData, this.hot.rootDocument);
event.clipboardData.setData('text/plain', textPlain);
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
} else if (typeof ClipboardEvent === 'undefined') {
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
}
this.hot.emptySelectedCells('CopyPaste.cut');
this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
}
event.preventDefault();
}
/**
* `paste` event callback on textarea element.
*
* @param {Event} event ClipboardEvent or pseudo ClipboardEvent, if paste was called manually.
* @private
*/
onPaste(event) {
if (!this.hot.isListening() || this.isEditorOpened()) {
return;
}
if (event && event.preventDefault) {
event.preventDefault();
}
let pastedData;
if (event && typeof event.clipboardData !== 'undefined') {
const textHTML = (0, _string.sanitize)(event.clipboardData.getData('text/html'), {
ADD_TAGS: ['meta'],
ADD_ATTR: ['content'],
FORCE_BODY: true
});
if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
const parsedConfig = (0, _parseTable.htmlToGridSettings)(textHTML, this.hot.rootDocument);
pastedData = parsedConfig.data;
} else {
pastedData = event.clipboardData.getData('text/plain');
}
} else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
pastedData = this.hot.rootWindow.clipboardData.getData('Text');
}
if (typeof pastedData === 'string') {
pastedData = (0, _SheetClip.parse)(pastedData);
}
if (pastedData && pastedData.length === 0) {
return;
}
if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
return;
}
const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
this.hot.runHooks('afterPaste', pastedData, this.copyableRanges);
}
/**
* Add copy and cut options to the Context Menu.
*
* @private
* @param {object} options Contains default added options of the Context Menu.
*/
onAfterContextMenuDefaultOptions(options) {
options.items.push({
name: '---------'
}, (0, _copy.default)(this));
if (_classPrivateFieldGet(this, _enableCopyColumnHeaders)) {
options.items.push((0, _copyWithColumnHeaders.default)(this));
}
if (_classPrivateFieldGet(this, _enableCopyColumnGroupHeaders)) {
options.items.push((0, _copyWithColumnGroupHeaders.default)(this));
}
if (_classPrivateFieldGet(this, _enableCopyColumnHeadersOnly)) {
options.items.push((0, _copyColumnHeadersOnly.default)(this));
}
options.items.push((0, _cut.default)(this));
}
/**
* Force focus on focusableElement.
*
* @private
*/
onAfterOnCellMouseUp() {
// Changing focused element will remove current selection. It's unnecessary in case when we give possibility
// for fragment selection
if (!this.hot.isListening() || this.isEditorOpened() || this.hot.getSettings().fragmentSelection) {
return;
}
this.getOrCreateFocusableElement();
this.focusableElement.focus();
}
/**
* Force focus on focusableElement after end of the selection.
*
* @private
*/
onAfterSelectionEnd() {
if (this.isEditorOpened()) {
return;
}
this.getOrCreateFocusableElement();
if (this.hot.getSettings().fragmentSelection && this.focusableElement.getFocusableElement() !== this.hot.rootDocument.activeElement && (0, _element.getSelectionText)()) {
return;
}
this.setCopyableText();
this.focusableElement.focus();
}
/**
* `beforeKeyDown` listener to force focus of focusableElement.
*
* @private
*/
onBeforeKeyDown() {
if (!this.hot.isListening() || this.isEditorOpened()) {
return;
}
const activeElement = this.hot.rootDocument.activeElement;
const activeEditor = this.hot.getActiveEditor();
if (!activeEditor || activeElement !== this.focusableElement.getFocusableElement() && activeElement !== activeEditor.select) {
return;
}
this.getOrCreateFocusableElement();
this.focusableElement.focus();
}
/**
* Destroys the `CopyPaste` plugin instance.
*/
destroy() {
if (this.focusableElement) {
(0, _focusableElement.destroyElement)(this.focusableElement);
this.focusableElement = null;
}
super.destroy();
}
}
exports.CopyPaste = CopyPaste;
function _countCopiedHeaders2(ranges) {
const {
rows
} = (0, _copyableRanges.normalizeRanges)(ranges);
let columnHeadersCount = 0;
for (let row = 0; row < rows.length; row++) {
if (rows[row] >= 0) {
break;
}
columnHeadersCount += 1;
}
return {
columnHeadersCount
};
}