slickgrid
Version:
A lightning fast JavaScript grid/spreadsheet
99 lines (87 loc) • 3.35 kB
text/typescript
import type { CssStyleHash, SlickPlugin } from '../models/index.js';
import { keyCode as keyCode_, SlickEvent as SlickEvent_, type SlickEventData, Utils as Utils_, type SlickRange } from '../slick.core.js';
import type { SlickGrid } from '../slick.grid.js';
// for (iife) load Slick methods from global Slick object, or use imports for (esm)
const keyCode = IIFE_ONLY ? Slick.keyCode : keyCode_;
const SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;
const Utils = IIFE_ONLY ? Slick.Utils : Utils_;
/**
* This manager enables users to copy/paste cell data
*/
export class SlickCellCopyManager implements SlickPlugin {
// --
// public API
pluginName = 'CellCopyManager' as const;
onCopyCells = new SlickEvent<{ ranges: SlickRange[] | null; }>('onCopyCells');
onCopyCancelled = new SlickEvent<{ ranges: SlickRange[] | null; }>('onCopyCancelled');
onPasteCells = new SlickEvent<{ from: SlickRange[] | undefined; to: SlickRange[] | undefined; }>('onPasteCells');
// --
// protected props
protected _grid!: SlickGrid;
protected _copiedRanges?: SlickRange[] | null = null;
init(grid: SlickGrid) {
this._grid = grid;
Utils.addSlickEventPubSubWhenDefined(grid.getPubSubService(), this);
this._grid.onKeyDown.subscribe(this.handleKeyDown.bind(this));
}
destroy() {
this._grid.onKeyDown.unsubscribe(this.handleKeyDown.bind(this));
}
protected handleKeyDown(e: SlickEventData) {
let ranges: SlickRange[] | undefined;
if (!this._grid.getEditorLock().isActive()) {
if (e.which === keyCode.ESCAPE) {
if (this._copiedRanges) {
e.preventDefault();
this.clearCopySelection();
this.onCopyCancelled.notify({ ranges: this._copiedRanges });
this._copiedRanges = null;
}
}
if (e.which === 67 && (e.ctrlKey || e.metaKey)) {
ranges = this._grid.getSelectionModel()?.getSelectedRanges() ?? [];
if (ranges.length !== 0) {
e.preventDefault();
this._copiedRanges = ranges;
this.markCopySelection(ranges);
this.onCopyCells.notify({ ranges });
}
}
if (e.which === 86 && (e.ctrlKey || e.metaKey)) {
if (this._copiedRanges) {
e.preventDefault();
ranges = this._grid.getSelectionModel()?.getSelectedRanges();
this.onPasteCells.notify({ from: this._copiedRanges, to: ranges });
if (!this._grid.getOptions().preserveCopiedSelectionOnPaste) {
this.clearCopySelection();
this._copiedRanges = null;
}
}
}
}
}
protected markCopySelection(ranges: SlickRange[]) {
const columns = this._grid.getColumns();
const hash: CssStyleHash = {};
for (let i = 0; i < ranges.length; i++) {
for (let j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
hash[j] = {};
for (let k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
hash[j][columns[k].id] = 'copied';
}
}
}
this._grid.setCellCssStyles('copy-manager', hash);
}
protected clearCopySelection() {
this._grid.removeCellCssStyles('copy-manager');
}
}
// extend Slick namespace on window object when building as iife
if (IIFE_ONLY && window.Slick) {
Utils.extend(true, window, {
Slick: {
CellCopyManager: SlickCellCopyManager
}
});
}