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

86 lines
2.2 KiB
TypeScript
Raw Normal View History

import {Directive, OnInit, OnDestroy, Output, EventEmitter, ElementRef} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/do';
import {Subscriber} from "rxjs";
@Directive({
selector: '[click-outside-or-esc]'
})
export class ClickOutsideOrEsc implements OnInit, OnDestroy {
private listening: boolean;
private subscriptions: any[] = [];
@Output('clickOutside') clickOutside: EventEmitter<Object>;
constructor(private _elRef: ElementRef) {
this.listening = false;
this.clickOutside = new EventEmitter();
}
ngOnInit() {
if(typeof document !== 'undefined') {
this.subscriptions.push(Observable
.fromEvent(document, 'click')
.delay(1)
.do(() => {
this.listening = true;
}).subscribe((event: MouseEvent) => {
this.onGlobalClick(event);
}));
this.subscriptions.push(Observable
.fromEvent(document, 'keydown')
.delay(1)
.do(() => {
this.listening = true;
}).subscribe((event: KeyboardEvent) => {
if (event.keyCode === 27) {
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) {
if (this.isDescendant(this._elRef.nativeElement, event.target) === true) {
this.clickOutside.emit({
target: (event.target || null),
value: false
});
} else {
this.clickOutside.emit({
target: (event.target || null),
value: true
});
}
}
}
isDescendant(parent, child) {
let node = child;
while (node !== null) {
if (node === parent) {
return true;
} else {
node = node.parentNode;
}
}
return false;
}
}