import {
Component, Output, EventEmitter, Input, HostBinding, ChangeDetectorRef, ChangeDetectionStrategy
} from '@angular/core';
import { SortType, SelectionType } from '../../types';
import { columnsByPin, columnGroupWidths, columnsByPinArr, translateXY } from '../../utils';
import { DataTableColumnDirective } from '../columns';
import { MouseEvent } from '../../events';
@Component({
selector: 'datatable-header',
template: `
`,
host: {
class: 'datatable-header'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DataTableHeaderComponent {
@Input() sortAscendingIcon: any;
@Input() sortDescendingIcon: any;
@Input() scrollbarH: boolean;
@Input() dealsWithGroup: boolean;
@Input() targetMarkerTemplate: any;
targetMarkerContext: any;
@Input() set innerWidth(val: number) {
this._innerWidth = val;
if (this._columns) {
const colByPin = columnsByPin(this._columns);
this._columnGroupWidths = columnGroupWidths(colByPin, this._columns);
this.setStylesByGroup();
}
}
get innerWidth(): number {
return this._innerWidth;
}
@Input() sorts: any[];
@Input() sortType: SortType;
@Input() allRowsSelected: boolean;
@Input() selectionType: SelectionType;
@Input() reorderable: boolean;
dragEventTarget: any;
@HostBinding('style.height')
@Input() set headerHeight(val: any) {
if (val !== 'auto') {
this._headerHeight = `${val}px`;
} else {
this._headerHeight = val;
}
}
get headerHeight(): any {
return this._headerHeight;
}
@Input() set columns(val: any[]) {
this._columns = val;
const colsByPin = columnsByPin(val);
this._columnsByPin = columnsByPinArr(val);
this._columnGroupWidths = columnGroupWidths(colsByPin, val);
this.setStylesByGroup();
}
get columns(): any[] {
return this._columns;
}
@Input()
set offsetX(val: number) {
this._offsetX = val;
this.setStylesByGroup();
}
get offsetX() { return this._offsetX; }
@Output() sort: EventEmitter = new EventEmitter();
@Output() reorder: EventEmitter = new EventEmitter();
@Output() resize: EventEmitter = new EventEmitter();
@Output() select: EventEmitter = new EventEmitter();
@Output() columnContextmenu = new EventEmitter<{ event: MouseEvent, column: any }>(false);
_columnsByPin: any;
_columnGroupWidths: any;
_innerWidth: number;
_offsetX: number;
_columns: any[];
_headerHeight: string;
_styleByGroup = {
left: {},
center: {},
right: {}
};
constructor(private cd: ChangeDetectorRef) { }
onLongPressStart({ event, model }: { event: any, model: any }) {
model.dragging = true;
this.dragEventTarget = event;
}
onLongPressEnd({ event, model }: { event: any, model: any }) {
this.dragEventTarget = event;
// delay resetting so sort can be
// prevented if we were dragging
setTimeout(() => {
// datatable component creates copies from columns on reorder
// set dragging to false on new objects
const column = this._columns.find(c => c.$$id === model.$$id);
if (column) {
column.dragging = false;
}
}, 5);
}
@HostBinding('style.width')
get headerWidth(): string {
if (this.scrollbarH) {
return this.innerWidth + 'px';
}
return '100%';
}
trackByGroups(index: number, colGroup: any): any {
return colGroup.type;
}
columnTrackingFn(index: number, column: any): any {
return column.$$id;
}
onColumnResized(width: number, column: DataTableColumnDirective): void {
if (width <= column.minWidth) {
width = column.minWidth;
} else if (width >= column.maxWidth) {
width = column.maxWidth;
}
this.resize.emit({
column,
prevValue: column.width,
newValue: width
});
}
onColumnReordered({ prevIndex, newIndex, model }: any): void {
const column = this.getColumn(newIndex);
column.isTarget = false;
column.targetMarkerContext = undefined;
this.reorder.emit({
column: model,
prevValue: prevIndex,
newValue: newIndex
});
}
onTargetChanged({ prevIndex, newIndex, initialIndex }: any): void {
if (prevIndex || prevIndex === 0) {
const oldColumn = this.getColumn(prevIndex);
oldColumn.isTarget = false;
oldColumn.targetMarkerContext = undefined;
}
if (newIndex || newIndex === 0) {
const newColumn = this.getColumn(newIndex);
newColumn.isTarget = true;
if (initialIndex !== newIndex) {
newColumn.targetMarkerContext = {class: 'targetMarker '.concat(
initialIndex > newIndex ? 'dragFromRight' : 'dragFromLeft')};
}
}
}
getColumn(index: number): any {
const leftColumnCount = this._columnsByPin[0].columns.length;
if (index < leftColumnCount) {
return this._columnsByPin[0].columns[index];
}
const centerColumnCount = this._columnsByPin[1].columns.length;
if (index < leftColumnCount + centerColumnCount) {
return this._columnsByPin[1].columns[index - leftColumnCount];
}
return this._columnsByPin[2].columns[index - leftColumnCount - centerColumnCount];
}
onSort({ column, prevValue, newValue }: any): void {
// if we are dragging don't sort!
if (column.dragging) return;
const sorts = this.calcNewSorts(column, prevValue, newValue);
this.sort.emit({
sorts,
column,
prevValue,
newValue
});
}
calcNewSorts(column: any, prevValue: number, newValue: number): any[] {
let idx = 0;
if (!this.sorts) {
this.sorts = [];
}
const sorts = this.sorts.map((s, i) => {
s = { ...s };
if (s.prop === column.prop) idx = i;
return s;
});
if (newValue === undefined) {
sorts.splice(idx, 1);
} else if (prevValue) {
sorts[idx].dir = newValue;
} else {
if (this.sortType === SortType.single) {
sorts.splice(0, this.sorts.length);
}
sorts.push({ dir: newValue, prop: column.prop });
}
return sorts;
}
setStylesByGroup() {
this._styleByGroup['left'] = this.calcStylesByGroup('left');
this._styleByGroup['center'] = this.calcStylesByGroup('center');
this._styleByGroup['right'] = this.calcStylesByGroup('right');
this.cd.detectChanges();
}
calcStylesByGroup(group: string): any {
const widths = this._columnGroupWidths;
const offsetX = this.offsetX;
const styles = {
width: `${widths[group]}px`
};
if (group === 'center') {
translateXY(styles, offsetX * -1, 0);
} else if (group === 'right') {
const totalDiff = widths.total - this.innerWidth;
const offset = totalDiff * -1;
translateXY(styles, offset, 0);
}
return styles;
}
}