ng-ytl-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
99 lines (89 loc) • 3.82 kB
text/typescript
import {
AfterViewInit,
ComponentFactoryResolver,
Directive,
ElementRef,
HostBinding,
Input,
Optional,
Renderer2,
SimpleChanges,
ViewContainerRef,
} from '@angular/core';
import { NzToolTipComponent } from './nz-tooltip.component';
export class NzTooltipDirective implements AfterViewInit {
// [NOTE] Here hard coded, and nzTitle used only under NzTooltipDirective currently.
// The inherited class such as NzPopconfirmDirective should override this property if want using this property.
get nzTitle(): string { return this.tooltip.nzTitle; }
set nzTitle(title: string) {
if (this.isDynamicTooltip) {
this.tooltip.nzTitle = title;
}
}
isTooltipOpen;
private tooltip: NzToolTipComponent;
private isDynamicTooltip = false; // Indicate whether current tooltip is dynamic created
private delayTimer; // Timer for delay enter/leave
constructor(
public elementRef: ElementRef,
private hostView: ViewContainerRef,
private resolver: ComponentFactoryResolver,
private renderer: Renderer2,
tooltip: NzToolTipComponent) {
this.tooltip = tooltip;
// Support faster tooltip mode: <a nz-tooltip="xxx"></a>. [NOTE] Used only under NzTooltipDirective currently.
if (!this.tooltip) {
const factory = this.resolver.resolveComponentFactory(NzToolTipComponent);
this.tooltip = this.hostView.createComponent(factory).instance;
this.isDynamicTooltip = true;
}
this.tooltip.setOverlayOrigin(this);
}
ngAfterViewInit(): void {
if (this.tooltip.nzTrigger === 'hover') {
let overlayElement;
this.renderer.listen(this.elementRef.nativeElement, 'mouseenter', () => this.delayEnterLeave(true, true, this.tooltip.nzMouseEnterDelay));
this.renderer.listen(this.elementRef.nativeElement, 'mouseleave', () => {
this.delayEnterLeave(true, false, this.tooltip.nzMouseLeaveDelay);
if (this.tooltip.overlay.overlayRef && !overlayElement) { // NOTE: we bind events under "mouseleave" due to the overlayRef is only created after the overlay was completely shown up
overlayElement = this.tooltip.overlay.overlayRef.overlayElement;
this.renderer.listen(overlayElement, 'mouseenter', () => this.delayEnterLeave(false, true));
this.renderer.listen(overlayElement, 'mouseleave', () => this.delayEnterLeave(false, false));
}
});
} else if (this.tooltip.nzTrigger === 'focus') {
this.renderer.listen(this.elementRef.nativeElement, 'focus', () => this.show());
this.renderer.listen(this.elementRef.nativeElement, 'blur', () => this.hide());
} else if (this.tooltip.nzTrigger === 'click') {
this.renderer.listen(this.elementRef.nativeElement, 'click', (e) => {
e.preventDefault();
this.show();
});
}
}
private show(): void {
this.tooltip.show();
this.isTooltipOpen = true;
}
private hide(): void {
this.tooltip.hide();
this.isTooltipOpen = false;
}
private delayEnterLeave(isOrigin: boolean, isEnter: boolean, delay: number = -1): void {
if (this.delayTimer) { // Clear timer during the delay time
window.clearTimeout(this.delayTimer);
this.delayTimer = null;
} else if (delay > 0) {
this.delayTimer = window.setTimeout(() => {
this.delayTimer = null;
isEnter ? this.show() : this.hide();
}, delay * 1000);
} else {
isEnter && isOrigin ? this.show() : this.hide(); // [Compatible] The "isOrigin" is used due to the tooltip will not hide immediately (may caused by the fade-out animation)
}
}
}