xenos
Version:
Xenos is a data grid built upon angular2 and bootstrap.
231 lines (184 loc) • 6.79 kB
text/typescript
import { Component, ElementRef, Input, Renderer, ViewChild, AfterViewInit } from "@angular/core";
import { ViewSource, ItemsPreview } from "./view-source";
import { CellDirective } from "./cell.directive";
import { HeaderDirective } from "./header.directive";
import { CandidateDirective } from "./candidate.directive";
import { DataGridColumn } from "./data-grid-column";
import { SortDescriptor } from "./sort-descriptor";
import { ColumnSortDescriptor } from "./column-sort-descriptor";
import { FilterDescriptor } from "./filter-descriptor";
import { FtsFilterDescriptor } from "./fts-filter-descriptor";
import { I18nService } from "./i18n.service";
import { I18n } from "./i18n";
import { I18nDirective } from "./i18n.directive";
import { IdGenerator } from "./id-generator";
import { ObservableArray } from "./observable-array";
import { Observable } from "rxjs/Observable";
// Some IDE's won't recognize the module node. I'm looking at you VS2015 ...
declare var module: { id: any }
export class DataGrid implements AfterViewInit {
private itemsPresenter: any[] = [];
private viewSource: ViewSource;
private pagingRangeInternal: number[] = [];
private columnsInternal: ObservableArray<DataGridColumn>;
private deferRefreshInternal: boolean = false;
private lastSnapShotInternal: ItemsPreview;
constructor(
private renderer: Renderer,
private elementRef: ElementRef,
private i18nService: I18nService) {
this.viewSource = new ViewSource();
this.viewSource.itemsViewChanging
.subscribe(x => this.lastSnapShotInternal = x);
this.viewSource.itemsViewChanged
.subscribe(x => this.onItemsViewChanged(x));
this.viewSource.filterDescriptors.itemsChanged.subscribe(x => {
this.autoRefresh();
});
this.viewSource.sortDescriptors.itemsChanged.subscribe(x => {
this.autoRefresh();
});
this.columnsInternal = new ObservableArray<DataGridColumn>();
this.columnsInternal.itemsChanged.subscribe(x => {
x.itemsRemoved.forEach(x => x.dataGrid = undefined);
x.itemsAdded.forEach(x => {
x.dataGrid = this;
if (x.initialSortDirection) {
x.sortDirection = x.initialSortDirection;
}
});
});
}
private table: ElementRef;
public set pageSize(value: number) {
this.viewSource.pageSize = value;
this.autoRefresh();
}
public set searchPhrase(phrase: string) {
let index = this.filterDescriptors.findIndex(x => x.id === FtsFilterDescriptor.id);
if (~index) {
this.filterDescriptors.splice(index, 1);
}
if (!phrase) {
return;
}
this.filterDescriptors.push(new FtsFilterDescriptor(this.columns, phrase));
}
public get itemsViewChanging(): Observable<ItemsPreview> {
return this.viewSource.itemsViewChanging;
}
public get itemsViewChanged(): Observable<any[]> {
return this.viewSource.itemsViewChanged;
}
public get i18n(): I18n {
return this.i18nService;
}
public get columns(): ObservableArray<DataGridColumn> {
return this.columnsInternal;
}
public get working(): boolean {
return this.viewSource.working;
}
public get filterDescriptors(): FilterDescriptor[] {
return this.viewSource.filterDescriptors;
}
public get sortDescriptors(): SortDescriptor[] {
return this.viewSource.sortDescriptors;
}
public get pageCount(): number {
return this.viewSource.pageCount;
}
public get pageIndex(): number {
return this.viewSource.pageIndex;
}
public set pageIndex(value: number) {
this.viewSource.pageIndex = value;
this.autoRefresh();
}
public get pageSize(): number {
return this.viewSource.pageSize;
}
public set itemsSource(source: any[]) {
this.viewSource.itemsSource = source;
this.autoRefresh();
}
public get lastSnapShot(): ItemsPreview {
if (!this.lastSnapShotInternal) {
return undefined;
}
return this.lastSnapShotInternal;
}
public get itemsSource(): any[] {
return this.viewSource.itemsSource;
}
private get items(): any[] {
return this.itemsPresenter;
}
public deferRefresh(): void {
this.deferRefreshInternal = true;
}
public refresh(): void {
this.viewSource.refresh();
this.deferRefreshInternal = false;
}
private autoRefresh(): void {
if (this.deferRefreshInternal) return;
this.viewSource.refresh();
}
private onItemsViewChanged(items: any[]): void {
this.itemsPresenter.splice(0);
items.forEach(x => this.itemsPresenter.push(x));
}
private onHeaderClicked(event: MouseEvent, column: DataGridColumn): void {
event.stopPropagation();
event.preventDefault();
if (column.disableSorting) {
return;
}
this.deferRefresh();
if (!event.ctrlKey) {
this.columns.forEach(x => {
if (x.id === column.id) return;
x.sortDirection = undefined;
});
}
column.cycleSortDirections();
this.refresh();
}
private onPageChanged(event: Event, i: number) {
event.preventDefault();
this.viewSource.pageIndex = i;
this.autoRefresh();
}
private get pagingRange(): number[] {
this.pagingRangeInternal.splice(0);
let start: number = this.pageIndex - 4;
let end: number = this.pageIndex + 5;
if (start < 0) {
let s = Math.abs(start);
start += s;
end = Math.min(end + Math.abs(s), this.pageCount);
}
if (end > this.pageCount) {
let e = end;
end = end + (this.pageCount - e);
start = Math.max(start + (this.pageCount - e), 0);
}
for (let i = start; i < end; i++) {
this.pagingRangeInternal.push(i);
}
return this.pagingRangeInternal;
}
// Implementation of AfterViewInit
public ngAfterViewInit(): void {
// Nada ...
}
}