Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / polymer / components / core-scroll-header-panel / core-scroll-header-panel.html
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.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
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 does not have a height.
18
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
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-scroll-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 element 
40 that represents a header by adding a `core-header` class to it.  Use the attribute 
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 height
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.headerMargin) {
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>