re base code
[sdc.git] / catalog-ui / src / app / directives / loader / loader-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 'use strict';
21 import {EVENTS} from "app/utils";
22 import {EventListenerService} from "app/services";
23
24 export interface ILoaderScope extends ng.IScope {
25     display:boolean;        // Toggle show || hide scroll
26     size:string;            // small || medium || large
27     elementSelector:string; // Jquery selector to hide and scroll inside
28     relative:boolean;       // Will use the parent of <loader> element and hide it and scroll inside
29     loaderType:string;
30 }
31
32 export class LoaderDirective implements ng.IDirective {
33
34     constructor(private EventListenerService:EventListenerService) {
35     }
36
37     /*
38      * relative is used when inserting the HTML loader inside some div <loader data-display="isLoading" relative="true"></loader>
39      * elementSelector when we want to pass the Jquery selector of the loader.
40      */
41     scope = {
42         display: '=',
43         size: '@?',
44         elementSelector: '@?',
45         relative: '=?',
46         loaderType: '@?'
47     };
48
49     public replace = false;
50     public restrict = 'E';
51     template = ():string => {
52         return require('./loader-directive.html');
53     }
54
55     link = (scope:ILoaderScope, element:any) => {
56
57         let interval;
58
59         if(scope.loaderType) {
60             this.EventListenerService.registerObserverCallback(EVENTS.SHOW_LOADER_EVENT + scope.loaderType, (loaderType)=> {
61                 scope.display = true;
62             });
63             this.EventListenerService.registerObserverCallback(EVENTS.HIDE_LOADER_EVENT + scope.loaderType, (loaderType)=> {
64                 scope.display = false;
65             });
66         }
67         let calculateSizesForFixPosition = (positionStyle:string):void => {
68             // This is problematic, I do not want to change the parent position.
69             // set the loader on all the screen
70             let parentPosition = element.parent().position();
71             let parentWidth = element.parent().width();
72             let parentHeight = element.parent().height();
73             element.css('position', positionStyle);
74             element.css('top', parentPosition.top);
75             element.css('left', parentPosition.left);
76             element.css('width', parentWidth);
77             element.css('height', parentHeight);
78         };
79
80         let setStyle = (positionStyle:string):void => {
81
82             switch (positionStyle) {
83                 case 'absolute':
84                 case 'fixed':
85                     // The parent size is not set yet, still loading, so need to use interval to update the size.
86                     interval = window.setInterval(()=> {
87                         calculateSizesForFixPosition(positionStyle);
88                     }, 2000);
89                     break;
90                 default:
91                     // Can change the parent position to relative without causing style issues.
92                     element.parent().css('position', 'relative');
93                     break;
94             }
95         };
96
97         // This should be executed after the dom loaded
98         window.setTimeout(():void => {
99
100             element.css('display', 'none');
101
102             if (scope.elementSelector) {
103                 let elemParent = angular.element(scope.elementSelector);
104                 let positionStyle:string = elemParent.css('position');
105                 setStyle(positionStyle);
106             }
107
108             if (scope.relative === true) {
109                 let positionStyle:string = element.parent().css('position');
110                 setStyle(positionStyle);
111             }
112
113             if (!scope.size) {
114                 scope.size = 'large';
115             }
116
117         }, 0);
118
119         if (scope.elementSelector) {
120
121         }
122
123         function cleanUp() {
124             clearInterval(interval);
125         }
126
127         scope.$watch("display", (newVal, oldVal) => {
128             element.css('display', 'none');
129             let timeout;
130             if (newVal === true) {
131                 timeout = window.setTimeout(():void => {
132                     element.css('display', 'block');
133                 }, 500);
134             } else {
135                 window.clearTimeout(timeout);
136                 window.setTimeout(():void => {
137                     element.css('display', 'none');
138                 }, 0);
139             }
140         });
141
142         scope.$on('$destroy', cleanUp);
143
144     };
145
146     public static factory = (EventListenerService:EventListenerService)=> {
147         return new LoaderDirective( EventListenerService);
148     };
149
150 }
151
152 LoaderDirective.factory.$inject = ['EventListenerService'];