8e3204a97b2d64ef8a06aa085a3fc550e0be3130
[sdc/sdc-workflow-designer.git] /
1 /**
2  * @license
3  * Copyright Google Inc. All Rights Reserved.
4  *
5  * Use of this source code is governed by an MIT-style license that can be
6  * found in the LICENSE file at https://angular.io/license
7  */
8 /* tslint:disable:array-type member-access variable-name typedef
9  only-arrow-functions directive-class-suffix component-class-suffix
10  component-selector no-unnecessary-type-assertion arrow-parens*/
11 import {PositionStrategy} from './position-strategy';
12
13
14 /**
15  * A strategy for positioning overlays. Using this strategy, an overlay is given
16  * an explicit position relative to the browser's viewport. We use flexbox,
17  * instead of transforms, in order to avoid issues with subpixel rendering which
18  * can cause the element to become blurry.
19  */
20 export class GlobalPositionStrategy implements PositionStrategy {
21   private _cssPosition = 'static';
22   private _topOffset = '';
23   private _bottomOffset = '';
24   private _leftOffset = '';
25   private _rightOffset = '';
26   private _alignItems = '';
27   private _justifyContent = '';
28   private _width = '';
29   private _height = '';
30
31   /* A lazily-created wrapper for the overlay element that is used as a flex
32    * container.  */
33   private _wrapper: HTMLElement|null = null;
34
35   /**
36    * Sets the top position of the overlay. Clears any previously set vertical
37    * position.
38    * @param value New top offset.
39    */
40   top(value = ''): this {
41         this._bottomOffset = '';
42         this._topOffset = value;
43         this._alignItems = 'flex-start';
44         return this;
45   }
46
47   /**
48    * Sets the left position of the overlay. Clears any previously set horizontal
49    * position.
50    * @param value New left offset.
51    */
52   left(value = ''): this {
53         this._rightOffset = '';
54         this._leftOffset = value;
55         this._justifyContent = 'flex-start';
56         return this;
57   }
58
59   /**
60    * Sets the bottom position of the overlay. Clears any previously set vertical
61    * position.
62    * @param value New bottom offset.
63    */
64   bottom(value = ''): this {
65         this._topOffset = '';
66         this._bottomOffset = value;
67         this._alignItems = 'flex-end';
68         return this;
69   }
70
71   /**
72    * Sets the right position of the overlay. Clears any previously set
73    * horizontal position.
74    * @param value New right offset.
75    */
76   right(value = ''): this {
77         this._leftOffset = '';
78         this._rightOffset = value;
79         this._justifyContent = 'flex-end';
80         return this;
81   }
82
83   /**
84    * Sets the overlay width and clears any previously set width.
85    * @param value New width for the overlay
86    */
87   width(value = ''): this {
88         this._width = value;
89
90     // When the width is 100%, we should reset the `left` and the offset,
91     // in order to ensure that the element is flush against the viewport edge.
92         if (value === '100%') {
93                 this.left('0px');
94         }
95
96         return this;
97   }
98
99   /**
100    * Sets the overlay height and clears any previously set height.
101    * @param value New height for the overlay
102    */
103   height(value = ''): this {
104         this._height = value;
105
106     // When the height is 100%, we should reset the `top` and the offset,
107     // in order to ensure that the element is flush against the viewport edge.
108         if (value === '100%') {
109                 this.top('0px');
110         }
111
112         return this;
113   }
114
115   /**
116    * Centers the overlay horizontally with an optional offset.
117    * Clears any previously set horizontal position.
118    *
119    * @param offset Overlay offset from the horizontal center.
120    */
121   centerHorizontally(offset = ''): this {
122         this.left(offset);
123         this._justifyContent = 'center';
124         return this;
125   }
126
127   /**
128    * Centers the overlay vertically with an optional offset.
129    * Clears any previously set vertical position.
130    *
131    * @param offset Overlay offset from the vertical center.
132    */
133   centerVertically(offset = ''): this {
134         this.top(offset);
135         this._alignItems = 'center';
136         return this;
137   }
138
139   /**
140    * Apply the position to the element.
141    * @docs-private
142    *
143    * @param element Element to which to apply the CSS.
144    * @returns Resolved when the styles have been applied.
145    */
146   apply(element: HTMLElement): void {
147         if (!this._wrapper && element.parentNode) {
148                 this._wrapper = document.createElement('div');
149                 this._wrapper.classList.add('cdk-global-overlay-wrapper');
150                 element.parentNode.insertBefore(this._wrapper, element);
151                 this._wrapper.appendChild(element);
152         }
153
154         const styles = element.style;
155         const parentStyles = (element.parentNode as HTMLElement).style;
156
157         styles.position = this._cssPosition;
158         styles.marginTop = this._topOffset;
159         styles.marginLeft = this._leftOffset;
160         styles.marginBottom = this._bottomOffset;
161         styles.marginRight = this._rightOffset;
162         styles.width = this._width;
163         styles.height = this._height;
164
165         parentStyles.justifyContent = this._justifyContent;
166         parentStyles.alignItems = this._alignItems;
167   }
168
169   /**
170    * Removes the wrapper element from the DOM.
171    */
172   dispose(): void {
173         if (this._wrapper && this._wrapper.parentNode) {
174                 this._wrapper.parentNode.removeChild(this._wrapper);
175                 this._wrapper = null;
176         }
177   }
178 }