@rdkmaster/jigsaw-labs
Version:
Jigsaw, the next generation component set for RDK
215 lines (183 loc) • 7.63 kB
text/typescript
import {
AfterContentInit, AfterViewInit, Component, ContentChildren, ElementRef, EventEmitter,
Input, NgZone, OnDestroy, QueryList, Renderer2, ViewChild
} from "@angular/core";
import {JigsawResizableBoxBase} from "./common-box";
import {CallbackRemoval} from "../../core/utils/common-utils";
export class JigsawBox extends JigsawResizableBoxBase implements AfterContentInit, AfterViewInit, OnDestroy {
constructor(elementRef: ElementRef, renderer: Renderer2, zone: NgZone) {
super(elementRef, renderer, zone);
}
public static resizeEnd = new EventEmitter();
public static resizeStart = new EventEmitter();
public static viewInit = new EventEmitter();
public resizable: boolean;
public _$isFlicker: boolean = true;
/**
* @internal
*/
public _$showResizeLine: boolean;
public parent: JigsawBox;
private _childrenBoxRaw: QueryList<JigsawBox>;
private _resizeLine: ElementRef;
private _resizeLineParent: ElementRef;
/**
* @internal
*/
public get _$childrenBox(): JigsawBox[] {
return <JigsawBox[]>this.childrenBox;
}
public set _$childrenBox(v: JigsawBox[]) {
this.childrenBox = v;
}
private _removeResizeStartListener: EventEmitter<any>;
private _removeResizeEndListener: EventEmitter<any>;
private _removeWindowResizeListener: CallbackRemoval;
private _isCurrentResizingBox: boolean;
private _computeResizeLineWidth() {
if (!this._resizeLine) return;
this.zone.runOutsideAngular(() => {
if (this.parent.direction == 'column') {
if (this.element.clientWidth != this._resizeLine.nativeElement.offsetWidth) {
this.renderer.setStyle(this._resizeLine.nativeElement, 'width', this.element.clientWidth + 'px');
}
} else {
if (this.element.clientHeight != this._resizeLine.nativeElement.offsetHeight) {
this.renderer.setStyle(this._resizeLine.nativeElement, 'height', this.element.clientHeight + 'px');
}
}
});
}
/**
* @internal
*/
public _$handleResizeStart(event) {
super._$handleResizeStart(event);
this._isCurrentResizingBox = true;
JigsawBox.resizeStart.emit();
this._emitResizeEvent('resizeStart');
}
/**
* @internal
*/
public _$handleResizeEnd() {
JigsawBox.resizeEnd.emit();
this._isCurrentResizingBox = false;
this._emitResizeEvent('resize');
}
private _emitResizeEvent(eventType: string) {
this[eventType].emit(this);
if (this.parent && this.parent.resizable && this.parent._$childrenBox.length) {
const index = this.parent._$childrenBox.findIndex(box => box == this);
const previousBox = this.parent._$childrenBox[index - 1];
if (previousBox) {
previousBox[eventType].emit(previousBox);
}
}
}
ngAfterViewInit() {
// resize line 视图渲染完成
if (!this._resizeLine) return;
this.callLater(this._computeResizeLineWidth, this);
this._removeAllListener();
this._removeResizeStartListener = JigsawBox.resizeStart.subscribe(() => {
if (this._isCurrentResizingBox || !this._resizeLineParent) return;
// 兼容IE,去掉resize过程中产生的莫名滚动条
this.renderer.setStyle(this._resizeLineParent.nativeElement, 'display', 'none');
});
this._removeResizeEndListener = JigsawBox.resizeEnd.subscribe(() => {
this._computeResizeLineWidth();
if (!this._resizeLineParent) return;
// 兼容IE,去掉resize过程中产生的莫名滚动条
if (this._isCurrentResizingBox) {
this.renderer.setStyle(this._resizeLineParent.nativeElement, 'display', 'none');
}
this.callLater(() => {
this.renderer.setStyle(this._resizeLineParent.nativeElement, 'display', 'block');
});
});
this._removeWindowResizeListener = this.renderer.listen('window', 'resize', () => {
this._computeResizeLineWidth();
});
this.removeElementScrollEvent = this.renderer.listen(this.element, 'scroll', () => {
if (this._resizeLine.nativeElement.scrollTop != this.element.scrollTop) {
this.renderer.setStyle(this._resizeLine.nativeElement, 'top', this.element.scrollTop + 'px');
}
if (this._resizeLine.nativeElement.scrollLeft != this.element.scrollLeft) {
this.renderer.setStyle(this._resizeLine.nativeElement, 'left', this.element.scrollLeft + 'px');
}
});
}
ngAfterContentInit() {
// 映射同一组件实例,ContentChildren会包含自己,https://github.com/angular/angular/issues/21148
this._$childrenBox = this._childrenBoxRaw.filter(box => box != this);
this.checkFlex();
this.removeBoxChangeListener = this._childrenBoxRaw.changes.subscribe(() => {
this._$childrenBox = this._childrenBoxRaw.filter(box => box != this);
this.checkFlexByChildren();
});
this._$childrenBox.forEach((box, index) => {
box.parent = this;
this._supportSetSize(box, this);
if (this.resizable && index != 0 && !box._isFixedSize && !this._$childrenBox[index - 1]._isFixedSize) {
// 第一个child box没有resize line
// 设置了尺寸的box没有resize line
box._$showResizeLine = true;
}
});
this.callLater(() => {
this._$isFlicker = false;
if(!this.parent) JigsawBox.viewInit.emit();
});
}
private _supportSetSize(box: JigsawBox, parent: JigsawBox) {
if (!parent) return;
if (box.width && parent.direction != 'column') {
box.renderer.setStyle(box.element, 'flex-grow', '0');
box.renderer.setStyle(box.element, 'flex-basis', box.width);
box._isFixedSize = true;
}
if (box.height && parent.direction == 'column') {
box.renderer.setStyle(box.element, 'flex-grow', '0');
box.renderer.setStyle(box.element, 'flex-basis', box.height);
box._isFixedSize = true;
}
}
private _removeAllListener() {
if (this._removeResizeStartListener) {
this._removeResizeStartListener.unsubscribe();
this._removeResizeStartListener = null;
}
if (this._removeResizeEndListener) {
this._removeResizeEndListener.unsubscribe();
this._removeResizeEndListener = null;
}
if (this._removeWindowResizeListener) {
this._removeWindowResizeListener();
this._removeWindowResizeListener = null;
}
if (this.removeElementScrollEvent) {
this.removeElementScrollEvent();
this.removeElementScrollEvent = null;
}
}
ngOnDestroy() {
super.ngOnDestroy();
this._removeAllListener();
}
}