gp-crm-ui
Version:
Модуль компонентов UI Имя модуля: `gp-crm-ui`
215 lines (174 loc) • 6.15 kB
text/typescript
import {
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
// Сенсор
import { ResizeSensor } from 'css-element-queries';
// Интерфейсы
import {
IColumn,
IRowCache,
ISize,
ITableOptions
} from '../../interfaces';
// Контент таблицы
export class CrmTableContentComponent
implements OnChanges, OnInit, OnDestroy {
// Строки
public rows: any[];
// Конфигурация таблицы
public options: ITableOptions;
// Закрепленные столбцы
public pinnedColumns: IColumn[];
// Ширина области контента закрепленных столбцов
public pinnedCanvasWidth: number;
// Обычные столбцы
public defaultColumns: IColumn[];
// Ширина области контента обычных столбцов
public defaultCanvasWidth: number;
// Смещение области контента в области отображения
public offsetLeft: number;
// Смещение области контента в области отображения
public offsetTop: number;
// Событие изменения размера defaultView
public resizedView = new EventEmitter<ISize>();
// Событие изменения размера defaultCanvas
public resizedCanvas = new EventEmitter<ISize>();
// Ссылка на область отображения закрепленных столбцов
public pinnedView: ElementRef;
// Ссылка на область отображения обычных столбцов
public defaultView: ElementRef;
// Ссылка на область контента обычных столбцов
public defaultCanvas: ElementRef;
// Сенсор изменения размера defaultView
private resizeSensorView: any;
// Сенсор изменения размера defaultCanvas
private resizeSensorCanvas: any;
// Высота строки по умолчанию
private readonly DEFAULT_ROW_HEIGHT: number = 32;
private get defaultRowHeight(): number {
return (this.options && this.options.defaultRowHeight) || this.DEFAULT_ROW_HEIGHT;
}
// Кеш высот строк
private readonly _rowsCache: WeakMap<object, IRowCache> = new WeakMap<object, IRowCache>();
public readonly rowsCache: WeakMap<object, number> = new WeakMap<object, number>();
// Событие изменения высоты ячейки
public readonly emitterChangeHeight: EventEmitter<any> = new EventEmitter<any>();
// --------------------------------------------------------------------------
// Обновить смещения
private updateOffset(): void {
const defaultView = this.defaultView && this.defaultView.nativeElement;
const pinnedView = this.pinnedView && this.pinnedView.nativeElement;
if (defaultView) {
defaultView.scrollLeft = this.offsetLeft;
defaultView.scrollTop = this.offsetTop;
}
if (pinnedView) {
pinnedView.scrollTop = this.offsetTop;
}
}
// Обновить кеш строк
private updateRowsCache(): void {
const rows = this.rows || [];
rows.forEach((row: any): void => {
if (!this.rowsCache.has(row)) {
this.rowsCache.set(row, this.defaultRowHeight);
}
});
}
// Расчет высоты строки
private calcRowHeight(row: any): void {
const rowCache = this._rowsCache.get(row);
if (rowCache) {
const heightCells = Object.keys(rowCache)
.map((key: string): number => rowCache[key].height);
const height = Math.max(...heightCells);
this.rowsCache.set(row, height);
}
}
// Обработчик изменения размера ячейки
private onChangeHeight(event: any): void {
const row = event.row;
const field = event.column.field;
const height = event.height || this.defaultRowHeight;
if (!this._rowsCache.has(row)) {
this._rowsCache.set(row, {});
}
const rowCache = this._rowsCache.get(row);
rowCache[field] = { field, height };
this.calcRowHeight(row);
}
// Обработчик изменения размера defaultView
public onResizedView(): void {
const el = this.defaultView.nativeElement;
this.resizedView.emit({
width: el.offsetWidth,
height: el.offsetHeight
});
}
// Обработчик изменения размера defaultCanvas
public onResizedCanvas(): void {
const el = this.defaultCanvas.nativeElement;
this.resizedCanvas.emit({
width: el.offsetWidth,
height: el.offsetHeight
});
}
// Добавить сенсоры
private addSensors(): void {
this.resizeSensorView = new ResizeSensor(
this.defaultView.nativeElement,
this.onResizedView.bind(this)
);
this.resizeSensorCanvas = new ResizeSensor(
this.defaultCanvas.nativeElement,
this.onResizedCanvas.bind(this)
);
}
// Удалить сенсоры
private removeSensors(): void {
if (this.resizeSensorView) { this.resizeSensorView.detach(); }
if (this.resizeSensorCanvas) { this.resizeSensorCanvas.detach(); }
}
// --------------------------------------------------------------------------
// HOOKS
// Инициализация
public ngOnInit(): void {
this.emitterChangeHeight.subscribe({
next: this.onChangeHeight.bind(this)
});
// Добавить сенсоры
this.addSensors();
// Пропуск кадра
setTimeout((): void => {
this.onResizedView();
this.onResizedCanvas();
});
}
// Уничтожение
public ngOnDestroy(): void {
this.removeSensors();
}
// Изменение входных параметров
public ngOnChanges(changes: SimpleChanges): void {
if (changes.offsetLeft || changes.offsetTop) {
this.updateOffset();
}
if (changes.rows) {
this.updateRowsCache();
}
}
}