b8cfb9775132f699e92c0169e06fe883554eb6fa
[vnfsdk/refrepo.git] /
1 /*!
2  * Angular Material Design
3  * https://github.com/angular/material
4  * @license MIT
5  * v1.1.3
6  */
7 (function( window, angular, undefined ){
8 "use strict";
9
10 /**
11  * @ngdoc module
12  * @name material.components.toolbar
13  */
14 mdToolbarDirective['$inject'] = ["$$rAF", "$mdConstant", "$mdUtil", "$mdTheming", "$animate"];
15 angular.module('material.components.toolbar', [
16   'material.core',
17   'material.components.content'
18 ])
19   .directive('mdToolbar', mdToolbarDirective);
20
21 /**
22  * @ngdoc directive
23  * @name mdToolbar
24  * @module material.components.toolbar
25  * @restrict E
26  * @description
27  * `md-toolbar` is used to place a toolbar in your app.
28  *
29  * Toolbars are usually used above a content area to display the title of the
30  * current page, and show relevant action buttons for that page.
31  *
32  * You can change the height of the toolbar by adding either the
33  * `md-medium-tall` or `md-tall` class to the toolbar.
34  *
35  * @usage
36  * <hljs lang="html">
37  * <div layout="column" layout-fill>
38  *   <md-toolbar>
39  *
40  *     <div class="md-toolbar-tools">
41  *       <h2 md-truncate flex>My App's Title</h2>
42  *
43  *       <md-button>
44  *         Right Bar Button
45  *       </md-button>
46  *     </div>
47  *
48  *   </md-toolbar>
49  *   <md-content>
50  *     Hello!
51  *   </md-content>
52  * </div>
53  * </hljs>
54  *
55  * <i><b>Note:</b> The code above shows usage with the `md-truncate` component which provides an
56  * ellipsis if the title is longer than the width of the Toolbar.</i>
57  *
58  * ## CSS & Styles
59  *
60  * The `<md-toolbar>` provides a few custom CSS classes that you may use to enhance the
61  * functionality of your toolbar.
62  *
63  * <div>
64  * <docs-css-api-table>
65  *
66  *   <docs-css-selector code="md-toolbar .md-toolbar-tools">
67  *     The `md-toolbar-tools` class provides quite a bit of automatic styling for your toolbar
68  *     buttons and text. When applied, it will center the buttons and text vertically for you.
69  *   </docs-css-selector>
70  *
71  * </docs-css-api-table>
72  * </div>
73  *
74  * ### Private Classes
75  *
76  * Currently, the only private class is the `md-toolbar-transitions` class. All other classes are
77  * considered public.
78  *
79  * @param {boolean=} md-scroll-shrink Whether the header should shrink away as
80  * the user scrolls down, and reveal itself as the user scrolls up.
81  *
82  * _**Note (1):** for scrollShrink to work, the toolbar must be a sibling of a
83  * `md-content` element, placed before it. See the scroll shrink demo._
84  *
85  * _**Note (2):** The `md-scroll-shrink` attribute is only parsed on component
86  * initialization, it does not watch for scope changes._
87  *
88  *
89  * @param {number=} md-shrink-speed-factor How much to change the speed of the toolbar's
90  * shrinking by. For example, if 0.25 is given then the toolbar will shrink
91  * at one fourth the rate at which the user scrolls down. Default 0.5.
92  *
93  */
94
95 function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate) {
96   var translateY = angular.bind(null, $mdUtil.supplant, 'translate3d(0,{0}px,0)');
97
98   return {
99     template: '',
100     restrict: 'E',
101
102     link: function(scope, element, attr) {
103
104       element.addClass('_md');     // private md component indicator for styling
105       $mdTheming(element);
106
107       $mdUtil.nextTick(function () {
108         element.addClass('_md-toolbar-transitions');     // adding toolbar transitions after digest
109       }, false);
110
111       if (angular.isDefined(attr.mdScrollShrink)) {
112         setupScrollShrink();
113       }
114
115       function setupScrollShrink() {
116
117         var toolbarHeight;
118         var contentElement;
119         var disableScrollShrink = angular.noop;
120
121         // Current "y" position of scroll
122         // Store the last scroll top position
123         var y = 0;
124         var prevScrollTop = 0;
125         var shrinkSpeedFactor = attr.mdShrinkSpeedFactor || 0.5;
126
127         var debouncedContentScroll = $$rAF.throttle(onContentScroll);
128         var debouncedUpdateHeight = $mdUtil.debounce(updateToolbarHeight, 5 * 1000);
129
130         // Wait for $mdContentLoaded event from mdContent directive.
131         // If the mdContent element is a sibling of our toolbar, hook it up
132         // to scroll events.
133
134         scope.$on('$mdContentLoaded', onMdContentLoad);
135
136         // If the toolbar is used inside an ng-if statement, we may miss the
137         // $mdContentLoaded event, so we attempt to fake it if we have a
138         // md-content close enough.
139
140         attr.$observe('mdScrollShrink', onChangeScrollShrink);
141
142         // If the toolbar has ngShow or ngHide we need to update height immediately as it changed
143         // and not wait for $mdUtil.debounce to happen
144
145         if (attr.ngShow) { scope.$watch(attr.ngShow, updateToolbarHeight); }
146         if (attr.ngHide) { scope.$watch(attr.ngHide, updateToolbarHeight); }
147
148         // If the scope is destroyed (which could happen with ng-if), make sure
149         // to disable scroll shrinking again
150
151         scope.$on('$destroy', disableScrollShrink);
152
153         /**
154          *
155          */
156         function onChangeScrollShrink(shrinkWithScroll) {
157           var closestContent = element.parent().find('md-content');
158
159           // If we have a content element, fake the call; this might still fail
160           // if the content element isn't a sibling of the toolbar
161
162           if (!contentElement && closestContent.length) {
163             onMdContentLoad(null, closestContent);
164           }
165
166           // Evaluate the expression
167           shrinkWithScroll = scope.$eval(shrinkWithScroll);
168
169           // Disable only if the attribute's expression evaluates to false
170           if (shrinkWithScroll === false) {
171             disableScrollShrink();
172           } else {
173             disableScrollShrink = enableScrollShrink();
174           }
175         }
176
177         /**
178          *
179          */
180         function onMdContentLoad($event, newContentEl) {
181           // Toolbar and content must be siblings
182           if (newContentEl && element.parent()[0] === newContentEl.parent()[0]) {
183             // unhook old content event listener if exists
184             if (contentElement) {
185               contentElement.off('scroll', debouncedContentScroll);
186             }
187
188             contentElement = newContentEl;
189             disableScrollShrink = enableScrollShrink();
190           }
191         }
192
193         /**
194          *
195          */
196         function onContentScroll(e) {
197           var scrollTop = e ? e.target.scrollTop : prevScrollTop;
198
199           debouncedUpdateHeight();
200
201           y = Math.min(
202             toolbarHeight / shrinkSpeedFactor,
203             Math.max(0, y + scrollTop - prevScrollTop)
204           );
205
206           element.css($mdConstant.CSS.TRANSFORM, translateY([-y * shrinkSpeedFactor]));
207           contentElement.css($mdConstant.CSS.TRANSFORM, translateY([(toolbarHeight - y) * shrinkSpeedFactor]));
208
209           prevScrollTop = scrollTop;
210
211           $mdUtil.nextTick(function() {
212             var hasWhiteFrame = element.hasClass('md-whiteframe-z1');
213
214             if (hasWhiteFrame && !y) {
215               $animate.removeClass(element, 'md-whiteframe-z1');
216             } else if (!hasWhiteFrame && y) {
217               $animate.addClass(element, 'md-whiteframe-z1');
218             }
219           });
220
221         }
222
223         /**
224          *
225          */
226         function enableScrollShrink() {
227           if (!contentElement)     return angular.noop;           // no md-content
228
229           contentElement.on('scroll', debouncedContentScroll);
230           contentElement.attr('scroll-shrink', 'true');
231
232           $mdUtil.nextTick(updateToolbarHeight, false);
233
234           return function disableScrollShrink() {
235             contentElement.off('scroll', debouncedContentScroll);
236             contentElement.attr('scroll-shrink', 'false');
237
238             updateToolbarHeight();
239           };
240         }
241
242         /**
243          *
244          */
245         function updateToolbarHeight() {
246           toolbarHeight = element.prop('offsetHeight');
247           // Add a negative margin-top the size of the toolbar to the content el.
248           // The content will start transformed down the toolbarHeight amount,
249           // so everything looks normal.
250           //
251           // As the user scrolls down, the content will be transformed up slowly
252           // to put the content underneath where the toolbar was.
253           var margin = (-toolbarHeight * shrinkSpeedFactor) + 'px';
254
255           contentElement.css({
256             "margin-top": margin,
257             "margin-bottom": margin
258           });
259
260           onContentScroll();
261         }
262
263       }
264
265     }
266   };
267
268 }
269
270 })(window, window.angular);