OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | |
3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | |
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | |
5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | |
6 Code distributed by Google as part of the polymer project is also | |
7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | |
8 --> | |
9 | |
10 <!-- | |
11 `core-scroll-header-panel` contains a header section and a content section. The | |
12 header is initially on the top part of the view but it scrolls away with the | |
13 rest of the scrollable content. Upon scrolling slightly up at any point, the | |
14 header scrolls back into view. This saves screen space and allows users to | |
15 access important controls by easily moving them back to the view. | |
16 | |
17 __Important:__ The `core-scroll-header-panel` will not display if its parent doe
s not have a height. | |
18 | |
19 Using [layout attributes](http://www.polymer-project.org/docs/polymer/layout-att
rs.html), you can easily make the `core-scroll-header-panel` fill the screen | |
20 | |
21 <body fullbleed layout vertical> | |
22 <core-scroll-header-panel flex> | |
23 <core-toolbar> | |
24 <div>Hello World!</div> | |
25 </core-toolbar> | |
26 </core-scroll-header-panel> | |
27 </body> | |
28 | |
29 or, if you would prefer to do it in CSS, just give `html`, `body`, and `core-scr
oll-header-panel` a height of 100%: | |
30 | |
31 html, body { | |
32 height: 100%; | |
33 margin: 0; | |
34 } | |
35 core-scroll-header-panel { | |
36 height: 100%; | |
37 } | |
38 | |
39 `core-scroll-header-panel` works well with `core-toolbar` but can use any elemen
t | |
40 that represents a header by adding a `core-header` class to it. Use the attribu
te | |
41 or class `content` to delineate the content section. | |
42 | |
43 <core-scroll-header-panel> | |
44 <core-toolbar>Header</core-toolbar> | |
45 <div content>Content goes here...</div> | |
46 </core-scroll-header-panel> | |
47 | |
48 @group Polymer Core Elements | |
49 @element core-scroll-header-panel | |
50 @homepage github.io | |
51 --> | |
52 | |
53 <link rel="import" href="../polymer/polymer.html"> | |
54 | |
55 <polymer-element name="core-scroll-header-panel"> | |
56 <template> | |
57 | |
58 <link rel="stylesheet" href="core-scroll-header-panel.css"> | |
59 | |
60 <div id="mainContainer" on-scroll="{{scroll}}"> | |
61 | |
62 <content id="mainContent" select="[content], .content"></content> | |
63 | |
64 </div> | |
65 | |
66 <div id="headerContainer"> | |
67 | |
68 <div class="bg-container"> | |
69 <div id="condensedHeaderBg"></div> | |
70 <div id="headerBg"></div> | |
71 </div> | |
72 | |
73 <content id="headerContent" select="core-toolbar, .core-header"></content> | |
74 | |
75 </div> | |
76 | |
77 </template> | |
78 <script> | |
79 | |
80 Polymer('core-scroll-header-panel', { | |
81 | |
82 /** | |
83 * Fired when the content has been scrolled. | |
84 * | |
85 * @event scroll | |
86 */ | |
87 | |
88 /** | |
89 * Fired when the header is transformed. | |
90 * | |
91 * @event core-header-transform | |
92 */ | |
93 | |
94 publish: { | |
95 /** | |
96 * If true, the header's height will condense to `_condensedHeaderHeight` | |
97 * as the user scrolls down from the top of the content area. | |
98 * | |
99 * @attribute condenses | |
100 * @type boolean | |
101 * @default false | |
102 */ | |
103 condenses: false, | |
104 | |
105 /** | |
106 * If true, no cross-fade transition from one background to another. | |
107 * | |
108 * @attribute noDissolve | |
109 * @type boolean | |
110 * @default false | |
111 */ | |
112 noDissolve: false, | |
113 | |
114 /** | |
115 * If true, the header doesn't slide back in when scrolling back up. | |
116 * | |
117 * @attribute noReveal | |
118 * @type boolean | |
119 * @default false | |
120 */ | |
121 noReveal: false, | |
122 | |
123 /** | |
124 * If true, the header is fixed to the top and never moves away. | |
125 * | |
126 * @attribute fixed | |
127 * @type boolean | |
128 * @default false | |
129 */ | |
130 fixed: false, | |
131 | |
132 /** | |
133 * If true, the condensed header is always shown and does not move away. | |
134 * | |
135 * @attribute keepCondensedHeader | |
136 * @type boolean | |
137 * @default false | |
138 */ | |
139 keepCondensedHeader: false, | |
140 | |
141 /** | |
142 * The height of the header when it is at its full size. | |
143 * | |
144 * By default, the height will be measured when it is ready. If the heigh
t | |
145 * changes later the user needs to either set this value to reflect the | |
146 * new height or invoke `measureHeaderHeight()`. | |
147 * | |
148 * @attribute headerHeight | |
149 * @type number | |
150 */ | |
151 headerHeight: 0, | |
152 | |
153 /** | |
154 * The height of the header when it is condensed. | |
155 * | |
156 * By default, `_condensedHeaderHeight` is 1/3 of `headerHeight` unless | |
157 * this is specified. | |
158 * | |
159 * @attribute condensedHeaderHeight | |
160 * @type number | |
161 */ | |
162 condensedHeaderHeight: 0 | |
163 }, | |
164 | |
165 prevScrollTop: 0, | |
166 | |
167 headerMargin: 0, | |
168 | |
169 y: 0, | |
170 | |
171 observe: { | |
172 'headerMargin fixed': 'setup' | |
173 }, | |
174 | |
175 domReady: function() { | |
176 this.async('measureHeaderHeight'); | |
177 }, | |
178 | |
179 get header() { | |
180 return this.$.headerContent.getDistributedNodes()[0]; | |
181 }, | |
182 | |
183 get scroller() { | |
184 return this.$.mainContainer; | |
185 }, | |
186 | |
187 measureHeaderHeight: function() { | |
188 var header = this.header; | |
189 if (this.header) { | |
190 this.headerHeight = header.offsetHeight; | |
191 } | |
192 }, | |
193 | |
194 headerHeightChanged: function() { | |
195 if (!this.condensedHeaderHeight) { | |
196 // assume _condensedHeaderHeight is 1/3 of the headerHeight | |
197 this._condensedHeaderHeight = this.headerHeight * 1 / 3; | |
198 } | |
199 this.condensedHeaderHeightChanged(); | |
200 }, | |
201 | |
202 condensedHeaderHeightChanged: function() { | |
203 if (this.condensedHeaderHeight) { | |
204 this._condensedHeaderHeight = this.condensedHeaderHeight; | |
205 } | |
206 if (this.headerHeight) { | |
207 this.headerMargin = this.headerHeight - this._condensedHeaderHeight; | |
208 } | |
209 }, | |
210 | |
211 condensesChanged: function() { | |
212 if (this.condenses) { | |
213 this.scroll(); | |
214 } else { | |
215 // reset transform/opacity set on the header | |
216 this.condenseHeader(null); | |
217 } | |
218 }, | |
219 | |
220 setup: function() { | |
221 var s = this.scroller.style; | |
222 s.paddingTop = this.fixed ? '' : this.headerHeight + 'px'; | |
223 s.top = this.fixed ? this.headerHeight + 'px' : ''; | |
224 if (this.fixed) { | |
225 this.transformHeader(null); | |
226 } else { | |
227 this.scroll(); | |
228 } | |
229 }, | |
230 | |
231 transformHeader: function(y) { | |
232 var s = this.$.headerContainer.style; | |
233 this.translateY(s, -y); | |
234 | |
235 if (this.condenses) { | |
236 this.condenseHeader(y); | |
237 } | |
238 | |
239 this.fire('core-header-transform', {y: y, height: this.headerHeight, | |
240 condensedHeight: this._condensedHeaderHeight}); | |
241 }, | |
242 | |
243 condenseHeader: function(y) { | |
244 var reset = y == null; | |
245 // adjust top bar in core-header so the top bar stays at the top | |
246 if (this.header.$ && this.header.$.topBar) { | |
247 this.translateY(this.header.$.topBar.style, | |
248 reset ? null : Math.min(y, this.headerMargin)); | |
249 } | |
250 // transition header bg | |
251 var hbg = this.$.headerBg.style; | |
252 if (!this.noDissolve) { | |
253 hbg.opacity = reset ? '' : (this.headerMargin - y) / this.headerMargin; | |
254 } | |
255 // adjust header bg so it stays at the center | |
256 this.translateY(hbg, reset ? null : y / 2); | |
257 // transition condensed header bg | |
258 var chbg = this.$.condensedHeaderBg.style; | |
259 if (!this.noDissolve) { | |
260 chbg = this.$.condensedHeaderBg.style; | |
261 chbg.opacity = reset ? '' : y / this.headerMargin; | |
262 // adjust condensed header bg so it stays at the center | |
263 this.translateY(chbg, reset ? null : y / 2); | |
264 } | |
265 }, | |
266 | |
267 translateY: function(s, y) { | |
268 s.transform = s.webkitTransform = y == null ? '' : | |
269 'translate3d(0, ' + y + 'px, 0)'; | |
270 }, | |
271 | |
272 scroll: function(event) { | |
273 if (!this.header) { | |
274 return; | |
275 } | |
276 | |
277 var sTop = this.scroller.scrollTop; | |
278 | |
279 var y = Math.min(this.keepCondensedHeader ? | |
280 this.headerMargin : this.headerHeight, Math.max(0, | |
281 (this.noReveal ? sTop : this.y + sTop - this.prevScrollTop))); | |
282 | |
283 if (this.condenses && this.prevScrollTop >= sTop && sTop > this.headerMarg
in) { | |
284 y = Math.max(y, this.headerMargin); | |
285 } | |
286 | |
287 if (!event || !this.fixed && y !== this.y) { | |
288 requestAnimationFrame(this.transformHeader.bind(this, y)); | |
289 } | |
290 | |
291 this.prevScrollTop = sTop; | |
292 this.y = y; | |
293 | |
294 if (event) { | |
295 this.fire('scroll', {target: this.scroller}, this, false); | |
296 } | |
297 } | |
298 | |
299 }); | |
300 | |
301 </script> | |
302 </polymer-element> | |
OLD | NEW |