Catalog alignment
[sdc.git] / catalog-ui / src / app / directives / clicked-outside / clicked-outside-directive.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 class ClickedOutsideModel {
22
23     private clickedOutsideContainerSelector:string;
24     private onClickedOutsideGetter:Function;
25     private clickedOutsideEnableGetter:Function;
26
27     constructor(clickedOutsideData:any) {
28         this.clickedOutsideContainerSelector = clickedOutsideData.clickedOutsideContainerSelector;
29         this.onClickedOutsideGetter = clickedOutsideData.onClickedOutsideGetter;
30         this.clickedOutsideEnableGetter = clickedOutsideData.clickedOutsideEnableGetter;
31     }
32
33     public getClickedOutsideContainerSelector = ():string => {
34         return this.clickedOutsideContainerSelector;
35     }
36
37     public getOnClickedOutsideGetter = ():Function => {
38         return this.onClickedOutsideGetter;
39     }
40
41     public getClickedOutsideEnableGetter = ():Function => {
42         return this.clickedOutsideEnableGetter;
43     }
44 }
45
46 export interface IClickedOutsideDirectiveScope extends ng.IScope {
47 }
48
49 export class ClickedOutsideDirective implements ng.IDirective {
50
51     constructor(private $document:JQuery, private $parse:ng.IParseService) {
52     }
53
54     restrict = 'A';
55
56     link = (scope:IClickedOutsideDirectiveScope, element:JQuery, attrs) => {
57
58         let container:HTMLElement;
59         let attrsAfterEval = scope.$eval(attrs.clickedOutside);
60         attrsAfterEval.onClickedOutsideGetter = this.$parse(attrsAfterEval.onClickedOutside);
61         attrsAfterEval.clickedOutsideEnableGetter = this.$parse(attrsAfterEval.clickedOutsideEnable);
62
63         let clickedOutsideModel:ClickedOutsideModel = new ClickedOutsideModel(attrsAfterEval);
64
65
66         let getContainer:Function = ():HTMLElement => {
67             if (!container) {
68                 let clickedOutsideContainerSelector:string = clickedOutsideModel.getClickedOutsideContainerSelector();
69                 if (!angular.isUndefined(clickedOutsideContainerSelector) && clickedOutsideContainerSelector !== '') {
70                     container = <HTMLElement>element.parents(clickedOutsideContainerSelector + ':first')[0];
71                     if (!container) {
72                         container = <HTMLElement>element[0];
73                     }
74                 } else {
75                     container = <HTMLElement>element[0];
76                 }
77             }
78             return container;
79         };
80
81
82         let onClickedOutside = (event:JQueryEventObject) => {
83             let containerDomElement:HTMLElement = getContainer();
84             let targetDomElementJq:JQuery = angular.element(event.target);
85             if (targetDomElementJq.hasClass('tooltip') || targetDomElementJq.parents('.tooltip:first').length) {
86                 return;
87             }
88             let targetDomElement:HTMLElement = <HTMLElement>targetDomElementJq[0];
89             if (!containerDomElement.contains(targetDomElement)) {
90                 scope.$apply(() => {
91                     let onClickedOutsideGetter:Function = clickedOutsideModel.getOnClickedOutsideGetter();
92                     onClickedOutsideGetter(scope);
93                 });
94             }
95         };
96
97         let attachDomEvents:Function = () => {
98             this.$document.on('mousedown', onClickedOutside);
99         };
100
101         let detachDomEvents:Function = () => {
102             this.$document.off('mousedown', onClickedOutside);
103         };
104
105         //
106         scope.$on('$destroy', () => {
107             detachDomEvents();
108         });
109
110
111         scope.$watch(() => {
112             let clickedOutsideEnableGetter:Function = clickedOutsideModel.getClickedOutsideEnableGetter();
113             return clickedOutsideEnableGetter(scope);
114         }, (newValue:boolean) => {
115             if (newValue) {
116                 attachDomEvents();
117                 return;
118             }
119             detachDomEvents();
120         });
121
122
123     }
124
125     public static factory = ($document:JQuery, $parse:ng.IParseService) => {
126         return new ClickedOutsideDirective($document, $parse);
127     }
128 }
129
130 ClickedOutsideDirective.factory.$inject = ['$document', '$parse'];