Project

General

Profile

1
import {Directive, OnInit, OnDestroy, Output, EventEmitter, ElementRef, Input} from '@angular/core';
2
import {Observable} from 'rxjs/Observable';
3
import 'rxjs/add/observable/fromEvent';
4
import 'rxjs/add/operator/delay';
5
import 'rxjs/add/operator/do';
6
import {Subscriber} from "rxjs";
7

    
8
@Directive({
9
  selector: '[click-outside-or-esc]'
10
})
11

    
12
export class ClickOutsideOrEsc implements OnInit, OnDestroy {
13
  private listening: boolean;
14
  private subscriptions: any[] = [];
15
  @Input()
16
  public targetId = null;
17
  @Input()
18
  public escClose = true;
19

    
20
  @Output('clickOutside') clickOutside: EventEmitter<Object>;
21

    
22
  constructor(private _elRef: ElementRef) {
23
    this.listening = false;
24
    this.clickOutside = new EventEmitter();
25
  }
26

    
27
  ngOnInit() {
28
    if(typeof document !== 'undefined') {
29
      this.subscriptions.push(Observable
30
        .fromEvent(document, 'click')
31
        .delay(1)
32
        .do(() => {
33
          this.listening = true;
34
        }).subscribe((event: MouseEvent) => {
35
          this.onGlobalClick(event);
36
        }));
37
      this.subscriptions.push(Observable
38
        .fromEvent(document, 'keydown')
39
        .delay(1)
40
        .do(() => {
41
          this.listening = true;
42
        }).subscribe((event: KeyboardEvent) => {
43
          if (event.keyCode === 27 && this.escClose) {
44
            this.clickOutside.emit({
45
              target: (event.target || null),
46
              value: true
47
            });
48
          }
49
        }));
50
    }
51
  }
52

    
53
  ngOnDestroy() {
54
    if (this.subscriptions) {
55
      this.subscriptions.forEach((subscription: Subscriber<any>) => {
56
        subscription.unsubscribe();
57
      });
58
    }
59
    this.subscriptions = [];
60
  }
61

    
62
  onGlobalClick(event: MouseEvent) {
63
    if (event instanceof MouseEvent && this.listening === true) {
64
      let element: HTMLElement = <HTMLElement>event.target;
65
      while (element) {
66
        if(element.id === this.targetId) {
67
          this.clickOutside.emit({
68
            target: (event.target || null),
69
            value: false
70
          });
71
          return;
72
        }
73
        element = element.parentElement;
74
      }
75
      this.clickOutside.emit({
76
        target: (event.target || null),
77
        value: true
78
      });
79
    }
80
  }
81
}
(1-1/3)