slickgrid
Version:
A lightning fast JavaScript grid/spreadsheet
88 lines (75 loc) • 2.97 kB
text/typescript
import type { CSSStyleDeclarationWritable, CellRangeDecoratorOption, SlickPlugin } from '../models/index.js';
import { 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 Utils = IIFE_ONLY ? Slick.Utils : Utils_;
/***
* Displays an overlay on top of a given cell range.
*
* TODO:
* Currently, it blocks mouse events to DOM nodes behind it.
* Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
* Could also construct the borders separately using 4 individual DIVs.
*
* @param {Grid} grid
* @param {Object} options
*/
export class SlickCellRangeDecorator implements SlickPlugin {
// --
// public API
pluginName = 'CellRangeDecorator' as const;
// --
// protected props
protected _options: CellRangeDecoratorOption;
protected _elem?: HTMLDivElement | null;
protected _defaults = {
selectionCssClass: 'slick-range-decorator',
selectionCss: {
zIndex: '9999',
border: '2px dashed red'
},
offset: { top: -1, left: -1, height: -2, width: -2 }
} as CellRangeDecoratorOption;
constructor(protected readonly grid: SlickGrid, options?: Partial<CellRangeDecoratorOption>) {
this._options = Utils.extend(true, {}, this._defaults, options);
}
destroy() {
this.hide();
}
init() { }
hide() {
this._elem?.remove();
this._elem = null;
}
show(range: SlickRange) {
if (!this._elem) {
this._elem = document.createElement('div');
this._elem.className = this._options.selectionCssClass;
Object.keys(this._options.selectionCss as CSSStyleDeclaration).forEach((cssStyleKey) => {
this._elem!.style[cssStyleKey as CSSStyleDeclarationWritable] = this._options.selectionCss[cssStyleKey as CSSStyleDeclarationWritable];
});
this._elem.style.position = 'absolute';
const canvasNode = this.grid.getActiveCanvasNode();
if (canvasNode) {
canvasNode.appendChild(this._elem);
}
}
const from = this.grid.getCellNodeBox(range.fromRow, range.fromCell);
const to = this.grid.getCellNodeBox(range.toRow, range.toCell);
if (from && to && this._options?.offset) {
this._elem.style.top = `${from.top + this._options.offset.top}px`;
this._elem.style.left = `${from.left + this._options.offset.left}px`;
this._elem.style.height = `${to.bottom - from.top + this._options.offset.height}px`;
this._elem.style.width = `${to.right - from.left + this._options.offset.width}px`;
}
return this._elem;
}
}
// extend Slick namespace on window object when building as iife
if (IIFE_ONLY && window.Slick) {
Utils.extend(true, window, {
Slick: {
CellRangeDecorator: SlickCellRangeDecorator
}
});
}