openaire-library/utils/click/click-outside-or-esc.direct...

80 lines
2.1 KiB
TypeScript

import {Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
import {fromEvent, Subscriber} from 'rxjs';
import {delay, tap} from 'rxjs/operators';
@Directive({
selector: '[click-outside-or-esc]'
})
export class ClickOutsideOrEsc implements OnInit, OnDestroy {
private listening: boolean;
private subscriptions: any[] = [];
@Input()
public targetId = null;
@Input()
public escClose = true;
@Input()
public clickClose = true;
@Output('clickOutside') clickOutside: EventEmitter<Object>;
constructor(private _elRef: ElementRef) {
this.listening = false;
this.clickOutside = new EventEmitter();
}
ngOnInit() {
if(typeof document !== 'undefined') {
this.subscriptions.push(fromEvent(document, 'click').pipe(
delay(1),
tap(() => {
this.listening = true;
})).subscribe((event: MouseEvent) => {
this.onGlobalClick(event);
}));
this.subscriptions.push(fromEvent(document, 'click').pipe(
delay(1),
tap(() => {
this.listening = true;
})).subscribe((event: KeyboardEvent) => {
if (event.keyCode === 27 && this.escClose) {
this.clickOutside.emit({
target: (event.target || null),
value: true
});
}
}));
}
}
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.forEach((subscription: Subscriber<any>) => {
subscription.unsubscribe();
});
}
this.subscriptions = [];
}
onGlobalClick(event: MouseEvent) {
if (event instanceof MouseEvent && this.listening === true) {
let element: HTMLElement = <HTMLElement>event.target;
while (element) {
if(element.id === this.targetId) {
this.clickOutside.emit({
target: (event.target || null),
value: false
});
return;
}
element = element.parentElement;
}
if(this.clickClose) {
this.clickOutside.emit({
target: (event.target || null),
value: true
});
}
}
}
}