handsontable 14.0.0-next-5fd908e-20231030 → 14.0.0-next-07c0a60-20231107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/base.js +2 -2
- package/base.mjs +2 -2
- package/dist/handsontable.css +2 -2
- package/dist/handsontable.full.css +2 -2
- package/dist/handsontable.full.js +2075 -3376
- package/dist/handsontable.full.min.css +2 -2
- package/dist/handsontable.full.min.js +57 -64
- package/dist/handsontable.js +2077 -3378
- package/dist/handsontable.min.css +2 -2
- package/dist/handsontable.min.js +16 -23
- package/helpers/mixed.js +2 -2
- package/helpers/mixed.mjs +2 -2
- package/package.json +1 -1
- package/pluginHooks.d.ts +6 -28
- package/pluginHooks.js +62 -116
- package/pluginHooks.mjs +62 -116
- package/plugins/comments/contextMenuItem/addEditComment.js +2 -5
- package/plugins/comments/contextMenuItem/addEditComment.mjs +2 -5
- package/plugins/comments/contextMenuItem/readOnlyComment.js +2 -8
- package/plugins/comments/contextMenuItem/readOnlyComment.mjs +2 -8
- package/plugins/comments/contextMenuItem/removeComment.js +2 -5
- package/plugins/comments/contextMenuItem/removeComment.mjs +2 -5
- package/plugins/copyPaste/clipboardData.js +18 -0
- package/plugins/copyPaste/clipboardData.mjs +14 -0
- package/plugins/copyPaste/copyPaste.js +92 -38
- package/plugins/copyPaste/copyPaste.mjs +94 -40
- package/plugins/copyPaste/pasteEvent.js +14 -0
- package/plugins/copyPaste/pasteEvent.mjs +9 -0
- package/plugins/nestedHeaders/nestedHeaders.js +22 -21
- package/plugins/nestedHeaders/nestedHeaders.mjs +22 -21
- package/utils/parseTable.js +83 -527
- package/utils/parseTable.mjs +82 -523
- package/plugins/copyPaste/clipboardData/clipboardData.js +0 -516
- package/plugins/copyPaste/clipboardData/clipboardData.mjs +0 -512
- package/plugins/copyPaste/clipboardData/copyClipboardData.js +0 -69
- package/plugins/copyPaste/clipboardData/copyClipboardData.mjs +0 -65
- package/plugins/copyPaste/clipboardData/index.js +0 -9
- package/plugins/copyPaste/clipboardData/index.mjs +0 -4
- package/plugins/copyPaste/clipboardData/pasteClipboardData.js +0 -81
- package/plugins/copyPaste/clipboardData/pasteClipboardData.mjs +0 -77
@@ -6,6 +6,7 @@ require("core-js/modules/es.error.cause.js");
|
|
6
6
|
var _base = require("../base");
|
7
7
|
var _pluginHooks = _interopRequireDefault(require("../../pluginHooks"));
|
8
8
|
var _SheetClip = require("../../3rdparty/SheetClip");
|
9
|
+
var _array = require("../../helpers/array");
|
9
10
|
var _string = require("../../helpers/string");
|
10
11
|
var _element = require("../../helpers/dom/element");
|
11
12
|
var _browser = require("../../helpers/browser");
|
@@ -14,10 +15,10 @@ var _copyColumnHeadersOnly = _interopRequireDefault(require("./contextMenuItem/c
|
|
14
15
|
var _copyWithColumnGroupHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnGroupHeaders"));
|
15
16
|
var _copyWithColumnHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnHeaders"));
|
16
17
|
var _cut = _interopRequireDefault(require("./contextMenuItem/cut"));
|
18
|
+
var _pasteEvent = _interopRequireDefault(require("./pasteEvent"));
|
17
19
|
var _copyableRanges = require("./copyableRanges");
|
18
20
|
var _parseTable = require("../../utils/parseTable");
|
19
21
|
var _eventManager = _interopRequireDefault(require("../../eventManager"));
|
20
|
-
var _clipboardData = require("./clipboardData");
|
21
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
22
23
|
function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
|
23
24
|
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
@@ -42,6 +43,7 @@ _pluginHooks.default.getSingleton().register('afterCopy');
|
|
42
43
|
const PLUGIN_KEY = exports.PLUGIN_KEY = 'copyPaste';
|
43
44
|
const PLUGIN_PRIORITY = exports.PLUGIN_PRIORITY = 80;
|
44
45
|
const SETTING_KEYS = ['fragmentSelection'];
|
46
|
+
const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
|
45
47
|
|
46
48
|
/* eslint-disable jsdoc/require-description-complete-sentence */
|
47
49
|
/**
|
@@ -86,6 +88,7 @@ var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
|
|
86
88
|
var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
|
87
89
|
var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
|
88
90
|
var _ensureClipboardEventsGetTriggered = /*#__PURE__*/new WeakSet();
|
91
|
+
var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
|
89
92
|
var _addContentEditableToHighlightedCell = /*#__PURE__*/new WeakSet();
|
90
93
|
var _removeContentEditableFromHighlightedCell = /*#__PURE__*/new WeakSet();
|
91
94
|
class CopyPaste extends _base.BasePlugin {
|
@@ -99,6 +102,15 @@ class CopyPaste extends _base.BasePlugin {
|
|
99
102
|
* Add the `contenteditable` attribute to the highlighted cell and select its content.
|
100
103
|
*/
|
101
104
|
_classPrivateMethodInitSpec(this, _addContentEditableToHighlightedCell);
|
105
|
+
/**
|
106
|
+
* Counts how many column headers will be copied based on the passed range.
|
107
|
+
*
|
108
|
+
* @private
|
109
|
+
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
|
110
|
+
* @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
|
111
|
+
* information with the number of copied headers.
|
112
|
+
*/
|
113
|
+
_classPrivateMethodInitSpec(this, _countCopiedHeaders);
|
102
114
|
/**
|
103
115
|
* Ensure that the `copy`/`cut` events get triggered properly in Safari.
|
104
116
|
*
|
@@ -383,14 +395,26 @@ class CopyPaste extends _base.BasePlugin {
|
|
383
395
|
* @returns {Array[]} An array of arrays that will be copied to the clipboard.
|
384
396
|
*/
|
385
397
|
getRangedData(ranges) {
|
398
|
+
const data = [];
|
386
399
|
const {
|
387
400
|
rows,
|
388
401
|
columns
|
389
402
|
} = (0, _copyableRanges.normalizeRanges)(ranges);
|
390
|
-
|
391
|
-
|
392
|
-
|
403
|
+
|
404
|
+
// concatenate all rows and columns data defined in ranges into one copyable string
|
405
|
+
(0, _array.arrayEach)(rows, row => {
|
406
|
+
const rowSet = [];
|
407
|
+
(0, _array.arrayEach)(columns, column => {
|
408
|
+
if (row < 0) {
|
409
|
+
// `row` as the second argument acts here as the `headerLevel` argument
|
410
|
+
rowSet.push(this.hot.getColHeader(column, row));
|
411
|
+
} else {
|
412
|
+
rowSet.push(this.hot.getCopyableData(row, column));
|
413
|
+
}
|
414
|
+
});
|
415
|
+
data.push(rowSet);
|
393
416
|
});
|
417
|
+
return data;
|
394
418
|
}
|
395
419
|
|
396
420
|
/**
|
@@ -407,17 +431,7 @@ class CopyPaste extends _base.BasePlugin {
|
|
407
431
|
if (!pastableText && !pastableHtml) {
|
408
432
|
return;
|
409
433
|
}
|
410
|
-
const pasteData =
|
411
|
-
clipboardData: {
|
412
|
-
data: {},
|
413
|
-
setData(type, value) {
|
414
|
-
this.data[type] = value;
|
415
|
-
},
|
416
|
-
getData(type) {
|
417
|
-
return this.data[type];
|
418
|
-
}
|
419
|
-
}
|
420
|
-
};
|
434
|
+
const pasteData = new _pasteEvent.default();
|
421
435
|
if (pastableText) {
|
422
436
|
pasteData.clipboardData.setData('text/plain', pastableText);
|
423
437
|
}
|
@@ -556,7 +570,7 @@ class CopyPaste extends _base.BasePlugin {
|
|
556
570
|
/**
|
557
571
|
* `copy` event callback on textarea element.
|
558
572
|
*
|
559
|
-
* @param {
|
573
|
+
* @param {Event} event ClipboardEvent.
|
560
574
|
* @private
|
561
575
|
*/
|
562
576
|
onCopy(event) {
|
@@ -565,12 +579,19 @@ class CopyPaste extends _base.BasePlugin {
|
|
565
579
|
}
|
566
580
|
this.setCopyableText();
|
567
581
|
_classPrivateFieldSet(this, _isTriggeredByCopy, false);
|
568
|
-
const
|
569
|
-
const
|
582
|
+
const data = this.getRangedData(this.copyableRanges);
|
583
|
+
const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
|
584
|
+
const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
|
570
585
|
if (allowCopying) {
|
571
|
-
|
572
|
-
|
573
|
-
|
586
|
+
const textPlain = (0, _SheetClip.stringify)(data);
|
587
|
+
if (event && event.clipboardData) {
|
588
|
+
const textHTML = (0, _parseTable._dataToHTML)(data, this.hot.rootDocument);
|
589
|
+
event.clipboardData.setData('text/plain', textPlain);
|
590
|
+
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
591
|
+
} else if (typeof ClipboardEvent === 'undefined') {
|
592
|
+
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
593
|
+
}
|
594
|
+
this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
|
574
595
|
}
|
575
596
|
_classPrivateFieldSet(this, _copyMode, 'cells-only');
|
576
597
|
event.preventDefault();
|
@@ -579,7 +600,7 @@ class CopyPaste extends _base.BasePlugin {
|
|
579
600
|
/**
|
580
601
|
* `cut` event callback on textarea element.
|
581
602
|
*
|
582
|
-
* @param {
|
603
|
+
* @param {Event} event ClipboardEvent.
|
583
604
|
* @private
|
584
605
|
*/
|
585
606
|
onCut(event) {
|
@@ -588,13 +609,19 @@ class CopyPaste extends _base.BasePlugin {
|
|
588
609
|
}
|
589
610
|
this.setCopyableText();
|
590
611
|
_classPrivateFieldSet(this, _isTriggeredByCut, false);
|
591
|
-
const
|
592
|
-
const allowCuttingOut = !!this.hot.runHooks('beforeCut',
|
612
|
+
const rangedData = this.getRangedData(this.copyableRanges);
|
613
|
+
const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
|
593
614
|
if (allowCuttingOut) {
|
594
|
-
|
595
|
-
|
615
|
+
const textPlain = (0, _SheetClip.stringify)(rangedData);
|
616
|
+
if (event && event.clipboardData) {
|
617
|
+
const textHTML = (0, _parseTable._dataToHTML)(rangedData, this.hot.rootDocument);
|
618
|
+
event.clipboardData.setData('text/plain', textPlain);
|
619
|
+
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
620
|
+
} else if (typeof ClipboardEvent === 'undefined') {
|
621
|
+
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
622
|
+
}
|
596
623
|
this.hot.emptySelectedCells('CopyPaste.cut');
|
597
|
-
this.hot.runHooks('afterCut',
|
624
|
+
this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
|
598
625
|
}
|
599
626
|
event.preventDefault();
|
600
627
|
}
|
@@ -612,22 +639,34 @@ class CopyPaste extends _base.BasePlugin {
|
|
612
639
|
if (event && event.preventDefault) {
|
613
640
|
event.preventDefault();
|
614
641
|
}
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
642
|
+
let pastedData;
|
643
|
+
if (event && typeof event.clipboardData !== 'undefined') {
|
644
|
+
const textHTML = (0, _string.sanitize)(event.clipboardData.getData('text/html'), {
|
645
|
+
ADD_TAGS: ['meta'],
|
646
|
+
ADD_ATTR: ['content'],
|
647
|
+
FORCE_BODY: true
|
648
|
+
});
|
649
|
+
if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
|
650
|
+
const parsedConfig = (0, _parseTable.htmlToGridSettings)(textHTML, this.hot.rootDocument);
|
651
|
+
pastedData = parsedConfig.data;
|
652
|
+
} else {
|
653
|
+
pastedData = event.clipboardData.getData('text/plain');
|
654
|
+
}
|
655
|
+
} else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
|
656
|
+
pastedData = this.hot.rootWindow.clipboardData.getData('Text');
|
657
|
+
}
|
658
|
+
if (typeof pastedData === 'string') {
|
659
|
+
pastedData = (0, _SheetClip.parse)(pastedData);
|
660
|
+
}
|
661
|
+
if (pastedData === void 0 || pastedData && pastedData.length === 0) {
|
622
662
|
return;
|
623
663
|
}
|
624
|
-
|
625
|
-
if (pastedTable.length === 0) {
|
664
|
+
if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
|
626
665
|
return;
|
627
666
|
}
|
628
|
-
const [startRow, startColumn, endRow, endColumn] = this.populateValues(
|
667
|
+
const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
|
629
668
|
this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
|
630
|
-
this.hot.runHooks('afterPaste',
|
669
|
+
this.hot.runHooks('afterPaste', pastedData, this.copyableRanges);
|
631
670
|
}
|
632
671
|
|
633
672
|
/**
|
@@ -724,6 +763,21 @@ function _ensureClipboardEventsGetTriggered2(eventName) {
|
|
724
763
|
this.hot.rootDocument.execCommand(eventName);
|
725
764
|
}
|
726
765
|
}
|
766
|
+
function _countCopiedHeaders2(ranges) {
|
767
|
+
const {
|
768
|
+
rows
|
769
|
+
} = (0, _copyableRanges.normalizeRanges)(ranges);
|
770
|
+
let columnHeadersCount = 0;
|
771
|
+
for (let row = 0; row < rows.length; row++) {
|
772
|
+
if (rows[row] >= 0) {
|
773
|
+
break;
|
774
|
+
}
|
775
|
+
columnHeadersCount += 1;
|
776
|
+
}
|
777
|
+
return {
|
778
|
+
columnHeadersCount
|
779
|
+
};
|
780
|
+
}
|
727
781
|
function _addContentEditableToHighlightedCell2() {
|
728
782
|
if (this.hot.isListening()) {
|
729
783
|
const lastSelectedRange = this.hot.getSelectedRangeLast();
|
@@ -14,7 +14,8 @@ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!priva
|
|
14
14
|
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; } }
|
15
15
|
import { BasePlugin } from "../base/index.mjs";
|
16
16
|
import Hooks from "../../pluginHooks.mjs";
|
17
|
-
import { stringify } from "../../3rdparty/SheetClip/index.mjs";
|
17
|
+
import { stringify, parse } from "../../3rdparty/SheetClip/index.mjs";
|
18
|
+
import { arrayEach } from "../../helpers/array.mjs";
|
18
19
|
import { sanitize } from "../../helpers/string.mjs";
|
19
20
|
import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent } from "../../helpers/dom/element.mjs";
|
20
21
|
import { isSafari } from "../../helpers/browser.mjs";
|
@@ -23,10 +24,10 @@ import copyColumnHeadersOnlyItem from "./contextMenuItem/copyColumnHeadersOnly.m
|
|
23
24
|
import copyWithColumnGroupHeadersItem from "./contextMenuItem/copyWithColumnGroupHeaders.mjs";
|
24
25
|
import copyWithColumnHeadersItem from "./contextMenuItem/copyWithColumnHeaders.mjs";
|
25
26
|
import cutItem from "./contextMenuItem/cut.mjs";
|
27
|
+
import PasteEvent from "./pasteEvent.mjs";
|
26
28
|
import { CopyableRangesFactory, normalizeRanges } from "./copyableRanges.mjs";
|
27
|
-
import {
|
29
|
+
import { _dataToHTML, htmlToGridSettings } from "../../utils/parseTable.mjs";
|
28
30
|
import EventManager from "../../eventManager.mjs";
|
29
|
-
import { CopyClipboardData, PasteClipboardData, META_HEAD } from "./clipboardData/index.mjs";
|
30
31
|
Hooks.getSingleton().register('afterCopyLimit');
|
31
32
|
Hooks.getSingleton().register('modifyCopyableRange');
|
32
33
|
Hooks.getSingleton().register('beforeCut');
|
@@ -38,6 +39,7 @@ Hooks.getSingleton().register('afterCopy');
|
|
38
39
|
export const PLUGIN_KEY = 'copyPaste';
|
39
40
|
export const PLUGIN_PRIORITY = 80;
|
40
41
|
const SETTING_KEYS = ['fragmentSelection'];
|
42
|
+
const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
|
41
43
|
|
42
44
|
/* eslint-disable jsdoc/require-description-complete-sentence */
|
43
45
|
/**
|
@@ -82,6 +84,7 @@ var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
|
|
82
84
|
var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
|
83
85
|
var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
|
84
86
|
var _ensureClipboardEventsGetTriggered = /*#__PURE__*/new WeakSet();
|
87
|
+
var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
|
85
88
|
var _addContentEditableToHighlightedCell = /*#__PURE__*/new WeakSet();
|
86
89
|
var _removeContentEditableFromHighlightedCell = /*#__PURE__*/new WeakSet();
|
87
90
|
export class CopyPaste extends BasePlugin {
|
@@ -95,6 +98,15 @@ export class CopyPaste extends BasePlugin {
|
|
95
98
|
* Add the `contenteditable` attribute to the highlighted cell and select its content.
|
96
99
|
*/
|
97
100
|
_classPrivateMethodInitSpec(this, _addContentEditableToHighlightedCell);
|
101
|
+
/**
|
102
|
+
* Counts how many column headers will be copied based on the passed range.
|
103
|
+
*
|
104
|
+
* @private
|
105
|
+
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
|
106
|
+
* @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
|
107
|
+
* information with the number of copied headers.
|
108
|
+
*/
|
109
|
+
_classPrivateMethodInitSpec(this, _countCopiedHeaders);
|
98
110
|
/**
|
99
111
|
* Ensure that the `copy`/`cut` events get triggered properly in Safari.
|
100
112
|
*
|
@@ -379,14 +391,26 @@ export class CopyPaste extends BasePlugin {
|
|
379
391
|
* @returns {Array[]} An array of arrays that will be copied to the clipboard.
|
380
392
|
*/
|
381
393
|
getRangedData(ranges) {
|
394
|
+
const data = [];
|
382
395
|
const {
|
383
396
|
rows,
|
384
397
|
columns
|
385
398
|
} = normalizeRanges(ranges);
|
386
|
-
|
387
|
-
|
388
|
-
|
399
|
+
|
400
|
+
// concatenate all rows and columns data defined in ranges into one copyable string
|
401
|
+
arrayEach(rows, row => {
|
402
|
+
const rowSet = [];
|
403
|
+
arrayEach(columns, column => {
|
404
|
+
if (row < 0) {
|
405
|
+
// `row` as the second argument acts here as the `headerLevel` argument
|
406
|
+
rowSet.push(this.hot.getColHeader(column, row));
|
407
|
+
} else {
|
408
|
+
rowSet.push(this.hot.getCopyableData(row, column));
|
409
|
+
}
|
410
|
+
});
|
411
|
+
data.push(rowSet);
|
389
412
|
});
|
413
|
+
return data;
|
390
414
|
}
|
391
415
|
|
392
416
|
/**
|
@@ -403,17 +427,7 @@ export class CopyPaste extends BasePlugin {
|
|
403
427
|
if (!pastableText && !pastableHtml) {
|
404
428
|
return;
|
405
429
|
}
|
406
|
-
const pasteData =
|
407
|
-
clipboardData: {
|
408
|
-
data: {},
|
409
|
-
setData(type, value) {
|
410
|
-
this.data[type] = value;
|
411
|
-
},
|
412
|
-
getData(type) {
|
413
|
-
return this.data[type];
|
414
|
-
}
|
415
|
-
}
|
416
|
-
};
|
430
|
+
const pasteData = new PasteEvent();
|
417
431
|
if (pastableText) {
|
418
432
|
pasteData.clipboardData.setData('text/plain', pastableText);
|
419
433
|
}
|
@@ -552,7 +566,7 @@ export class CopyPaste extends BasePlugin {
|
|
552
566
|
/**
|
553
567
|
* `copy` event callback on textarea element.
|
554
568
|
*
|
555
|
-
* @param {
|
569
|
+
* @param {Event} event ClipboardEvent.
|
556
570
|
* @private
|
557
571
|
*/
|
558
572
|
onCopy(event) {
|
@@ -561,12 +575,19 @@ export class CopyPaste extends BasePlugin {
|
|
561
575
|
}
|
562
576
|
this.setCopyableText();
|
563
577
|
_classPrivateFieldSet(this, _isTriggeredByCopy, false);
|
564
|
-
const
|
565
|
-
const
|
578
|
+
const data = this.getRangedData(this.copyableRanges);
|
579
|
+
const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
|
580
|
+
const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
|
566
581
|
if (allowCopying) {
|
567
|
-
|
568
|
-
|
569
|
-
|
582
|
+
const textPlain = stringify(data);
|
583
|
+
if (event && event.clipboardData) {
|
584
|
+
const textHTML = _dataToHTML(data, this.hot.rootDocument);
|
585
|
+
event.clipboardData.setData('text/plain', textPlain);
|
586
|
+
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
587
|
+
} else if (typeof ClipboardEvent === 'undefined') {
|
588
|
+
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
589
|
+
}
|
590
|
+
this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
|
570
591
|
}
|
571
592
|
_classPrivateFieldSet(this, _copyMode, 'cells-only');
|
572
593
|
event.preventDefault();
|
@@ -575,7 +596,7 @@ export class CopyPaste extends BasePlugin {
|
|
575
596
|
/**
|
576
597
|
* `cut` event callback on textarea element.
|
577
598
|
*
|
578
|
-
* @param {
|
599
|
+
* @param {Event} event ClipboardEvent.
|
579
600
|
* @private
|
580
601
|
*/
|
581
602
|
onCut(event) {
|
@@ -584,13 +605,19 @@ export class CopyPaste extends BasePlugin {
|
|
584
605
|
}
|
585
606
|
this.setCopyableText();
|
586
607
|
_classPrivateFieldSet(this, _isTriggeredByCut, false);
|
587
|
-
const
|
588
|
-
const allowCuttingOut = !!this.hot.runHooks('beforeCut',
|
608
|
+
const rangedData = this.getRangedData(this.copyableRanges);
|
609
|
+
const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
|
589
610
|
if (allowCuttingOut) {
|
590
|
-
|
591
|
-
|
611
|
+
const textPlain = stringify(rangedData);
|
612
|
+
if (event && event.clipboardData) {
|
613
|
+
const textHTML = _dataToHTML(rangedData, this.hot.rootDocument);
|
614
|
+
event.clipboardData.setData('text/plain', textPlain);
|
615
|
+
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
616
|
+
} else if (typeof ClipboardEvent === 'undefined') {
|
617
|
+
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
618
|
+
}
|
592
619
|
this.hot.emptySelectedCells('CopyPaste.cut');
|
593
|
-
this.hot.runHooks('afterCut',
|
620
|
+
this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
|
594
621
|
}
|
595
622
|
event.preventDefault();
|
596
623
|
}
|
@@ -608,22 +635,34 @@ export class CopyPaste extends BasePlugin {
|
|
608
635
|
if (event && event.preventDefault) {
|
609
636
|
event.preventDefault();
|
610
637
|
}
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
638
|
+
let pastedData;
|
639
|
+
if (event && typeof event.clipboardData !== 'undefined') {
|
640
|
+
const textHTML = sanitize(event.clipboardData.getData('text/html'), {
|
641
|
+
ADD_TAGS: ['meta'],
|
642
|
+
ADD_ATTR: ['content'],
|
643
|
+
FORCE_BODY: true
|
644
|
+
});
|
645
|
+
if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
|
646
|
+
const parsedConfig = htmlToGridSettings(textHTML, this.hot.rootDocument);
|
647
|
+
pastedData = parsedConfig.data;
|
648
|
+
} else {
|
649
|
+
pastedData = event.clipboardData.getData('text/plain');
|
650
|
+
}
|
651
|
+
} else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
|
652
|
+
pastedData = this.hot.rootWindow.clipboardData.getData('Text');
|
653
|
+
}
|
654
|
+
if (typeof pastedData === 'string') {
|
655
|
+
pastedData = parse(pastedData);
|
656
|
+
}
|
657
|
+
if (pastedData === void 0 || pastedData && pastedData.length === 0) {
|
618
658
|
return;
|
619
659
|
}
|
620
|
-
|
621
|
-
if (pastedTable.length === 0) {
|
660
|
+
if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
|
622
661
|
return;
|
623
662
|
}
|
624
|
-
const [startRow, startColumn, endRow, endColumn] = this.populateValues(
|
663
|
+
const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
|
625
664
|
this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
|
626
|
-
this.hot.runHooks('afterPaste',
|
665
|
+
this.hot.runHooks('afterPaste', pastedData, this.copyableRanges);
|
627
666
|
}
|
628
667
|
|
629
668
|
/**
|
@@ -719,6 +758,21 @@ function _ensureClipboardEventsGetTriggered2(eventName) {
|
|
719
758
|
this.hot.rootDocument.execCommand(eventName);
|
720
759
|
}
|
721
760
|
}
|
761
|
+
function _countCopiedHeaders2(ranges) {
|
762
|
+
const {
|
763
|
+
rows
|
764
|
+
} = normalizeRanges(ranges);
|
765
|
+
let columnHeadersCount = 0;
|
766
|
+
for (let row = 0; row < rows.length; row++) {
|
767
|
+
if (rows[row] >= 0) {
|
768
|
+
break;
|
769
|
+
}
|
770
|
+
columnHeadersCount += 1;
|
771
|
+
}
|
772
|
+
return {
|
773
|
+
columnHeadersCount
|
774
|
+
};
|
775
|
+
}
|
722
776
|
function _addContentEditableToHighlightedCell2() {
|
723
777
|
if (this.hot.isListening()) {
|
724
778
|
const lastSelectedRange = this.hot.getSelectedRangeLast();
|
@@ -0,0 +1,14 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
exports.__esModule = true;
|
4
|
+
var _clipboardData = _interopRequireDefault(require("./clipboardData"));
|
5
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
6
|
+
/**
|
7
|
+
* @private
|
8
|
+
*/
|
9
|
+
class PasteEvent {
|
10
|
+
constructor() {
|
11
|
+
this.clipboardData = new _clipboardData.default();
|
12
|
+
}
|
13
|
+
}
|
14
|
+
exports.default = PasteEvent;
|
@@ -529,44 +529,45 @@ class NestedHeaders extends _base.BasePlugin {
|
|
529
529
|
* of the column.
|
530
530
|
*
|
531
531
|
* @private
|
532
|
-
* @param {
|
533
|
-
* @param {
|
534
|
-
*
|
535
|
-
* @param {
|
536
|
-
*
|
537
|
-
* @param {Function} clipboardData.setCellAt Change headers or cells in the copied/pasted dataset.
|
538
|
-
* @param {Function} clipboardData.getCellAt Get headers or cells from the copied/pasted dataset.
|
539
|
-
* @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
|
540
|
-
* @param {Function} clipboardData.getMetaInfo Gets grid settings for copied data.
|
541
|
-
* @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
|
532
|
+
* @param {Array[]} data An array of arrays which contains data to copied.
|
533
|
+
* @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
|
534
|
+
* which will copied.
|
535
|
+
* @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
|
536
|
+
* the number of copied headers.
|
542
537
|
*/
|
543
|
-
onBeforeCopy(
|
544
|
-
|
545
|
-
|
538
|
+
onBeforeCopy(data, copyableRanges, _ref2) {
|
539
|
+
let {
|
540
|
+
columnHeadersCount
|
541
|
+
} = _ref2;
|
542
|
+
if (columnHeadersCount === 0) {
|
543
|
+
return;
|
544
|
+
}
|
545
|
+
for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++) {
|
546
546
|
const {
|
547
547
|
startRow,
|
548
548
|
startCol,
|
549
549
|
endRow,
|
550
550
|
endCol
|
551
551
|
} = copyableRanges[rangeIndex];
|
552
|
+
const rowsCount = endRow - startRow + 1;
|
552
553
|
const columnsCount = startCol - endCol + 1;
|
553
554
|
|
554
555
|
// do not process dataset ranges and column headers where only one column is copied
|
555
556
|
if (startRow >= 0 || columnsCount === 1) {
|
556
557
|
break;
|
557
558
|
}
|
558
|
-
for (let column = startCol; column <= endCol; column
|
559
|
-
for (let row = startRow; row <= endRow; row
|
560
|
-
var _classPrivateFieldGet4
|
559
|
+
for (let column = startCol; column <= endCol; column++) {
|
560
|
+
for (let row = startRow; row <= endRow; row++) {
|
561
|
+
var _classPrivateFieldGet4;
|
562
|
+
const zeroBasedColumnHeaderLevel = rowsCount + row;
|
561
563
|
const zeroBasedColumnIndex = column - startCol;
|
562
564
|
if (zeroBasedColumnIndex === 0) {
|
563
565
|
continue; // eslint-disable-line no-continue
|
564
566
|
}
|
565
567
|
|
566
568
|
const isRoot = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.isRoot;
|
567
|
-
|
568
|
-
|
569
|
-
clipboardData.setCellAt(row, zeroBasedColumnIndex, '');
|
569
|
+
if (isRoot === false) {
|
570
|
+
data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
|
570
571
|
}
|
571
572
|
}
|
572
573
|
}
|
@@ -869,10 +870,10 @@ class NestedHeaders extends _base.BasePlugin {
|
|
869
870
|
* @returns {string} Returns the column header value to update.
|
870
871
|
*/
|
871
872
|
onModifyColumnHeaderValue(value, visualColumnIndex, headerLevel) {
|
872
|
-
var
|
873
|
+
var _classPrivateFieldGet5;
|
873
874
|
const {
|
874
875
|
label
|
875
|
-
} = (
|
876
|
+
} = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet5 !== void 0 ? _classPrivateFieldGet5 : {
|
876
877
|
label: ''
|
877
878
|
};
|
878
879
|
return label;
|
@@ -525,44 +525,45 @@ export class NestedHeaders extends BasePlugin {
|
|
525
525
|
* of the column.
|
526
526
|
*
|
527
527
|
* @private
|
528
|
-
* @param {
|
529
|
-
* @param {
|
530
|
-
*
|
531
|
-
* @param {
|
532
|
-
*
|
533
|
-
* @param {Function} clipboardData.setCellAt Change headers or cells in the copied/pasted dataset.
|
534
|
-
* @param {Function} clipboardData.getCellAt Get headers or cells from the copied/pasted dataset.
|
535
|
-
* @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
|
536
|
-
* @param {Function} clipboardData.getMetaInfo Gets grid settings for copied data.
|
537
|
-
* @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
|
528
|
+
* @param {Array[]} data An array of arrays which contains data to copied.
|
529
|
+
* @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
|
530
|
+
* which will copied.
|
531
|
+
* @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
|
532
|
+
* the number of copied headers.
|
538
533
|
*/
|
539
|
-
onBeforeCopy(
|
540
|
-
|
541
|
-
|
534
|
+
onBeforeCopy(data, copyableRanges, _ref2) {
|
535
|
+
let {
|
536
|
+
columnHeadersCount
|
537
|
+
} = _ref2;
|
538
|
+
if (columnHeadersCount === 0) {
|
539
|
+
return;
|
540
|
+
}
|
541
|
+
for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++) {
|
542
542
|
const {
|
543
543
|
startRow,
|
544
544
|
startCol,
|
545
545
|
endRow,
|
546
546
|
endCol
|
547
547
|
} = copyableRanges[rangeIndex];
|
548
|
+
const rowsCount = endRow - startRow + 1;
|
548
549
|
const columnsCount = startCol - endCol + 1;
|
549
550
|
|
550
551
|
// do not process dataset ranges and column headers where only one column is copied
|
551
552
|
if (startRow >= 0 || columnsCount === 1) {
|
552
553
|
break;
|
553
554
|
}
|
554
|
-
for (let column = startCol; column <= endCol; column
|
555
|
-
for (let row = startRow; row <= endRow; row
|
556
|
-
var _classPrivateFieldGet4
|
555
|
+
for (let column = startCol; column <= endCol; column++) {
|
556
|
+
for (let row = startRow; row <= endRow; row++) {
|
557
|
+
var _classPrivateFieldGet4;
|
558
|
+
const zeroBasedColumnHeaderLevel = rowsCount + row;
|
557
559
|
const zeroBasedColumnIndex = column - startCol;
|
558
560
|
if (zeroBasedColumnIndex === 0) {
|
559
561
|
continue; // eslint-disable-line no-continue
|
560
562
|
}
|
561
563
|
|
562
564
|
const isRoot = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.isRoot;
|
563
|
-
|
564
|
-
|
565
|
-
clipboardData.setCellAt(row, zeroBasedColumnIndex, '');
|
565
|
+
if (isRoot === false) {
|
566
|
+
data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
|
566
567
|
}
|
567
568
|
}
|
568
569
|
}
|
@@ -865,10 +866,10 @@ export class NestedHeaders extends BasePlugin {
|
|
865
866
|
* @returns {string} Returns the column header value to update.
|
866
867
|
*/
|
867
868
|
onModifyColumnHeaderValue(value, visualColumnIndex, headerLevel) {
|
868
|
-
var
|
869
|
+
var _classPrivateFieldGet5;
|
869
870
|
const {
|
870
871
|
label
|
871
|
-
} = (
|
872
|
+
} = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet5 !== void 0 ? _classPrivateFieldGet5 : {
|
872
873
|
label: ''
|
873
874
|
};
|
874
875
|
return label;
|