mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-21 09:35:38 -05:00
Add no implicit any to the strict null check (#5635)
* wip * working through adding no implicit any
This commit is contained in:
@@ -222,4 +222,8 @@ export class AsyncDataProvider<T extends Slick.SlickData> implements IDisposable
|
||||
dispose() {
|
||||
this.dataRows.dispose();
|
||||
}
|
||||
|
||||
getItems(): T[] {
|
||||
throw new Error('Method not supported.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export class AdditionalKeyBindings<T> implements Slick.Plugin<T> {
|
||||
|
||||
public init(grid: Slick.Grid<T>) {
|
||||
this.grid = grid;
|
||||
this.handler.subscribe(this.grid.onKeyDown, (e, args) => this.handleKeyDown(e, args));
|
||||
this.handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent, args) => this.handleKeyDown(e, args));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
||||
@@ -49,7 +49,7 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
||||
|
||||
// since data can be async we want to only do this if we have the data to actual
|
||||
// work on since we are measuring the physical length of data
|
||||
let data = this._grid.getData();
|
||||
let data = this._grid.getData() as Slick.DataProvider<T>;
|
||||
let item = data.getItem(0);
|
||||
if (item && Object.keys(item).length > 0) {
|
||||
let hasValue = false;
|
||||
@@ -134,15 +134,15 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private getMaxColumnTextWidth(columnDef, colIndex: number): number {
|
||||
private getMaxColumnTextWidth(columnDef: Slick.Column<T>, colIndex: number): number {
|
||||
let texts: Array<string> = [];
|
||||
let rowEl = this.createRow(columnDef);
|
||||
let data = this._grid.getData();
|
||||
let rowEl = this.createRow();
|
||||
let data = this._grid.getData() as Slick.DataProvider<T>;
|
||||
let viewPort = this._grid.getViewport();
|
||||
let start = Math.max(0, viewPort.top);
|
||||
let end = Math.min(data.getLength(), viewPort.bottom);
|
||||
for (let i = start; i < end; i++) {
|
||||
texts.push(data.getItem(i)[columnDef.field]);
|
||||
texts.push(data.getItem(i)[columnDef.field!]);
|
||||
}
|
||||
let template = this.getMaxTextTemplate(texts, columnDef, colIndex, data, rowEl);
|
||||
let width = this.getTemplateWidth(rowEl, template);
|
||||
@@ -150,21 +150,21 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
||||
return width > this._options.maxWidth! ? this._options.maxWidth! : width;
|
||||
}
|
||||
|
||||
private getTemplateWidth(rowEl: JQuery, template: JQuery | HTMLElement): number {
|
||||
private getTemplateWidth(rowEl: JQuery, template: JQuery | HTMLElement | string): number {
|
||||
let cell = jQuery(rowEl.find('.slick-cell'));
|
||||
cell.append(template);
|
||||
jQuery(cell).find('*').css('position', 'relative');
|
||||
return cell.outerWidth() + 1;
|
||||
}
|
||||
|
||||
private getMaxTextTemplate(texts: string[], columnDef, colIndex: number, data, rowEl: JQuery): JQuery | HTMLElement {
|
||||
private getMaxTextTemplate(texts: string[], columnDef: Slick.Column<T>, colIndex: number, data: Slick.DataProvider<T>, rowEl: JQuery): JQuery | HTMLElement | string {
|
||||
let max = 0,
|
||||
maxTemplate = null;
|
||||
maxTemplate: JQuery | HTMLElement | string | undefined;
|
||||
let formatFun = columnDef.formatter;
|
||||
texts.forEach((text, index) => {
|
||||
let template;
|
||||
if (formatFun) {
|
||||
template = jQuery('<span>' + formatFun(index, colIndex, text, columnDef, data[index]) + '</span>');
|
||||
template = jQuery('<span>' + formatFun(index, colIndex, text, columnDef, data.getItem(index)) + '</span>');
|
||||
text = template.text() || text;
|
||||
}
|
||||
let length = text ? this.getElementWidthUsingCanvas(rowEl, text) : 0;
|
||||
@@ -176,7 +176,7 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
||||
return maxTemplate!;
|
||||
}
|
||||
|
||||
private createRow(columnDef): JQuery {
|
||||
private createRow(): JQuery {
|
||||
let rowEl = jQuery('<div class="slick-row"><div class="slick-cell"></div></div>');
|
||||
rowEl.find('.slick-cell').css({
|
||||
'visibility': 'hidden',
|
||||
|
||||
@@ -26,13 +26,13 @@ export interface ICellRangeSelectorOptions {
|
||||
}
|
||||
|
||||
export interface ICellRangeSelector<T> extends Slick.Plugin<T> {
|
||||
onCellRangeSelected: Slick.Event<{ range: Slick.Range }>;
|
||||
onCellRangeSelected: Slick.Event<Slick.Range>;
|
||||
onBeforeCellRangeSelected: Slick.Event<Slick.Cell>;
|
||||
}
|
||||
|
||||
export interface ICellRangeDecorator {
|
||||
show(range: Slick.Range);
|
||||
hide();
|
||||
show(range: Slick.Range): void;
|
||||
hide(): void;
|
||||
}
|
||||
|
||||
export class CellRangeSelector<T> implements ICellRangeSelector<T> {
|
||||
@@ -44,7 +44,7 @@ export class CellRangeSelector<T> implements ICellRangeSelector<T> {
|
||||
private currentlySelectedRange: { start: Slick.Cell, end?: Slick.Cell };
|
||||
|
||||
public onBeforeCellRangeSelected = new Slick.Event<Slick.Cell>();
|
||||
public onCellRangeSelected = new Slick.Event<{ range: Slick.Range }>();
|
||||
public onCellRangeSelected = new Slick.Event<Slick.Range>();
|
||||
|
||||
constructor(private options: ICellRangeSelectorOptions) {
|
||||
require.__$__nodeRequire('slickgrid/plugins/slick.cellrangedecorator');
|
||||
@@ -58,9 +58,9 @@ export class CellRangeSelector<T> implements ICellRangeSelector<T> {
|
||||
this.canvas = this.grid.getCanvasNode();
|
||||
this.handler
|
||||
.subscribe(this.grid.onDragInit, e => this.handleDragInit(e))
|
||||
.subscribe(this.grid.onDragStart, (e, dd) => this.handleDragStart(e, dd))
|
||||
.subscribe(this.grid.onDrag, (e, dd) => this.handleDrag(e, dd))
|
||||
.subscribe(this.grid.onDragEnd, (e, dd) => this.handleDragEnd(e, dd));
|
||||
.subscribe(this.grid.onDragStart, (e: MouseEvent, dd) => this.handleDragStart(e, dd))
|
||||
.subscribe(this.grid.onDrag, (e: MouseEvent, dd) => this.handleDrag(e, dd))
|
||||
.subscribe(this.grid.onDragEnd, (e: MouseEvent, dd) => this.handleDragEnd(e, dd));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
@@ -138,13 +138,11 @@ export class CellRangeSelector<T> implements ICellRangeSelector<T> {
|
||||
if (!dd || !dd.range || !dd.range.start || !dd.range.end) {
|
||||
return;
|
||||
}
|
||||
this.onCellRangeSelected.notify({
|
||||
range: new Slick.Range(
|
||||
dd.range.start.row,
|
||||
dd.range.start.cell,
|
||||
dd.range.end.row,
|
||||
dd.range.end.cell
|
||||
)
|
||||
});
|
||||
this.onCellRangeSelected.notify(new Slick.Range(
|
||||
dd.range.start.row,
|
||||
dd.range.start.cell,
|
||||
dd.range.end.row,
|
||||
dd.range.end.cell
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
private grid: Slick.Grid<T>;
|
||||
private selector: ICellRangeSelector<T>;
|
||||
private ranges: Array<Slick.Range> = [];
|
||||
private _handler = new Slick.EventHandler();
|
||||
|
||||
public onSelectedRangesChanged = new Slick.Event<Array<Slick.Range>>();
|
||||
|
||||
@@ -35,19 +36,16 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
|
||||
public init(grid: Slick.Grid<T>) {
|
||||
this.grid = grid;
|
||||
this.grid.onActiveCellChanged.subscribe((e, args) => this.handleActiveCellChange(e, args));
|
||||
this.grid.onKeyDown.subscribe(e => this.handleKeyDown(e));
|
||||
this.grid.onHeaderClick.subscribe((e: MouseEvent, args) => this.handleHeaderClick(e, args));
|
||||
this._handler.subscribe(this.grid.onActiveCellChanged, (e: Event, args: Slick.OnActiveCellChangedEventArgs<T>) => this.handleActiveCellChange(e, args));
|
||||
this._handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e));
|
||||
this._handler.subscribe(this.grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs<T>) => this.handleHeaderClick(e, args));
|
||||
this.grid.registerPlugin(this.selector);
|
||||
this.selector.onCellRangeSelected.subscribe((e, args) => this.handleCellRangeSelected(e, args));
|
||||
this.selector.onBeforeCellRangeSelected.subscribe((e, args) => this.handleBeforeCellRangeSelected(e, args));
|
||||
this._handler.subscribe(this.selector.onCellRangeSelected, (e: Event, range: Slick.Range) => this.handleCellRangeSelected(e, range));
|
||||
this._handler.subscribe(this.selector.onBeforeCellRangeSelected, (e: Event, cell: Slick.Cell) => this.handleBeforeCellRangeSelected(e, cell));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.grid.onActiveCellChanged.unsubscribe((e, args) => this.handleActiveCellChange(e, args));
|
||||
this.grid.onKeyDown.unsubscribe(e => this.handleKeyDown(e));
|
||||
this.selector.onCellRangeSelected.unsubscribe((e, args) => this.handleCellRangeSelected(e, args));
|
||||
this.selector.onBeforeCellRangeSelected.unsubscribe((e, args) => this.handleBeforeCellRangeSelected(e, args));
|
||||
this._handler.unsubscribeAll();
|
||||
this.grid.unregisterPlugin(this.selector);
|
||||
}
|
||||
|
||||
@@ -81,7 +79,7 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
return this.ranges;
|
||||
}
|
||||
|
||||
private handleBeforeCellRangeSelected(e, args: Slick.Cell) {
|
||||
private handleBeforeCellRangeSelected(e: Event, args: Slick.Cell) {
|
||||
if (this.grid.getEditorLock().isActive()) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
@@ -89,12 +87,12 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
return true;
|
||||
}
|
||||
|
||||
private handleCellRangeSelected(e, args: { range: Slick.Range }) {
|
||||
this.grid.setActiveCell(args.range.fromRow, args.range.fromCell, false, false, true);
|
||||
this.setSelectedRanges([args.range]);
|
||||
private handleCellRangeSelected(e: Event, range: Slick.Range) {
|
||||
this.grid.setActiveCell(range.fromRow, range.fromCell, false, false, true);
|
||||
this.setSelectedRanges([range]);
|
||||
}
|
||||
|
||||
private handleActiveCellChange(e, args) {
|
||||
private handleActiveCellChange(e: Event, args: Slick.OnActiveCellChangedEventArgs<T>) {
|
||||
if (this.options.selectActiveCell && !isUndefinedOrNull(args.row) && !isUndefinedOrNull(args.cell)) {
|
||||
this.setSelectedRanges([new Slick.Range(args.row, args.cell)]);
|
||||
} else if (!this.options.selectActiveCell) {
|
||||
@@ -120,7 +118,7 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
}
|
||||
}
|
||||
|
||||
private handleKeyDown(e) {
|
||||
private handleKeyDown(e: KeyboardEvent) {
|
||||
/***
|
||||
* Кey codes
|
||||
* 37 left
|
||||
@@ -128,12 +126,12 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
* 39 right
|
||||
* 40 down
|
||||
*/
|
||||
let ranges, last;
|
||||
let active = this.grid.getActiveCell();
|
||||
let metaKey = e.ctrlKey || e.metaKey;
|
||||
|
||||
if (active && e.shiftKey && !metaKey && !e.altKey &&
|
||||
(e.which === 37 || e.which === 39 || e.which === 38 || e.which === 40)) {
|
||||
let ranges = this.getSelectedRanges(), last: Slick.Range;
|
||||
|
||||
ranges = this.getSelectedRanges();
|
||||
if (!ranges.length) {
|
||||
@@ -141,7 +139,7 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
|
||||
}
|
||||
|
||||
// keyboard can work with last range only
|
||||
last = ranges.pop();
|
||||
last = ranges.pop()!; // this is guarenteed since if ranges is empty we add one
|
||||
|
||||
// can't handle selection out of active cell
|
||||
if (!last.contains(active.row, active.cell)) {
|
||||
|
||||
@@ -8,6 +8,7 @@ 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';
|
||||
import * as dict from 'vs/base/common/collections';
|
||||
|
||||
export interface ICheckboxSelectColumnOptions extends Slick.PluginOptions, ICheckboxStyles {
|
||||
columnId?: string;
|
||||
@@ -44,11 +45,11 @@ const checkboxTemplate = `<div style="display: flex; align-items: center; flex-d
|
||||
<input type="checkbox" {0}>
|
||||
</div>`;
|
||||
|
||||
export class CheckboxSelectColumn<T> implements Slick.Plugin<T> {
|
||||
export class CheckboxSelectColumn<T extends Slick.SlickData> implements Slick.Plugin<T> {
|
||||
private _options: ICheckboxSelectColumnOptions;
|
||||
private _grid: Slick.Grid<T>;
|
||||
private _handler = new Slick.EventHandler();
|
||||
private _selectedRowsLookup = {};
|
||||
private _selectedRowsLookup: dict.INumberDictionary<boolean> = {};
|
||||
private _selectedCheckBoxLookup = {};
|
||||
private _useState = false;
|
||||
|
||||
@@ -64,10 +65,10 @@ export class CheckboxSelectColumn<T> implements Slick.Plugin<T> {
|
||||
public init(grid: Slick.Grid<T>): 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));
|
||||
.subscribe(this._grid.onSelectedRowsChanged, (e: Event, args: Slick.OnSelectedRowsChangedEventArgs<T>) => this.handleSelectedRowsChanged(e, args))
|
||||
.subscribe(this._grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs<T>) => this.handleClick(e, args))
|
||||
.subscribe(this._grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs<T>) => this.handleHeaderClick(e, args))
|
||||
.subscribe(this._grid.onKeyDown, (e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(e, args));
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
@@ -82,7 +83,7 @@ export class CheckboxSelectColumn<T> implements Slick.Plugin<T> {
|
||||
}
|
||||
|
||||
const selectedRows = this._grid.getSelectedRows();
|
||||
let lookup = {}, row, i;
|
||||
let lookup: dict.INumberDictionary<boolean> = {}, row: number, i: number;
|
||||
for (i = 0; i < selectedRows.length; i++) {
|
||||
row = selectedRows[i];
|
||||
lookup[row] = true;
|
||||
@@ -91,9 +92,7 @@ export class CheckboxSelectColumn<T> implements Slick.Plugin<T> {
|
||||
delete this._selectedRowsLookup[row];
|
||||
}
|
||||
}
|
||||
for (i in this._selectedRowsLookup) {
|
||||
this._grid.invalidateRow(i);
|
||||
}
|
||||
dict.forEach(this._selectedRowsLookup, (e) => this._grid.invalidateRow(e.key));
|
||||
this._selectedRowsLookup = lookup;
|
||||
this._grid.render();
|
||||
|
||||
@@ -231,11 +230,11 @@ export class CheckboxSelectColumn<T> implements Slick.Plugin<T> {
|
||||
sortable: false,
|
||||
cssClass: this._options.cssClass,
|
||||
headerCssClass: this._options.headerCssClass,
|
||||
formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc)
|
||||
formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc as T)
|
||||
};
|
||||
}
|
||||
|
||||
private checkboxSelectionFormatter(row, cell, value, columnDef: Slick.Column<T>, dataContext): string {
|
||||
private checkboxSelectionFormatter(row: number, cell: number, value: any, columnDef: Slick.Column<T>, dataContext: T): string {
|
||||
if (this.isCustomActionRequested()) {
|
||||
return this.checkboxTemplateCustom(row);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export class CopyKeybind<T> implements Slick.Plugin<T> {
|
||||
|
||||
public init(grid: Slick.Grid<T>) {
|
||||
this.grid = grid;
|
||||
this.handler.subscribe(this.grid.onKeyDown, (e, args) => this.handleKeyDown(e, args));
|
||||
this.handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(e, args));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
||||
@@ -1,46 +1,39 @@
|
||||
// Adopted and converted to typescript from https://github.com/danny-sg/slickgrid-spreadsheet-plugins/blob/master/ext.headerfilter.js
|
||||
// heavily modified
|
||||
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { IButtonStyles } from 'vs/base/browser/ui/button/button';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
import { Button } from 'sql/base/browser/ui/button/button';
|
||||
import { escape } from 'sql/base/common/strings';
|
||||
|
||||
export class HeaderFilter {
|
||||
interface IExtendedColumn<T> extends Slick.Column<T> {
|
||||
filterValues?: Array<string>;
|
||||
}
|
||||
|
||||
export class HeaderFilter<T extends Slick.SlickData> {
|
||||
|
||||
public onFilterApplied = new Slick.Event();
|
||||
public onCommand = new Slick.Event();
|
||||
|
||||
private grid: Slick.Grid<any>;
|
||||
private grid: Slick.Grid<T>;
|
||||
private handler = new Slick.EventHandler();
|
||||
private defaults = {
|
||||
filterImage: 'src/sql/media/icons/filter.svg',
|
||||
sortAscImage: 'sort-asc.gif',
|
||||
sortDescImage: 'sort-desc.gif'
|
||||
};
|
||||
|
||||
private $menu?: JQuery<HTMLElement>;
|
||||
private options: any;
|
||||
private okButton: Button;
|
||||
private clearButton: Button;
|
||||
private cancelButton: Button;
|
||||
private workingFilters: any;
|
||||
private columnDef: any;
|
||||
private workingFilters: Array<string>;
|
||||
private columnDef: IExtendedColumn<T>;
|
||||
private buttonStyles: IButtonStyles;
|
||||
|
||||
constructor(options: any) {
|
||||
this.options = mixin(options, this.defaults, false);
|
||||
}
|
||||
|
||||
public init(grid: Slick.Grid<any>): void {
|
||||
public init(grid: Slick.Grid<T>): void {
|
||||
this.grid = grid;
|
||||
this.handler.subscribe(this.grid.onHeaderCellRendered, (e, args) => this.handleHeaderCellRendered(e, args))
|
||||
.subscribe(this.grid.onBeforeHeaderCellDestroy, (e, args) => this.handleBeforeHeaderCellDestroy(e, args))
|
||||
.subscribe(this.grid.onClick, (e) => this.handleBodyMouseDown)
|
||||
this.handler.subscribe(this.grid.onHeaderCellRendered, (e: Event, args: Slick.OnHeaderCellRenderedEventArgs<T>) => this.handleHeaderCellRendered(e, args))
|
||||
.subscribe(this.grid.onBeforeHeaderCellDestroy, (e: Event, args: Slick.OnBeforeHeaderCellDestroyEventArgs<T>) => this.handleBeforeHeaderCellDestroy(e, args))
|
||||
.subscribe(this.grid.onClick, (e: MouseEvent) => this.handleBodyMouseDown(e))
|
||||
.subscribe(this.grid.onColumnsResized, () => this.columnsResized())
|
||||
.subscribe(this.grid.onKeyDown, (e) => this.handleKeyDown);
|
||||
.subscribe(this.grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e));
|
||||
this.grid.setColumns(this.grid.getColumns());
|
||||
|
||||
jQuery(document.body).bind('mousedown', this.handleBodyMouseDown);
|
||||
@@ -53,7 +46,7 @@ export class HeaderFilter {
|
||||
jQuery(document.body).unbind('keydown', this.handleKeyDown);
|
||||
}
|
||||
|
||||
private handleKeyDown = (e) => {
|
||||
private handleKeyDown(e: KeyboardEvent | JQuery.Event<HTMLElement, null>): void {
|
||||
if (this.$menu && (e.key === 'Escape' || e.keyCode === 27)) {
|
||||
this.hideMenu();
|
||||
e.preventDefault();
|
||||
@@ -61,8 +54,8 @@ export class HeaderFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private handleBodyMouseDown = (e) => {
|
||||
if (this.$menu && this.$menu[0] !== e.target && !jQuery.contains(this.$menu[0], e.target)) {
|
||||
private handleBodyMouseDown(e: MouseEvent | JQuery.Event<HTMLElement, null>): void {
|
||||
if (this.$menu && this.$menu[0] !== e.target && !jQuery.contains(this.$menu[0], e.target as Element)) {
|
||||
this.hideMenu();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -76,7 +69,7 @@ export class HeaderFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private handleHeaderCellRendered(e, args) {
|
||||
private handleHeaderCellRendered(e: Event, args: Slick.OnHeaderCellRenderedEventArgs<T>) {
|
||||
const column = args.column;
|
||||
if (column.id === '_detail_selector') {
|
||||
return;
|
||||
@@ -88,13 +81,13 @@ export class HeaderFilter {
|
||||
$el.bind('click', (e) => this.showFilter(e)).appendTo(args.node);
|
||||
}
|
||||
|
||||
private handleBeforeHeaderCellDestroy(e, args) {
|
||||
private handleBeforeHeaderCellDestroy(e: Event, args: Slick.OnBeforeHeaderCellDestroyEventArgs<T>) {
|
||||
jQuery(args.node)
|
||||
.find('.slick-header-menubutton')
|
||||
.remove();
|
||||
}
|
||||
|
||||
private addMenuItem(menu, columnDef, title, command, image) {
|
||||
private addMenuItem(menu: JQuery<HTMLElement>, columnDef: Slick.Column<T>, title: string, command: string) {
|
||||
const $item = jQuery('<div class="slick-header-menuitem">')
|
||||
.data('command', command)
|
||||
.data('column', columnDef)
|
||||
@@ -115,7 +108,7 @@ export class HeaderFilter {
|
||||
.appendTo($item);
|
||||
}
|
||||
|
||||
private addMenuInput(menu, columnDef) {
|
||||
private addMenuInput(menu: JQuery<HTMLElement>, columnDef: Slick.Column<T>) {
|
||||
const self = this;
|
||||
jQuery('<input class="input" placeholder="Search" style="margin-top: 5px; width: 206px">')
|
||||
.data('column', columnDef)
|
||||
@@ -126,7 +119,7 @@ export class HeaderFilter {
|
||||
.appendTo(menu);
|
||||
}
|
||||
|
||||
private updateFilterInputs(menu, columnDef, filterItems) {
|
||||
private updateFilterInputs(menu: JQuery<HTMLElement>, columnDef: IExtendedColumn<T>, filterItems: Array<string>) {
|
||||
let filterOptions = '<label><input type="checkbox" value="-1" />(Select All)</label>';
|
||||
columnDef.filterValues = columnDef.filterValues || [];
|
||||
|
||||
@@ -148,7 +141,7 @@ export class HeaderFilter {
|
||||
});
|
||||
}
|
||||
|
||||
private showFilter(e) {
|
||||
private showFilter(e: JQuery.Event<HTMLElement, null>) {
|
||||
const $menuButton = jQuery(e.target);
|
||||
this.columnDef = $menuButton.data('column');
|
||||
|
||||
@@ -157,15 +150,15 @@ export class HeaderFilter {
|
||||
// WorkingFilters is a copy of the filters to enable apply/cancel behaviour
|
||||
this.workingFilters = this.columnDef.filterValues.slice(0);
|
||||
|
||||
let filterItems;
|
||||
let filterItems: Array<string>;
|
||||
|
||||
if (this.workingFilters.length === 0) {
|
||||
// Filter based all available values
|
||||
filterItems = this.getFilterValues(this.grid.getData(), this.columnDef);
|
||||
filterItems = this.getFilterValues(this.grid.getData() as Slick.DataProvider<T>, this.columnDef);
|
||||
}
|
||||
else {
|
||||
// Filter based on current dataView subset
|
||||
filterItems = this.getAllFilterValues(this.grid.getData().getItems(), this.columnDef);
|
||||
filterItems = this.getAllFilterValues((this.grid.getData() as Slick.DataProvider<T>).getItems(), this.columnDef);
|
||||
}
|
||||
|
||||
if (!this.$menu) {
|
||||
@@ -174,8 +167,8 @@ export class HeaderFilter {
|
||||
|
||||
this.$menu.empty();
|
||||
|
||||
this.addMenuItem(this.$menu, this.columnDef, 'Sort Ascending', 'sort-asc', this.options.sortAscImage);
|
||||
this.addMenuItem(this.$menu, this.columnDef, 'Sort Descending', 'sort-desc', this.options.sortDescImage);
|
||||
this.addMenuItem(this.$menu, this.columnDef, 'Sort Ascending', 'sort-asc');
|
||||
this.addMenuItem(this.$menu, this.columnDef, 'Sort Descending', 'sort-desc');
|
||||
this.addMenuInput(this.$menu, this.columnDef);
|
||||
|
||||
let filterOptions = '<label><input type="checkbox" value="-1" />(Select All)</label>';
|
||||
@@ -209,7 +202,7 @@ export class HeaderFilter {
|
||||
this.clearButton.element.id = 'filter-clear-button';
|
||||
const clearElement = jQuery('#filter-clear-button');
|
||||
clearElement.bind('click', (ev) => {
|
||||
this.columnDef.filterValues.length = 0;
|
||||
this.columnDef.filterValues!.length = 0;
|
||||
this.setButtonImage($menuButton, false);
|
||||
this.handleApply(ev, this.columnDef);
|
||||
});
|
||||
@@ -265,11 +258,11 @@ export class HeaderFilter {
|
||||
this.hideMenu();
|
||||
}
|
||||
|
||||
private changeWorkingFilter(filterItems, workingFilters, $checkbox) {
|
||||
const value = $checkbox.val();
|
||||
private changeWorkingFilter(filterItems: Array<string>, workingFilters: Array<string>, $checkbox: JQuery<HTMLElement>) {
|
||||
const value = $checkbox.val() as number;
|
||||
const $filter = $checkbox.parent().parent();
|
||||
|
||||
if ($checkbox.val() < 0) {
|
||||
if ($checkbox.val() as number < 0) {
|
||||
// Select All
|
||||
if ($checkbox.prop('checked')) {
|
||||
jQuery(':checkbox', $filter).prop('checked', true);
|
||||
@@ -283,7 +276,7 @@ export class HeaderFilter {
|
||||
|
||||
if ($checkbox.prop('checked') && index < 0) {
|
||||
workingFilters.push(filterItems[value]);
|
||||
const nextRow = filterItems[(parseInt(value) + 1).toString()];
|
||||
const nextRow = filterItems[(parseInt(<string><any>value) + 1).toString()]; // for some reason parseInt is defined as only supporting strings even though it works fine for numbers
|
||||
if (nextRow && nextRow.indexOf('Error:') >= 0) {
|
||||
workingFilters.push(nextRow);
|
||||
}
|
||||
@@ -298,7 +291,7 @@ export class HeaderFilter {
|
||||
return workingFilters;
|
||||
}
|
||||
|
||||
private setButtonImage($el, filtered) {
|
||||
private setButtonImage($el: JQuery<HTMLElement>, filtered: boolean) {
|
||||
const element: HTMLElement = $el.get(0);
|
||||
if (filtered) {
|
||||
element.className += ' filtered';
|
||||
@@ -310,7 +303,7 @@ export class HeaderFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private handleApply(e, columnDef) {
|
||||
private handleApply(e: JQuery.Event<HTMLElement, null>, columnDef: Slick.Column<T>) {
|
||||
this.hideMenu();
|
||||
|
||||
this.onFilterApplied.notify({ 'grid': this.grid, 'column': columnDef }, e, self);
|
||||
@@ -318,10 +311,10 @@ export class HeaderFilter {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
private getFilterValues(dataView, column) {
|
||||
const seen: Array<any> = [];
|
||||
private getFilterValues(dataView: Slick.DataProvider<T>, column: Slick.Column<T>): Array<any> {
|
||||
const seen: Array<string> = [];
|
||||
for (let i = 0; i < dataView.getLength(); i++) {
|
||||
const value = dataView.getItem(i)[column.field];
|
||||
const value = dataView.getItem(i)[column.field!];
|
||||
|
||||
if (!_.contains(seen, value)) {
|
||||
seen.push(value);
|
||||
@@ -330,10 +323,10 @@ export class HeaderFilter {
|
||||
return seen;
|
||||
}
|
||||
|
||||
private getFilterValuesByInput($input) {
|
||||
private getFilterValuesByInput($input: JQuery<HTMLElement>): Array<string> {
|
||||
const column = $input.data('column'),
|
||||
filter = $input.val(),
|
||||
dataView = this.grid.getData(),
|
||||
filter = $input.val() as string,
|
||||
dataView = this.grid.getData() as Slick.DataProvider<T>,
|
||||
seen: Array<any> = [];
|
||||
|
||||
for (let i = 0; i < dataView.getLength(); i++) {
|
||||
@@ -357,10 +350,10 @@ export class HeaderFilter {
|
||||
return _.sortBy(seen, (v) => { return v; });
|
||||
}
|
||||
|
||||
private getAllFilterValues(data, column) {
|
||||
private getAllFilterValues(data: Array<Slick.SlickData>, column: Slick.Column<T>) {
|
||||
const seen: Array<any> = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const value = data[i][column.field];
|
||||
const value = data[i][column.field!];
|
||||
|
||||
if (!_.contains(seen, value)) {
|
||||
seen.push(value);
|
||||
@@ -370,7 +363,7 @@ export class HeaderFilter {
|
||||
return _.sortBy(seen, (v) => { return v; });
|
||||
}
|
||||
|
||||
private handleMenuItemClick(e, command, columnDef) {
|
||||
private handleMenuItemClick(e: JQuery.Event<HTMLElement, null>, command: string, columnDef: Slick.Column<T>) {
|
||||
this.hideMenu();
|
||||
|
||||
this.onCommand.notify({
|
||||
|
||||
@@ -4,44 +4,79 @@ import { escape } from 'sql/base/common/strings';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
export class RowDetailView {
|
||||
export interface IRowDetailViewOptions<T> {
|
||||
columnId?: string;
|
||||
cssClass?: string;
|
||||
toolTip?: string;
|
||||
width?: number;
|
||||
panelRows: number;
|
||||
useRowClick?: boolean;
|
||||
loadOnce?: boolean;
|
||||
preTemplate: (item: ExtendedItem<T>) => string;
|
||||
process: (item: ExtendedItem<T>) => void;
|
||||
postTemplate: (item: ExtendedItem<T>) => string;
|
||||
}
|
||||
|
||||
public onAsyncResponse = new Slick.Event<any>();
|
||||
public onAsyncEndUpdate = new Slick.Event<any>();
|
||||
public onAfterRowDetailToggle = new Slick.Event<any>();
|
||||
public onBeforeRowDetailToggle = new Slick.Event<any>();
|
||||
const defaultOptions = {
|
||||
columnId: '_detail_selector',
|
||||
toolTip: '',
|
||||
width: 30
|
||||
};
|
||||
|
||||
private _grid: any;
|
||||
private _expandedRows: any = [];
|
||||
export interface IExtendedItem<T extends Slick.SlickData> {
|
||||
_collapsed?: boolean;
|
||||
_parent?: IExtendedItem<T> & T;
|
||||
_detailContent?: string;
|
||||
_detailViewLoaded?: boolean;
|
||||
_sizePadding?: number;
|
||||
id?: string;
|
||||
_height?: number;
|
||||
_isPadding?: boolean;
|
||||
name?: string;
|
||||
_child?: IExtendedItem<T>;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export type ExtendedItem<T extends Slick.SlickData> = T & IExtendedItem<T>;
|
||||
|
||||
interface AugmentedDataView<T extends Slick.SlickData> extends Slick.Data.DataView<T> {
|
||||
getItem(row: number): ExtendedItem<T>;
|
||||
getItemByIdx(row: number): ExtendedItem<T>;
|
||||
}
|
||||
|
||||
export class RowDetailView<T extends Slick.SlickData> {
|
||||
|
||||
public readonly onAsyncResponse = new Slick.Event<{ itemDetail: ExtendedItem<T>, detailView: string }>();
|
||||
public readonly onAsyncEndUpdate = new Slick.Event<{ grid: Slick.Grid<T>, itemDetail: T }>();
|
||||
public readonly onAfterRowDetailToggle = new Slick.Event<{ grid: Slick.Grid<T>, item: T }>();
|
||||
public readonly onBeforeRowDetailToggle = new Slick.Event<{ grid: Slick.Grid<T>, item: T }>();
|
||||
|
||||
private _grid: Slick.Grid<T>;
|
||||
private _expandedRows: Array<ExtendedItem<T>> = [];
|
||||
private _handler = new Slick.EventHandler();
|
||||
private _defaults: any = {
|
||||
columnId: '_detail_selector',
|
||||
cssClass: null,
|
||||
toolTip: '',
|
||||
width: 30
|
||||
};
|
||||
|
||||
private _dataView: any;
|
||||
private _options: any;
|
||||
private _dataView: AugmentedDataView<T>;
|
||||
private _options: IRowDetailViewOptions<T>;
|
||||
|
||||
constructor(options) {
|
||||
this._options = mixin(options, this._defaults, false);
|
||||
constructor(options: IRowDetailViewOptions<T>) {
|
||||
this._options = options || Object.create(null);
|
||||
mixin(this._options, defaultOptions, false);
|
||||
}
|
||||
|
||||
public init(grid: any): void {
|
||||
public init(grid: Slick.Grid<T>): void {
|
||||
this._grid = grid;
|
||||
this._dataView = this._grid.getData();
|
||||
this._dataView = this._grid.getData() as AugmentedDataView<T>; // this is a bad assumption but the code is written with this assumption
|
||||
|
||||
// Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
|
||||
this._grid.getOptions().minRowBuffer = this._options.panelRows + 3;
|
||||
|
||||
this._handler
|
||||
.subscribe(this._grid.onClick, (e, args) => this.handleClick(e, args))
|
||||
.subscribe(this._grid.onSort, (e, args) => this.handleSort(e, args))
|
||||
.subscribe(this._grid.onScroll, (e, args) => this.handleScroll(e, args));
|
||||
.subscribe(this._grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs<T>) => this.handleClick(e, args))
|
||||
.subscribe(this._grid.onSort, () => this.handleSort())
|
||||
.subscribe(this._grid.onScroll, () => this.handleScroll());
|
||||
|
||||
this._grid.getData().onRowCountChanged.subscribe(() => { this._grid.updateRowCount(); this._grid.render(); });
|
||||
this._grid.getData().onRowsChanged.subscribe((e, a) => { this._grid.invalidateRows(a.rows); this._grid.render(); });
|
||||
this._dataView.onRowCountChanged.subscribe(() => { this._grid.updateRowCount(); this._grid.render(); });
|
||||
this._dataView.onRowsChanged.subscribe((e, a) => { this._grid.invalidateRows(a.rows); this._grid.render(); });
|
||||
|
||||
// subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished
|
||||
this.subscribeToOnAsyncResponse();
|
||||
@@ -55,17 +90,17 @@ export class RowDetailView {
|
||||
this.onBeforeRowDetailToggle.unsubscribe();
|
||||
}
|
||||
|
||||
public getOptions(options: any) {
|
||||
public getOptions() {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
public setOptions(options: any) {
|
||||
public setOptions(options: IRowDetailViewOptions<T>) {
|
||||
this._options = jQuery.extend(true, {}, this._options, options);
|
||||
}
|
||||
|
||||
public handleClick(e: any, args: any): void {
|
||||
public handleClick(e: MouseEvent, args: Slick.OnClickEventArgs<T>): void {
|
||||
// clicking on a row select checkbox
|
||||
if (this._options.useRowClick || this._grid.getColumns()[args.cell].id === this._options.columnId && jQuery(e.target).hasClass('detailView-toggle')) {
|
||||
if (this._options.useRowClick || this._grid.getColumns()[args.cell].id === this._options.columnId && jQuery(e.target!).hasClass('detailView-toggle')) {
|
||||
// if editing, try to commit
|
||||
if (this._grid.getEditorLock().isActive() && !this._grid.getEditorLock().commitCurrentEdit()) {
|
||||
e.preventDefault();
|
||||
@@ -95,12 +130,12 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
// Sort will just collapse all of the open items
|
||||
public handleSort(e, args) {
|
||||
public handleSort() {
|
||||
this.collapseAll();
|
||||
}
|
||||
|
||||
// If we scroll save detail views that go out of cache range
|
||||
public handleScroll(e, args) {
|
||||
public handleScroll() {
|
||||
|
||||
const range = this._grid.getRenderedRange();
|
||||
|
||||
@@ -136,10 +171,10 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
// Toggle between showing and hiding a row
|
||||
public toggleRowSelection(row) {
|
||||
this._grid.getData().beginUpdate();
|
||||
public toggleRowSelection(row: T) {
|
||||
this._dataView.beginUpdate();
|
||||
this.handleAccordionShowHide(row);
|
||||
this._grid.getData().endUpdate();
|
||||
this._dataView.endUpdate();
|
||||
}
|
||||
|
||||
// Collapse all of the open items
|
||||
@@ -150,7 +185,7 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
// Saves the current state of the detail view
|
||||
public saveDetailView(item) {
|
||||
public saveDetailView(item: ExtendedItem<T>) {
|
||||
const view = jQuery('#innerDetailView_' + item.id);
|
||||
if (view) {
|
||||
const html = jQuery('#innerDetailView_' + item.id).html();
|
||||
@@ -161,7 +196,7 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
// Colapse an Item so it is notlonger seen
|
||||
public collapseItem(item) {
|
||||
public collapseItem(item: ExtendedItem<T>) {
|
||||
|
||||
// Save the details on the collapse assuming onetime loading
|
||||
if (this._options.loadOnce) {
|
||||
@@ -169,11 +204,11 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
item._collapsed = true;
|
||||
for (let idx = 1; idx <= item._sizePadding; idx++) {
|
||||
for (let idx = 1; idx <= item._sizePadding!; idx++) {
|
||||
this._dataView.deleteItem(item.id + '.' + idx);
|
||||
}
|
||||
item._sizePadding = 0;
|
||||
this._dataView.updateItem(item.id, item);
|
||||
this._dataView.updateItem(item.id!, item);
|
||||
|
||||
// Remove the item from the expandedRows
|
||||
this._expandedRows = this._expandedRows.filter((r) => {
|
||||
@@ -182,7 +217,7 @@ export class RowDetailView {
|
||||
}
|
||||
|
||||
// Expand a row given the dataview item that is to be expanded
|
||||
public expandItem(item) {
|
||||
public expandItem(item: ExtendedItem<T>) {
|
||||
item._collapsed = false;
|
||||
this._expandedRows.push(item);
|
||||
|
||||
@@ -197,16 +232,16 @@ export class RowDetailView {
|
||||
} else {
|
||||
this.onAsyncResponse.notify({
|
||||
itemDetail: item,
|
||||
detailView: item._detailContent
|
||||
detailView: item._detailContent!
|
||||
}, undefined, this);
|
||||
this.applyTemplateNewLineHeight(item);
|
||||
this._dataView.updateItem(item.id, item);
|
||||
this._dataView.updateItem(item.id!, item);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.applyTemplateNewLineHeight(item);
|
||||
this._dataView.updateItem(item.id, item);
|
||||
this._dataView.updateItem(item.id!, item);
|
||||
|
||||
// async server call
|
||||
this._options.process(item);
|
||||
@@ -231,7 +266,7 @@ export class RowDetailView {
|
||||
|
||||
args.itemDetail._detailViewLoaded = true;
|
||||
|
||||
this._dataView.updateItem(args.itemDetail.id, args.itemDetail);
|
||||
this._dataView.updateItem(args.itemDetail.id!, args.itemDetail);
|
||||
|
||||
// trigger an event once the post template is finished loading
|
||||
this.onAsyncEndUpdate.notify({
|
||||
@@ -241,7 +276,7 @@ export class RowDetailView {
|
||||
});
|
||||
}
|
||||
|
||||
public handleAccordionShowHide(item) {
|
||||
public handleAccordionShowHide(item?: ExtendedItem<T>) {
|
||||
if (item) {
|
||||
if (!item._collapsed) {
|
||||
this.collapseItem(item);
|
||||
@@ -253,7 +288,7 @@ export class RowDetailView {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
public getPaddingItem(parent, offset) {
|
||||
public getPaddingItem(parent: ExtendedItem<T>, offset: number | string) {
|
||||
const item: any = {};
|
||||
|
||||
for (const prop in this._grid.getData()) {
|
||||
@@ -265,18 +300,16 @@ export class RowDetailView {
|
||||
item._collapsed = true;
|
||||
item._isPadding = true;
|
||||
item._parent = parent;
|
||||
item._offset = offset;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public getErrorItem(parent, offset) {
|
||||
const item: any = {};
|
||||
public getErrorItem(parent: ExtendedItem<T>, offset: number | string) {
|
||||
const item: ExtendedItem<T> = Object.create(null);
|
||||
item.id = parent.id + '.' + offset;
|
||||
item._collapsed = true;
|
||||
item._isPadding = false;
|
||||
item._parent = parent;
|
||||
item._offset = offset;
|
||||
item.name = parent.message ? parent.message : nls.localize('rowDetailView.loadError', 'Loading Error...');
|
||||
parent._child = item;
|
||||
return item;
|
||||
@@ -285,17 +318,17 @@ export class RowDetailView {
|
||||
//////////////////////////////////////////////////////////////
|
||||
//create the detail ctr node. this belongs to the dev & can be custom-styled as per
|
||||
//////////////////////////////////////////////////////////////
|
||||
public applyTemplateNewLineHeight(item, showError = false) {
|
||||
public applyTemplateNewLineHeight(item: ExtendedItem<T>, showError = false) {
|
||||
// the height seems to be calculated by the template row count (how many line of items does the template have)
|
||||
const rowCount = this._options.panelRows;
|
||||
|
||||
//calculate padding requirements based on detail-content..
|
||||
//ie. worst-case: create an invisible dom node now &find it's height.
|
||||
const lineHeight = 13; //we know cuz we wrote the custom css innit ;)
|
||||
item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / this._grid.getOptions().rowHeight);
|
||||
item._height = (item._sizePadding * this._grid.getOptions().rowHeight);
|
||||
item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / this._grid.getOptions().rowHeight!);
|
||||
item._height = (item._sizePadding * this._grid.getOptions().rowHeight!);
|
||||
|
||||
const idxParent = this._dataView.getIdxById(item.id);
|
||||
const idxParent = this._dataView.getIdxById(item.id!);
|
||||
for (let idx = 1; idx <= item._sizePadding; idx++) {
|
||||
if (showError) {
|
||||
this._dataView.insertItem(idxParent + idx, this.getErrorItem(item, 'error'));
|
||||
@@ -305,7 +338,7 @@ export class RowDetailView {
|
||||
}
|
||||
}
|
||||
|
||||
public getColumnDefinition() {
|
||||
public getColumnDefinition(): Slick.Column<T> {
|
||||
return {
|
||||
id: this._options.columnId,
|
||||
name: '',
|
||||
@@ -315,11 +348,11 @@ export class RowDetailView {
|
||||
resizable: false,
|
||||
sortable: false,
|
||||
cssClass: this._options.cssClass,
|
||||
formatter: (row, cell, value, columnDef, dataContext) => this.detailSelectionFormatter(row, cell, value, columnDef, dataContext)
|
||||
formatter: (row, cell, value, columnDef, dataContext) => this.detailSelectionFormatter(row, cell, value, columnDef, dataContext as ExtendedItem<T>)
|
||||
};
|
||||
}
|
||||
|
||||
public detailSelectionFormatter(row, cell, value, columnDef, dataContext) {
|
||||
public detailSelectionFormatter(row: number, cell: number, value: any, columnDef: Slick.Column<T>, dataContext: ExtendedItem<T>): string | undefined {
|
||||
|
||||
if (dataContext._collapsed === undefined) {
|
||||
dataContext._collapsed = true;
|
||||
@@ -327,7 +360,6 @@ export class RowDetailView {
|
||||
dataContext._height = 0; //the actual height in pixels of the detail field
|
||||
dataContext._isPadding = false;
|
||||
dataContext._parent = undefined;
|
||||
dataContext._offset = 0;
|
||||
}
|
||||
|
||||
if (dataContext._isPadding === true) {
|
||||
@@ -336,7 +368,7 @@ export class RowDetailView {
|
||||
return '<div class=\'detailView-toggle expand\'></div>';
|
||||
} else {
|
||||
const html: Array<string> = [];
|
||||
const rowHeight = this._grid.getOptions().rowHeight;
|
||||
const rowHeight = this._grid.getOptions().rowHeight!;
|
||||
const bottomMargin = 5;
|
||||
|
||||
//V313HAX:
|
||||
@@ -353,59 +385,12 @@ export class RowDetailView {
|
||||
html.push(`<div id='cellDetailView_${dataContext.id}' class='dynamic-cell-detail' `); //apply custom css to detail
|
||||
html.push(`style=\'height:${dataContext._height}px;`); //set total height of padding
|
||||
html.push(`top:${rowHeight}px'>`); //shift detail below 1st row
|
||||
html.push(`<div id='detailViewContainer_${dataContext.id}"' class='detail-container' style='max-height:${(dataContext._height - rowHeight + bottomMargin)}px'>`); //sub ctr for custom styling
|
||||
html.push(`<div id='innerDetailView_${dataContext.id}'>${escape(dataContext._detailContent)}</div></div>`);
|
||||
html.push(`<div id='detailViewContainer_${dataContext.id}"' class='detail-container' style='max-height:${(dataContext._height! - rowHeight + bottomMargin)}px'>`); //sub ctr for custom styling
|
||||
html.push(`<div id='innerDetailView_${dataContext.id}'>${escape(dataContext._detailContent!)}</div></div>`);
|
||||
//&omit a final closing detail container </div> that would come next
|
||||
|
||||
return html.join('');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public resizeDetailView(item) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grad each of the dom items
|
||||
const mainContainer = document.getElementById('detailViewContainer_' + item.id);
|
||||
const cellItem = document.getElementById('cellDetailView_' + item.id);
|
||||
const inner = document.getElementById('innerDetailView_' + item.id);
|
||||
|
||||
if (!mainContainer || !cellItem || !inner) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let idx = 1; idx <= item._sizePadding; idx++) {
|
||||
this._dataView.deleteItem(item.id + '.' + idx);
|
||||
}
|
||||
|
||||
const rowHeight = this._grid.getOptions().rowHeight; // height of a row
|
||||
const lineHeight = 13; //we know cuz we wrote the custom css innit ;)
|
||||
|
||||
// Get the inner Item height as this will be the actual size
|
||||
const itemHeight = inner.clientHeight;
|
||||
|
||||
// Now work out how many rows
|
||||
const rowCount = Math.ceil(itemHeight / rowHeight) + 1;
|
||||
|
||||
item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / rowHeight);
|
||||
item._height = (item._sizePadding * rowHeight);
|
||||
|
||||
// If the padding is now more than the original minRowBuff we need to increase it
|
||||
if (this._grid.getOptions().minRowBuffer < item._sizePadding) {
|
||||
// Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
|
||||
this._grid.getOptions().minRowBuffer = item._sizePadding + 3;
|
||||
}
|
||||
|
||||
mainContainer.setAttribute('style', `max-height: ${item._height}px`);
|
||||
if (cellItem) {
|
||||
cellItem.setAttribute('style', `height: ${item._height}px;top:${rowHeight}px`);
|
||||
}
|
||||
|
||||
const idxParent = this._dataView.getIdxById(item.id);
|
||||
for (let idx = 1; idx <= item._sizePadding; idx++) {
|
||||
this._dataView.insertItem(idxParent + idx, this.getPaddingItem(item, idx));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ export class RowNumberColumn<T> implements Slick.Plugin<T> {
|
||||
public init(grid: Slick.Grid<T>) {
|
||||
this.grid = grid;
|
||||
this.handler
|
||||
.subscribe(this.grid.onClick, (e, args) => this.handleClick(e, args))
|
||||
.subscribe(this.grid.onHeaderClick, (e, args) => this.handleHeaderClick(e, args));
|
||||
.subscribe(this.grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs<T>) => this.handleClick(e, args))
|
||||
.subscribe(this.grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs<T>) => this.handleHeaderClick(e, args));
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
@@ -56,11 +56,11 @@ export class RowNumberColumn<T> implements Slick.Plugin<T> {
|
||||
cssClass: this.options.cssClass,
|
||||
focusable: false,
|
||||
selectable: false,
|
||||
formatter: (r, c, v, cd, dc) => this.formatter(r, c, v, cd, dc)
|
||||
formatter: r => this.formatter(r)
|
||||
};
|
||||
}
|
||||
|
||||
private formatter(row, cell, value, columnDef: Slick.Column<T>, dataContext): string {
|
||||
private formatter(row: number): string {
|
||||
// row is zero-based, we need make it 1 based for display in the result grid
|
||||
return `<span>${row + 1}</span>`;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ export class RowSelectionModel<T extends Slick.SlickData> implements Slick.Selec
|
||||
public init(grid: Slick.Grid<T>) {
|
||||
this._grid = grid;
|
||||
this._handler
|
||||
.subscribe(this._grid.onActiveCellChanged, (e, data) => this.handleActiveCellChange(e, data))
|
||||
.subscribe(this._grid.onKeyDown, e => this.handleKeyDown(e))
|
||||
.subscribe(this._grid.onClick, e => this.handleClick(e));
|
||||
.subscribe(this._grid.onActiveCellChanged, (e: Event, data: Slick.OnActiveCellChangedEventArgs<T>) => this.handleActiveCellChange(e, data))
|
||||
.subscribe(this._grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e))
|
||||
.subscribe(this._grid.onClick, (e: MouseEvent) => this.handleClick(e));
|
||||
}
|
||||
|
||||
private rangesToRows(ranges: Slick.Range[]): number[] {
|
||||
@@ -116,7 +116,7 @@ export class RowSelectionModel<T extends Slick.SlickData> implements Slick.Selec
|
||||
}
|
||||
}
|
||||
|
||||
private handleClick(e: KeyboardEvent): boolean {
|
||||
private handleClick(e: MouseEvent): boolean {
|
||||
const cell = this._grid.getCellFromEvent(e);
|
||||
if (!cell || !this._grid.canCellBeActive(cell.row, cell.cell)) {
|
||||
return false;
|
||||
|
||||
@@ -117,6 +117,10 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
|
||||
return this._data[index];
|
||||
}
|
||||
|
||||
getItems(): T[] {
|
||||
return this._data.slice();
|
||||
}
|
||||
|
||||
getLengthNonFiltered(): number {
|
||||
return this.filterEnabled ? this._allData.length : this._data.length;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user