import { DOCUMENT } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Inject,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
} from '@angular/core';
import { ActivationEnd, ActivationStart, Event, Router } from '@angular/router';
import { InputBoolean, InputNumber } from '@delon/util';
import { fromEvent, Subscription } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators';
import { FullContentService } from './full-content.service';
const wrapCls = `full-content__body`;
const openedCls = `full-content__opened`;
const hideTitleCls = `full-content__hidden-title`;
@Component({
selector: 'full-content',
exportAs: 'fullContent',
template: `
`,
host: {
'[class.full-content]': 'true',
'[style.height.px]': '_height',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FullContentComponent implements AfterViewInit, OnInit, OnChanges, OnDestroy {
private bodyEl: HTMLElement;
private inited = false;
private srv$: Subscription;
private route$: Subscription;
private id = `_full-content-${Math.random()
.toString(36)
.substring(2)}`;
private scroll$: Subscription | null = null;
_height = 0;
// #region fields
@Input() @InputBoolean() fullscreen: boolean;
@Input() @InputBoolean() hideTitle = true;
@Input() @InputNumber() padding = 24;
@Output() readonly fullscreenChange = new EventEmitter();
// #endregion
constructor(
private el: ElementRef,
private cdr: ChangeDetectorRef,
private srv: FullContentService,
private router: Router,
@Inject(DOCUMENT) private doc: any,
) {}
private updateCls() {
const clss = this.bodyEl.classList;
if (this.fullscreen) {
clss.add(openedCls);
if (this.hideTitle) {
clss.add(hideTitleCls);
}
} else {
clss.remove(openedCls);
if (this.hideTitle) {
clss.remove(hideTitleCls);
}
}
}
private update() {
this.updateCls();
this.updateHeight();
this.fullscreenChange.emit(this.fullscreen);
}
private updateHeight() {
this._height =
this.bodyEl.getBoundingClientRect().height -
(this.el.nativeElement as HTMLElement).getBoundingClientRect().top -
this.padding;
this.cdr.detectChanges();
}
private removeInBody() {
this.bodyEl.classList.remove(wrapCls, openedCls, hideTitleCls);
}
ngOnInit(): void {
this.inited = true;
this.bodyEl = this.doc.querySelector('body');
this.bodyEl.classList.add(wrapCls);
(this.el.nativeElement as HTMLElement).id = this.id;
this.updateCls();
// when window resize
this.scroll$ = fromEvent(window, 'resize')
.pipe(debounceTime(200))
.subscribe(() => this.updateHeight());
// when servier changed
this.srv$ = this.srv.change.pipe(filter(res => res !== null)).subscribe(() => this.toggle());
// when router changed
this.route$ = this.router.events
.pipe(
filter((e: Event) => e instanceof ActivationStart || e instanceof ActivationEnd),
debounceTime(200),
)
.subscribe(() => {
if (!!this.doc.querySelector('#' + this.id)) {
this.bodyEl.classList.add(wrapCls);
this.updateCls();
} else {
this.removeInBody();
}
});
}
toggle() {
this.fullscreen = !this.fullscreen;
this.update();
this.updateHeight();
}
ngAfterViewInit() {
setTimeout(() => this.updateHeight());
}
ngOnChanges(): void {
if (this.inited) this.update();
}
ngOnDestroy(): void {
this.removeInBody();
this.scroll$!.unsubscribe();
this.srv$.unsubscribe();
this.route$.unsubscribe();
}
}