common-ui/src/lib/directives/sync-width.directive.ts
2023-03-19 12:01:43 +02:00

85 lines
2.7 KiB
TypeScript

import { Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
@Directive({
selector: '[iqserSyncWidth]',
standalone: true,
})
export class SyncWidthDirective implements OnDestroy {
@Input() iqserSyncWidth!: string;
readonly #interval: number;
constructor(private readonly _elementRef: ElementRef) {
this.#interval = window.setInterval(() => {
this.#matchWidth();
}, 1000);
}
ngOnDestroy() {
window.clearInterval(this.#interval);
}
@HostListener('window:resize')
onResize() {
this.#matchWidth();
}
#matchWidth() {
const headerItems = (this._elementRef.nativeElement as HTMLElement).children;
const tableRows = (this._elementRef.nativeElement as HTMLElement).parentElement?.parentElement?.getElementsByClassName(
this.iqserSyncWidth,
);
if (!tableRows || !tableRows.length) {
return;
}
(this._elementRef.nativeElement as HTMLElement).setAttribute('synced', 'true');
const { columns, length } = this.#sampleRow(tableRows);
if (!columns) {
return;
}
const hasExtraColumns = headerItems.length !== length ? 1 : 0;
for (let idx = 0; idx < length - hasExtraColumns - 1; idx += 1) {
const item = headerItems[idx] as HTMLElement;
if (item) {
item.style.width = `${columns[idx].getBoundingClientRect().width}px`;
item.style.minWidth = `${columns[idx].getBoundingClientRect().width}px`;
}
}
for (let idx = length - hasExtraColumns - 1; idx < headerItems.length; idx += 1) {
const item = headerItems[idx] as HTMLElement;
if (item) {
item.style.minWidth = '0';
}
}
}
#sampleRow(tableRows: HTMLCollectionOf<Element>): {
columns?: Element[];
length: number;
} {
let length = 0;
let columns: Element[] | undefined;
for (let idx = 0; idx < tableRows.length; idx += 1) {
const row = tableRows.item(idx);
const selectionColumns = Array.from(row?.getElementsByClassName('selection-column') || []);
const cells = Array.from(row?.getElementsByClassName('cell') || []);
const scrollbarPlaceholders = Array.from(row?.getElementsByClassName('scrollbar-placeholder') || []);
const rowColumns = [...selectionColumns, ...cells, ...scrollbarPlaceholders];
if (row && rowColumns && rowColumns.length > length) {
length = rowColumns.length;
columns = rowColumns;
}
}
return { columns, length };
}
}