import { Directive , HostListener , ComponentRef , ViewContainerRef , ComponentFactoryResolver , ComponentFactory , Input , OnChanges , SimpleChange , Output , EventEmitter } from "@angular/core" ; import { PopoverContent } from "./PopoverContent" ; @ Directive ( { selector : "[popover]" , exportAs : "popover" } ) export class Popover implements OnChanges { protected PopoverComponent = PopoverContent ; protected popover : ComponentRef < PopoverContent > ; protected visible : boolean ; constructor ( protected viewContainerRef , protected resolver ) { } @ Input ( "popover" ) content : string | PopoverContent ; @ Input ( ) popoverDisabled : boolean ; @ Input ( ) popoverAnimation : boolean ; @ Input ( ) popoverPlacement : "top" | "bottom" | "left" | "right" | "auto" | "auto top" | "auto bottom" | "auto left" | "auto right" ; @ Input ( ) popoverTitle : string ; @ Input ( ) popoverOnHover : boolean = false ; @ Input ( ) popoverCloseOnClickOutside : boolean ; @ Input ( ) popoverCloseOnMouseOutside : boolean ; @ Input ( ) popoverDismissTimeout : number = 0 ; @ Output ( ) onShown = new EventEmitter < Popover > ( ) ; @ Output ( ) onHidden = new EventEmitter < Popover > ( ) ; @ HostListener ( "click" ) showOrHideOnClick ( ) { if ( this . popoverOnHover ) return ; if ( this . popoverDisabled ) return ; this . toggle ( ) ; } @ HostListener ( "focusin" ) @ HostListener ( "mouseenter" ) showOnHover ( ) { if ( ! this . popoverOnHover ) return ; if ( this . popoverDisabled ) return ; this . show ( ) ; } @ HostListener ( "focusout" ) @ HostListener ( "mouseleave" ) hideOnHover ( ) { if ( this . popoverCloseOnMouseOutside ) return ; if ( ! this . popoverOnHover ) return ; if ( this . popoverDisabled ) return ; this . hide ( ) ; } ngOnChanges ( changes ) { if ( changes [ "popoverDisabled" ] ) { if ( changes [ "popoverDisabled" ] . currentValue ) { this . hide ( ) ; } } } toggle ( ) { if ( ! this . visible ) { this . show ( ) ; } else { this . hide ( ) ; } } show ( ) { if ( this . visible ) return ; this . visible = true ; if ( typeof this . content === "string" ) { const factory = this . resolver . resolveComponentFactory ( this . PopoverComponent ) ; if ( ! this . visible ) return ; this . popover = this . viewContainerRef . createComponent ( factory ) ; const popover = this . popover . instance as PopoverContent ; popover . popover = this ; popover . content = this . content as string ; if ( this . popoverPlacement !== undefined ) popover . placement = this . popoverPlacement ; if ( this . popoverAnimation !== undefined ) popover . animation = this . popoverAnimation ; if ( this . popoverTitle !== undefined ) popover . title = this . popoverTitle ; if ( this . popoverCloseOnClickOutside !== undefined ) popover . closeOnClickOutside = this . popoverCloseOnClickOutside ; if ( this . popoverCloseOnMouseOutside !== undefined ) popover . closeOnMouseOutside = this . popoverCloseOnMouseOutside ; popover . onCloseFromOutside . subscribe ( ( ) => this . hide ( ) ) ; if ( this . popoverDismissTimeout > 0 ) setTimeout ( ( ) => this . hide ( ) , this . popoverDismissTimeout ) ; } else { const popover = this . content as PopoverContent ; popover . popover = this ; if ( this . popoverPlacement !== undefined ) popover . placement = this . popoverPlacement ; if ( this . popoverAnimation !== undefined ) popover . animation = this . popoverAnimation ; if ( this . popoverTitle !== undefined ) popover . title = this . popoverTitle ; if ( this . popoverCloseOnClickOutside !== undefined ) popover . closeOnClickOutside = this . popoverCloseOnClickOutside ; if ( this . popoverCloseOnMouseOutside !== undefined ) popover . closeOnMouseOutside = this . popoverCloseOnMouseOutside ; popover . onCloseFromOutside . subscribe ( ( ) => this . hide ( ) ) ; if ( this . popoverDismissTimeout > 0 ) setTimeout ( ( ) => this . hide ( ) , this . popoverDismissTimeout ) ; popover . show ( ) ; } this . onShown . emit ( this ) ; } hide ( ) { if ( ! this . visible ) return ; this . visible = false ; if ( this . popover ) this . popover . destroy ( ) ; if ( this . content instanceof PopoverContent ) ( this . content as PopoverContent ) . hideFromPopover ( ) ; this . onHidden . emit ( this ) ; } getElement ( ) { return this . viewContainerRef . element . nativeElement ; } }