import {NgModule,Component,Input,Output,AfterViewInit,AfterViewChecked,OnDestroy,EventEmitter,Renderer2,ElementRef,ChangeDetectorRef} from '@angular/core'; import {CommonModule} from '@angular/common'; import {DomHandler} from '../dom/domhandler'; import {trigger,state,style,transition,animate} from '@angular/animations'; @Component({ selector: 'p-overlayPanel', template: `
`, animations: [ trigger('panelState', [ state('hidden', style({ opacity: 0 })), state('visible', style({ opacity: 1 })), transition('visible => hidden', animate('400ms ease-in')), transition('hidden => visible', animate('400ms ease-out')) ]) ], providers: [DomHandler] }) export class OverlayPanel implements AfterViewInit,AfterViewChecked,OnDestroy { @Input() dismissable: boolean = true; @Input() showCloseIcon: boolean; @Input() style: any; @Input() styleClass: string; @Input() appendTo: any; @Output() onBeforeShow: EventEmitter = new EventEmitter(); @Output() onAfterShow: EventEmitter = new EventEmitter(); @Output() onBeforeHide: EventEmitter = new EventEmitter(); @Output() onAfterHide: EventEmitter = new EventEmitter(); container: any; visible: boolean = false; documentClickListener: any; selfClick: boolean; target: any; willHide: boolean; willShow: boolean; targetClickEvent: boolean; closeClick: boolean; constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private cd: ChangeDetectorRef) {} ngAfterViewInit() { this.container = this.el.nativeElement.children[0]; if(this.appendTo) { if(this.appendTo === 'body') document.body.appendChild(this.container); else this.domHandler.appendChild(this.container, this.appendTo); } } ngAfterViewChecked() { if(this.willShow) { this.domHandler.absolutePosition(this.container, this.target); this.bindDocumentClickListener(); this.onAfterShow.emit(null); this.willShow = false; } if(this.willHide) { this.onAfterHide.emit(null); this.willHide = false; } } bindDocumentClickListener() { if(!this.documentClickListener && this.dismissable) { this.documentClickListener = this.renderer.listen('document', 'click', () => { if(!this.selfClick && !this.targetClickEvent) { this.hide(); } this.selfClick = false; this.targetClickEvent = false; this.cd.markForCheck(); }); } } unbindDocumentClickListener() { if(this.documentClickListener) { this.documentClickListener(); this.documentClickListener = null; } } toggle(event, target?) { if(!this.target || this.target === (target||event.currentTarget||event.target)) { if(this.visible) this.hide(); else this.show(event, target); } else { this.show(event, target); } } show(event, target?) { this.onBeforeShow.emit(null); this.target = target||event.currentTarget||event.target; this.container.style.zIndex = ++DomHandler.zindex; this.visible = true; this.willShow = true; if(event.type === 'click') { this.targetClickEvent = true; } } hide() { if(this.visible) { this.onBeforeHide.emit(null); this.willHide = true; this.visible = false; this.selfClick = false; this.targetClickEvent = false; this.unbindDocumentClickListener(); } } onPanelClick(event) { if(this.closeClick) { this.hide(); this.closeClick = false; } else if(this.dismissable) { this.selfClick = true; } } onCloseClick(event) { this.closeClick = true; event.preventDefault(); } ngOnDestroy() { this.unbindDocumentClickListener(); if(this.appendTo) { this.el.nativeElement.appendChild(this.container); } this.target = null; } } @NgModule({ imports: [CommonModule], exports: [OverlayPanel], declarations: [OverlayPanel] }) export class OverlayPanelModule { }