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.github.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/CONTRIBUTORS.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/PATENTS.txt
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.
17 __Important:__ The `core-scroll-header-panel` will not display if its parent does not have a height.
19 Using [layout attributes](http://www.polymer-project.org/docs/polymer/layout-attrs.html), you can easily make the `core-scroll-header-panel` fill the screen
21 <body fullbleed layout vertical>
22 <core-scroll-header-panel flex>
24 <div>Hello World!</div>
26 </core-scroll-header-panel>
29 or, if you would prefer to do it in CSS, just give `html`, `body`, and `core-scroll-header-panel` a height of 100%:
35 core-scroll-header-panel {
39 `core-scroll-header-panel` works well with `core-toolbar` but can use any element
40 that represents a header by adding a `core-header` class to it.
42 <core-scroll-header-panel>
43 <core-toolbar>Header</core-toolbar>
44 <div>Content goes here...</div>
45 </core-scroll-header-panel>
47 @group Polymer Core Elements
48 @element core-scroll-header-panel
52 <link rel=
"import" href=
"../polymer/polymer.html">
53 <link rel=
"import" href=
"../core-resizable/core-resizable.html">
55 <polymer-element name=
"core-scroll-header-panel">
58 <link rel=
"stylesheet" href=
"core-scroll-header-panel.css">
60 <div id=
"mainContainer">
62 <content id=
"mainContent" select=
":not(core-toolbar):not(.core-header)"></content>
66 <div id=
"headerContainer">
68 <div class=
"bg-container">
69 <div id=
"condensedHeaderBg"></div>
70 <div id=
"headerBg"></div>
73 <content id=
"headerContent" select=
"core-toolbar, .core-header"></content>
81 Polymer(Polymer
.mixin({
84 * Fired when the content has been scrolled.
90 * Fired when the header is transformed.
92 * @event core-header-transform
97 * If true, the header's height will condense to `_condensedHeaderHeight`
98 * as the user scrolls down from the top of the content area.
100 * @attribute condenses
107 * If true, no cross-fade transition from one background to another.
109 * @attribute noDissolve
116 * If true, the header doesn't slide back in when scrolling back up.
118 * @attribute noReveal
125 * If true, the header is fixed to the top and never moves away.
134 * If true, the condensed header is always shown and does not move away.
136 * @attribute keepCondensedHeader
140 keepCondensedHeader
: false,
143 * The height of the header when it is at its full size.
145 * By default, the height will be measured when it is ready. If the height
146 * changes later the user needs to either set this value to reflect the
147 * new height or invoke `measureHeaderHeight()`.
149 * @attribute headerHeight
156 * The height of the header when it is condensed.
158 * By default, `_condensedHeaderHeight` is 1/3 of `headerHeight` unless
161 * @attribute condensedHeaderHeight
165 condensedHeaderHeight
: 0,
168 * By default, the top part of the header stays when the header is being
169 * condensed. Set this to true if you want the top part of the header
170 * to be scrolled away.
172 * @attribute scrollAwayTopbar
176 scrollAwayTopbar
: false
186 'headerMargin fixed': 'setup'
190 'core-resize': 'measureHeaderHeight'
193 attached: function() {
194 this.resizableAttachedHandler();
198 this._scrollHandler
= this.scroll
.bind(this);
199 this.scroller
.addEventListener('scroll', this._scrollHandler
);
202 detached: function() {
203 this.scroller
.removeEventListener('scroll', this._scrollHandler
);
204 this.resizableDetachedHandler();
207 domReady: function() {
208 this.async('measureHeaderHeight');
212 return this.$.headerContent
.getDistributedNodes()[0];
216 * Returns the scrollable element.
222 return this.$.mainContainer
;
226 * Invoke this to tell `core-scroll-header-panel` to re-measure the header's
229 * @method measureHeaderHeight
231 measureHeaderHeight: function() {
232 var header
= this.header
;
233 if (header
&& header
.offsetHeight
) {
234 this.headerHeight
= header
.offsetHeight
;
238 headerHeightChanged: function() {
239 if (!this.condensedHeaderHeight
) {
240 // assume _condensedHeaderHeight is 1/3 of the headerHeight
241 this._condensedHeaderHeight
= this.headerHeight
* 1 / 3;
243 this.condensedHeaderHeightChanged();
246 condensedHeaderHeightChanged: function() {
247 if (this.condensedHeaderHeight
) {
248 this._condensedHeaderHeight
= this.condensedHeaderHeight
;
250 if (this.headerHeight
) {
251 this.headerMargin
= this.headerHeight
- this._condensedHeaderHeight
;
255 condensesChanged: function() {
256 if (this.condenses
) {
259 // reset transform/opacity set on the header
260 this.condenseHeader(null);
265 var s
= this.scroller
.style
;
266 s
.paddingTop
= this.fixed
? '' : this.headerHeight
+ 'px';
267 s
.top
= this.fixed
? this.headerHeight
+ 'px' : '';
269 this.transformHeader(null);
275 transformHeader: function(y
) {
276 var s
= this.$.headerContainer
.style
;
277 this.translateY(s
, -y
);
279 if (this.condenses
) {
280 this.condenseHeader(y
);
283 this.fire('core-header-transform', {y
: y
, height
: this.headerHeight
,
284 condensedHeight
: this._condensedHeaderHeight
});
287 condenseHeader: function(y
) {
288 var reset
= y
== null;
289 // adjust top bar in core-header so the top bar stays at the top
290 if (!this.scrollAwayTopbar
&& this.header
.$ && this.header
.$.topBar
) {
291 this.translateY(this.header
.$.topBar
.style
,
292 reset
? null : Math
.min(y
, this.headerMargin
));
294 // transition header bg
295 var hbg
= this.$.headerBg
.style
;
296 if (!this.noDissolve
) {
297 hbg
.opacity
= reset
? '' : (this.headerMargin
- y
) / this.headerMargin
;
299 // adjust header bg so it stays at the center
300 this.translateY(hbg
, reset
? null : y
/ 2);
301 // transition condensed header bg
302 var chbg
= this.$.condensedHeaderBg
.style
;
303 if (!this.noDissolve
) {
304 chbg
= this.$.condensedHeaderBg
.style
;
305 chbg
.opacity
= reset
? '' : y
/ this.headerMargin
;
306 // adjust condensed header bg so it stays at the center
307 this.translateY(chbg
, reset
? null : y
/ 2);
311 translateY: function(s
, y
) {
312 var t
= y
== null ? '' : 'translate3d(0, ' + y
+ 'px, 0)';
316 scroll: function(event
) {
321 var sTop
= this.scroller
.scrollTop
;
323 var y
= Math
.min(this.keepCondensedHeader
?
324 this.headerMargin
: this.headerHeight
, Math
.max(0,
325 (this.noReveal
? sTop
: this.y
+ sTop
- this.prevScrollTop
)));
327 if (this.condenses
&& this.prevScrollTop
>= sTop
&& sTop
> this.headerMargin
) {
328 y
= Math
.max(y
, this.headerMargin
);
331 if (!event
|| !this.fixed
&& y
!== this.y
) {
332 this.transformHeader(y
);
335 this.prevScrollTop
= Math
.max(sTop
, 0);
339 this.fire('scroll', {target
: this.scroller
}, this, false);
343 }, Polymer
.CoreResizable
));
345 //determine proper transform mechanizm
346 if (document
.documentElement
.style
.transform
!== undefined) {
347 var setTransform = function(style
, string
) {
348 style
.transform
= string
;
351 var setTransform = function(style
, string
) {
352 style
.webkitTransform
= string
;