Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / paper-header-panel / paper-header-panel-extracted.js
blob1b1f0714071013eb8d2e0c942b082091b8a6bb4e
3   (function() {
5     'use strict';
7     var SHADOW_WHEN_SCROLLING = 1;
8     var SHADOW_ALWAYS = 2;
11     var MODE_CONFIGS = {
13       outerScroll: {
14         scroll: true
15       },
17       shadowMode: {
18         standard: SHADOW_ALWAYS,
19         waterfall: SHADOW_WHEN_SCROLLING,
20         'waterfall-tall': SHADOW_WHEN_SCROLLING
21       },
23       tallMode: {
24         'waterfall-tall': true
25       }
26     };
28     Polymer({
30       is: 'paper-header-panel',
32       /**
33        * Fired when the content has been scrolled.  `event.detail.target` returns
34        * the scrollable element which you can use to access scroll info such as
35        * `scrollTop`.
36        *
37        *     <paper-header-panel on-content-scroll="{{scrollHandler}}">
38        *       ...
39        *     </paper-header-panel>
40        *
41        *
42        *     scrollHandler: function(event) {
43        *       var scroller = event.detail.target;
44        *       console.log(scroller.scrollTop);
45        *     }
46        *
47        * @event content-scroll
48        */
50       properties: {
52         /**
53          * Controls header and scrolling behavior. Options are
54          * `standard`, `seamed`, `waterfall`, `waterfall-tall`, `scroll` and
55          * `cover`. Default is `standard`.
56          *
57          * `standard`: The header is a step above the panel. The header will consume the
58          * panel at the point of entry, preventing it from passing through to the
59          * opposite side.
60          *
61          * `seamed`: The header is presented as seamed with the panel.
62          *
63          * `waterfall`: Similar to standard mode, but header is initially presented as
64          * seamed with panel, but then separates to form the step.
65          *
66          * `waterfall-tall`: The header is initially taller (`tall` class is added to
67          * the header).  As the user scrolls, the header separates (forming an edge)
68          * while condensing (`tall` class is removed from the header).
69          *
70          * `scroll`: The header keeps its seam with the panel, and is pushed off screen.
71          *
72          * `cover`: The panel covers the whole `paper-header-panel` including the
73          * header. This allows user to style the panel in such a way that the panel is
74          * partially covering the header.
75          *
76          *     <paper-header-panel mode="cover">
77          *       <paper-toolbar class="tall">
78          *         <core-icon-button icon="menu"></core-icon-button>
79          *       </paper-toolbar>
80          *       <div class="content"></div>
81          *     </paper-header-panel>
82          */
83         mode: {
84           type: String,
85           value: 'standard',
86           observer: '_modeChanged',
87           reflectToAttribute: true
88         },
90         /**
91          * If true, the drop-shadow is always shown no matter what mode is set to.
92          */
93         shadow: {
94           type: Boolean,
95           value: false
96         },
98         /**
99          * The class used in waterfall-tall mode.  Change this if the header
100          * accepts a different class for toggling height, e.g. "medium-tall"
101          */
102         tallClass: {
103           type: String,
104           value: 'tall'
105         },
107         /**
108          * If true, the scroller is at the top
109          */
110         atTop: {
111           type: Boolean,
112           value: true,
113           readOnly: true
114         }
115       },
117       observers: [
118         '_computeDropShadowHidden(atTop, mode, shadow)'
119       ],
121       ready: function() {
122         this.scrollHandler = this._scroll.bind(this);
123         this._addListener();
125         // Run `scroll` logic once to initialze class names, etc.
126         this._keepScrollingState();
127       },
129       detached: function() {
130         this._removeListener();
131       },
133       /**
134        * Returns the header element
135        *
136        * @property header
137        * @type Object
138        */
139       get header() {
140         return Polymer.dom(this.$.headerContent).getDistributedNodes()[0];
141       },
143       /**
144        * Returns the scrollable element.
145        *
146        * @property scroller
147        * @type Object
148        */
149       get scroller() {
150         return this._getScrollerForMode(this.mode);
151       },
153       /**
154        * Returns true if the scroller has a visible shadow.
155        *
156        * @property visibleShadow
157        * @type Boolean
158        */
159       get visibleShadow() {
160         return this.header.classList.contains('has-shadow');
161       },
163       _computeDropShadowHidden: function(atTop, mode, shadow) {
165         var shadowMode = MODE_CONFIGS.shadowMode[mode];
167         if (this.shadow) {
168           this.toggleClass('has-shadow', true, this.header);
170         } else if (shadowMode === SHADOW_ALWAYS) {
171           this.toggleClass('has-shadow', true, this.header);
173         } else if (shadowMode === SHADOW_WHEN_SCROLLING && !atTop) {
174           this.toggleClass('has-shadow', true, this.header);
176         } else {
177           this.toggleClass('has-shadow', false, this.header);
179         }
180       },
182       _computeMainContainerClass: function(mode) {
183         // TODO:  It will be useful to have a utility for classes
184         // e.g. Polymer.Utils.classes({ foo: true });
186         var classes = {};
188         classes['flex'] = mode !== 'cover';
190         return Object.keys(classes).filter(
191           function(className) {
192             return classes[className];
193           }).join(' ');
194       },
196       _addListener: function() {
197         this.scroller.addEventListener('scroll', this.scrollHandler, false);
198       },
200       _removeListener: function() {
201         this.scroller.removeEventListener('scroll', this.scrollHandler);
202       },
204       _modeChanged: function(newMode, oldMode) {
205         var configs = MODE_CONFIGS;
206         var header = this.header;
207         var animateDuration = 200;
209         if (header) {
210           // in tallMode it may add tallClass to the header; so do the cleanup
211           // when mode is changed from tallMode to not tallMode
212           if (configs.tallMode[oldMode] && !configs.tallMode[newMode]) {
213             header.classList.remove(this.tallClass);
214             this.async(function() {
215               header.classList.remove('animate');
216             }, animateDuration);
217           } else {
218             header.classList.toggle('animate', configs.tallMode[newMode]);
219           }
220         }
221         this._keepScrollingState();
222       },
224       _keepScrollingState: function () {
225         var main = this.scroller;
226         var header = this.header;
228         this._setAtTop(main.scrollTop === 0);
230         if (header && MODE_CONFIGS.tallMode[this.mode]) {
231           this.toggleClass(this.tallClass, this.atTop ||
232               header.classList.contains(this.tallClass) &&
233               main.scrollHeight < this.offsetHeight, header);
234         }
235       },
237       _scroll: function(e) {
238         this._keepScrollingState();
239         this.fire('content-scroll', {target: this.scroller}, {bubbles: false});
240       },
242       _getScrollerForMode: function(mode) {
243         return MODE_CONFIGS.outerScroll[mode] ?
244             this : this.$.mainContainer;
245       }
247     });
249   })();