// Adopted and converted to typescript from https://github.com/6pac/SlickGrid/blob/master/plugins/slick.checkboxselectcolumn.js import { mixin } from 'vs/base/common/objects'; import * as nls from 'vs/nls'; import { ICheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox'; import * as strings from 'vs/base/common/strings'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { range } from 'vs/base/common/arrays'; export interface ICheckboxSelectColumnOptions extends Slick.PluginOptions, ICheckboxStyles { columnId?: string; cssClass?: string; toolTip?: string; width?: number; title?: string; } const defaultOptions: ICheckboxSelectColumnOptions = { columnId: '_checkbox_selector', cssClass: undefined, toolTip: nls.localize('selectDeselectAll', 'Select/Deselect All'), width: 30 }; const checkboxTemplate = `
`; export class CheckboxSelectColumn implements Slick.Plugin { private _options: ICheckboxSelectColumnOptions; private _grid: Slick.Grid; private _handler = new Slick.EventHandler(); private _selectedRowsLookup = {}; constructor(options?: ICheckboxSelectColumnOptions) { this._options = mixin(options, defaultOptions, false); } public init(grid: Slick.Grid): void { this._grid = grid; this._handler .subscribe(this._grid.onSelectedRowsChanged, (e, args) => this.handleSelectedRowsChanged(e, args)) .subscribe(this._grid.onClick, (e, args) => this.handleClick(e, args)) .subscribe(this._grid.onHeaderClick, (e, args) => this.handleHeaderClick(e, args)) .subscribe(this._grid.onKeyDown, (e, args) => this.handleKeyDown(e, args)); } public destroy(): void { this._handler.unsubscribeAll(); } private handleSelectedRowsChanged(e: Event, args: Slick.OnSelectedRowsChangedEventArgs): void { const selectedRows = this._grid.getSelectedRows(); let lookup = {}, row, i; for (i = 0; i < selectedRows.length; i++) { row = selectedRows[i]; lookup[row] = true; if (lookup[row] !== this._selectedRowsLookup[row]) { this._grid.invalidateRow(row); delete this._selectedRowsLookup[row]; } } for (i in this._selectedRowsLookup) { this._grid.invalidateRow(i); } this._selectedRowsLookup = lookup; this._grid.render(); if (!this._options.title) { if (selectedRows.length && selectedRows.length === this._grid.getDataLength()) { this._grid.updateColumnHeader(this._options.columnId!, strings.format(checkboxTemplate, 'checked'), this._options.toolTip); } else { this._grid.updateColumnHeader(this._options.columnId!, strings.format(checkboxTemplate, ''), this._options.toolTip); } } } private handleKeyDown(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs): void { if (e.which === 32) { if (this._grid.getColumns()[args.cell].id === this._options.columnId) { // if editing, try to commit if (!this._grid.getEditorLock().isActive() || this._grid.getEditorLock().commitCurrentEdit()) { this.toggleRowSelection(args.row); } e.preventDefault(); e.stopImmediatePropagation(); } } else { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Enter)) { // clicking on a row select checkbox if (this._grid.getColumns()[args.cell].id === this._options.columnId) { this.toggleRowSelection(args.row); e.stopPropagation(); e.stopImmediatePropagation(); } } } } private handleClick(e: Event, args: Slick.OnClickEventArgs): void { // clicking on a row select checkbox if (this._grid.getColumns()[args.cell].id === this._options.columnId && jQuery(e.target!).is('input[type="checkbox"]')) { // if editing, try to commit if (this._grid.getEditorLock().isActive() && !this._grid.getEditorLock().commitCurrentEdit()) { e.preventDefault(); e.stopImmediatePropagation(); return; } this.toggleRowSelection(args.row); e.stopPropagation(); e.stopImmediatePropagation(); } } private toggleRowSelection(row: number): void { if (this._selectedRowsLookup[row]) { this._grid.setSelectedRows(this._grid.getSelectedRows().filter(n => n !== row)); } else { this._grid.setSelectedRows(this._grid.getSelectedRows().concat(row)); } } private handleHeaderClick(e: Event, args: Slick.OnHeaderClickEventArgs): void { if (!this._options.title && args.column.id === this._options.columnId && jQuery(e.target!).is('input[type="checkbox"]')) { // if editing, try to commit if (this._grid.getEditorLock().isActive() && !this._grid.getEditorLock().commitCurrentEdit()) { e.preventDefault(); e.stopImmediatePropagation(); return; } if (jQuery(e.target!).is('input[checked]')) { const rows = range(this._grid.getDataLength()); this._grid.setSelectedRows(rows); this._grid.updateColumnHeader(this._options.columnId!, strings.format(checkboxTemplate, 'checked'), this._options.toolTip); } else { this._grid.setSelectedRows([]); this._grid.updateColumnHeader(this._options.columnId!, strings.format(checkboxTemplate, ''), this._options.toolTip); e.stopPropagation(); e.stopImmediatePropagation(); } } } public getColumnDefinition(): Slick.Column { return { id: this._options.columnId, name: this._options.title || strings.format(checkboxTemplate, ''), toolTip: this._options.toolTip, field: 'sel', width: this._options.width, resizable: false, sortable: false, cssClass: this._options.cssClass, formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc) }; } private checkboxSelectionFormatter(row, cell, value, columnDef: Slick.Column, dataContext): string { return this._selectedRowsLookup[row] ? strings.format(checkboxTemplate, 'checked') : strings.format(checkboxTemplate, ''); } }