summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/clicked-outside/clicked-outside-directive.ts
blob: 009e10474096fdc8e573cb716a585e952bbe393a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
class ClickedOutsideModel {

    private clickedOutsideContainerSelector:string;
    private onClickedOutsideGetter:Function;
    private clickedOutsideEnableGetter:Function;

    constructor(clickedOutsideData:any) {
        this.clickedOutsideContainerSelector = clickedOutsideData.clickedOutsideContainerSelector;
        this.onClickedOutsideGetter = clickedOutsideData.onClickedOutsideGetter;
        this.clickedOutsideEnableGetter = clickedOutsideData.clickedOutsideEnableGetter;
    }

    public getClickedOutsideContainerSelector = ():string => {
        return this.clickedOutsideContainerSelector;
    }

    public getOnClickedOutsideGetter = ():Function => {
        return this.onClickedOutsideGetter;
    }

    public getClickedOutsideEnableGetter = ():Function => {
        return this.clickedOutsideEnableGetter;
    }
}

export interface IClickedOutsideDirectiveScope extends ng.IScope {
}

export class ClickedOutsideDirective implements ng.IDirective {

    constructor(private $document:JQuery, private $parse:ng.IParseService) {
    }

    restrict = 'A';

    link = (scope:IClickedOutsideDirectiveScope, element:JQuery, attrs) => {

        let container:HTMLElement;
        let attrsAfterEval = scope.$eval(attrs.clickedOutside);
        attrsAfterEval.onClickedOutsideGetter = this.$parse(attrsAfterEval.onClickedOutside);
        attrsAfterEval.clickedOutsideEnableGetter = this.$parse(attrsAfterEval.clickedOutsideEnable);

        let clickedOutsideModel:ClickedOutsideModel = new ClickedOutsideModel(attrsAfterEval);


        let getContainer:Function = ():HTMLElement => {
            if (!container) {
                let clickedOutsideContainerSelector:string = clickedOutsideModel.getClickedOutsideContainerSelector();
                if (!angular.isUndefined(clickedOutsideContainerSelector) && clickedOutsideContainerSelector !== '') {
                    container = element.parents(clickedOutsideContainerSelector + ':first')[0];
                    if (!container) {
                        container = element[0];
                    }
                } else {
                    container = element[0];
                }
            }
            return container;
        };


        let onClickedOutside = (event:JQueryEventObject) => {
            let containerDomElement:HTMLElement = getContainer();
            let targetDomElementJq:JQuery = angular.element(event.target);
            if (targetDomElementJq.hasClass('tooltip') || targetDomElementJq.parents('.tooltip:first').length) {
                return;
            }
            let targetDomElement:HTMLElement = targetDomElementJq[0];
            if (!containerDomElement.contains(targetDomElement)) {
                scope.$apply(() => {
                    let onClickedOutsideGetter:Function = clickedOutsideModel.getOnClickedOutsideGetter();
                    onClickedOutsideGetter(scope);
                });
            }
        };

        let attachDomEvents:Function = () => {
            this.$document.on('mousedown', onClickedOutside);
        };

        let detachDomEvents:Function = () => {
            this.$document.off('mousedown', onClickedOutside);
        };

        //
        scope.$on('$destroy', () => {
            detachDomEvents();
        });


        scope.$watch(() => {
            let clickedOutsideEnableGetter:Function = clickedOutsideModel.getClickedOutsideEnableGetter();
            return clickedOutsideEnableGetter(scope);
        }, (newValue:boolean) => {
            if (newValue) {
                attachDomEvents();
                return;
            }
            detachDomEvents();
        });


    }

    public static factory = ($document:JQuery, $parse:ng.IParseService) => {
        return new ClickedOutsideDirective($document, $parse);
    }
}

ClickedOutsideDirective.factory.$inject = ['$document', '$parse'];