unicorn-components
Version:
<a target="_blank" href="https://getunicorn.io"><img src="https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2017/Jul/07/2615006260-5-nitsnetsstudios-ondemand-UNI_avatar.png" align="left"></a>
112 lines (98 loc) • 3.57 kB
text/typescript
import {
AfterContentInit,
Component,
ContentChild,
Directive,
ElementRef,
EventEmitter,
Host,
HostListener,
Input,
OnDestroy,
Output,
HostBinding,
} from '@angular/core';
import { OnChanges } from '@angular/core';
import { UniPopupContainerComponent } from './container/container.component';
export type UniPopupPosition = 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
export class UniPopupComponent implements AfterContentInit, OnChanges {
componentClass = true;
toggle = false;
keepOpen = true;
opened = false;
closable = true;
openedChange = new EventEmitter();
position: UniPopupPosition = null;
calculatedPosition: UniPopupPosition = null;
popupScope: UniPopupContainerComponent;
constructor(private elementRef: ElementRef) { }
ngOnChanges(changes) {
if (changes['closable']) {
this.popupScope.closable = this.closable;
}
}
ngAfterContentInit() {
this.popupScope.closable = this.closable;
this.popupScope.close.subscribe(_ => this.close());
}
open(x = null) {
if (x) {
this.calculatedPosition = x > document.documentElement.clientWidth / 2 ? 'bottom-left' : 'bottom-right';
}
this.opened = true;
this.openedChange.emit(true);
}
close() {
this.opened = false;
this.openedChange.emit(false);
}
isInClosableZone(element: HTMLElement) {
if (!this.popupScope || this.keepOpen === false) { return false; }
return this.popupScope.elementRef.nativeElement.contains(element);
}
}
export class UniPopupTriggerDirective implements OnDestroy {
private openedByFocus = false;
private closePopupOnOutsideClick = (event: MouseEvent) => this.close(event);
constructor( public popup: UniPopupComponent, private elementRef: ElementRef) { }
openPopup(ev: MouseEvent) {
if (this.openedByFocus) {
this.openedByFocus = false;
return;
}
if (this.popup.opened && this.popup.toggle) {
this.popup.close();
document.removeEventListener('click', this.closePopupOnOutsideClick);
} else {
this.popup.open(ev.clientX);
document.addEventListener('click', this.closePopupOnOutsideClick, true);
}
}
onBlur(event: FocusEvent) {
if (event.relatedTarget &&
!this.popup.isInClosableZone(<HTMLElement>event.relatedTarget) &&
event.relatedTarget !== this.elementRef.nativeElement) {
this.popup.close();
document.removeEventListener('click', this.closePopupOnOutsideClick);
}
}
ngOnDestroy() {
document.removeEventListener('click', this.closePopupOnOutsideClick);
}
private close(event: Event) {
if (!this.popup.isInClosableZone(<HTMLElement>event.target)
&& event.target !== this.elementRef.nativeElement
&& !this.elementRef.nativeElement.contains(event.target)) {
this.popup.close();
document.removeEventListener('click', this.closePopupOnOutsideClick);
}
}
}