| OLD | NEW |
| (Empty) |
| 1 | |
| 2 (function() { | |
| 3 | |
| 4 'use strict'; | |
| 5 | |
| 6 Polymer({ | |
| 7 | |
| 8 /** | |
| 9 * Fired when the content has been scrolled. | |
| 10 * | |
| 11 * @event content-scroll | |
| 12 */ | |
| 13 | |
| 14 /** | |
| 15 * Fired when the header is transformed. | |
| 16 * | |
| 17 * @event paper-header-transform | |
| 18 */ | |
| 19 | |
| 20 is: 'paper-scroll-header-panel', | |
| 21 | |
| 22 behaviors: [ | |
| 23 Polymer.IronResizableBehavior | |
| 24 ], | |
| 25 | |
| 26 properties: { | |
| 27 | |
| 28 /** | |
| 29 * If true, the header's height will condense to `_condensedHeaderHeight` | |
| 30 * as the user scrolls down from the top of the content area. | |
| 31 */ | |
| 32 condenses: { | |
| 33 type: Boolean, | |
| 34 value: false, | |
| 35 observer: '_condensesChanged' | |
| 36 }, | |
| 37 | |
| 38 /** | |
| 39 * If true, no cross-fade transition from one background to another. | |
| 40 */ | |
| 41 noDissolve: { | |
| 42 type: Boolean, | |
| 43 value: false | |
| 44 }, | |
| 45 | |
| 46 /** | |
| 47 * If true, the header doesn't slide back in when scrolling back up. | |
| 48 */ | |
| 49 noReveal: { | |
| 50 type: Boolean, | |
| 51 value: false | |
| 52 }, | |
| 53 | |
| 54 /** | |
| 55 * If true, the header is fixed to the top and never moves away. | |
| 56 */ | |
| 57 fixed: { | |
| 58 type: Boolean, | |
| 59 value: false | |
| 60 }, | |
| 61 | |
| 62 /** | |
| 63 * If true, the condensed header is always shown and does not move away. | |
| 64 */ | |
| 65 keepCondensedHeader: { | |
| 66 type: Boolean, | |
| 67 value: false | |
| 68 }, | |
| 69 | |
| 70 /** | |
| 71 * The height of the header when it is at its full size. | |
| 72 * | |
| 73 * By default, the height will be measured when it is ready. If the heigh
t | |
| 74 * changes later the user needs to either set this value to reflect the | |
| 75 * new height or invoke `measureHeaderHeight()`. | |
| 76 */ | |
| 77 headerHeight: { | |
| 78 type: Number, | |
| 79 value: 0 | |
| 80 }, | |
| 81 | |
| 82 /** | |
| 83 * The height of the header when it is condensed. | |
| 84 * | |
| 85 * By default, `_condensedHeaderHeight` is 1/3 of `headerHeight` unless | |
| 86 * this is specified. | |
| 87 */ | |
| 88 condensedHeaderHeight: { | |
| 89 type: Number, | |
| 90 value: 0 | |
| 91 }, | |
| 92 | |
| 93 /** | |
| 94 * By default, the top part of the header stays when the header is being | |
| 95 * condensed. Set this to true if you want the top part of the header | |
| 96 * to be scrolled away. | |
| 97 */ | |
| 98 scrollAwayTopbar: { | |
| 99 type: Boolean, | |
| 100 value: false | |
| 101 }, | |
| 102 | |
| 103 _headerMargin: { | |
| 104 type: Number | |
| 105 }, | |
| 106 | |
| 107 _prevScrollTop: { | |
| 108 type: Number | |
| 109 }, | |
| 110 | |
| 111 _y: { | |
| 112 type: Number | |
| 113 } | |
| 114 | |
| 115 }, | |
| 116 | |
| 117 observers: [ | |
| 118 '_setup(_headerMargin, headerHeight, fixed)', | |
| 119 '_headerHeightChanged(headerHeight, condensedHeaderHeight)', | |
| 120 '_condensedHeaderHeightChanged(headerHeight, condensedHeaderHeight)' | |
| 121 ], | |
| 122 | |
| 123 listeners: { | |
| 124 'iron-resize': 'measureHeaderHeight' | |
| 125 }, | |
| 126 | |
| 127 ready: function() { | |
| 128 this.async(this.measureHeaderHeight, 5); | |
| 129 this._scrollHandler = this._scroll.bind(this); | |
| 130 this.scroller.addEventListener('scroll', this._scrollHandler); | |
| 131 }, | |
| 132 | |
| 133 detached: function() { | |
| 134 this.scroller.removeEventListener('scroll', this._scrollHandler); | |
| 135 }, | |
| 136 | |
| 137 /** | |
| 138 * Returns the header element. | |
| 139 * | |
| 140 * @property header | |
| 141 * @type Object | |
| 142 */ | |
| 143 get header() { | |
| 144 return Polymer.dom(this.$.headerContent).getDistributedNodes()[0]; | |
| 145 }, | |
| 146 | |
| 147 /** | |
| 148 * Returns the content element. | |
| 149 * | |
| 150 * @property content | |
| 151 * @type Object | |
| 152 */ | |
| 153 get content() { | |
| 154 return Polymer.dom(this.$.mainContent).getDistributedNodes()[0]; | |
| 155 }, | |
| 156 | |
| 157 /** | |
| 158 * Returns the scrollable element. | |
| 159 * | |
| 160 * @property scroller | |
| 161 * @type Object | |
| 162 */ | |
| 163 get scroller() { | |
| 164 return this.$.mainContainer; | |
| 165 }, | |
| 166 | |
| 167 /** | |
| 168 * Invoke this to tell `paper-scroll-header-panel` to re-measure the header'
s | |
| 169 * height. | |
| 170 * | |
| 171 * @method measureHeaderHeight | |
| 172 */ | |
| 173 measureHeaderHeight: function() { | |
| 174 var header = this.header; | |
| 175 if (header && header.offsetHeight) { | |
| 176 this.headerHeight = header.offsetHeight; | |
| 177 } | |
| 178 }, | |
| 179 | |
| 180 _headerHeightChanged: function() { | |
| 181 if (!this.condensedHeaderHeight) { | |
| 182 // assume condensedHeaderHeight is 1/3 of the headerHeight | |
| 183 this.condensedHeaderHeight = this.headerHeight * 1 / 3; | |
| 184 } | |
| 185 }, | |
| 186 | |
| 187 _condensedHeaderHeightChanged: function() { | |
| 188 if (this.headerHeight) { | |
| 189 this._headerMargin = this.headerHeight - this.condensedHeaderHeight; | |
| 190 } | |
| 191 }, | |
| 192 | |
| 193 _condensesChanged: function() { | |
| 194 if (this.condenses) { | |
| 195 this._scroll(); | |
| 196 } else { | |
| 197 // reset transform/opacity set on the header | |
| 198 this._condenseHeader(null); | |
| 199 } | |
| 200 }, | |
| 201 | |
| 202 _setup: function() { | |
| 203 var s = this.scroller.style; | |
| 204 s.paddingTop = this.fixed ? '' : this.headerHeight + 'px'; | |
| 205 | |
| 206 s.top = this.fixed ? this.headerHeight + 'px' : ''; | |
| 207 | |
| 208 if (this.fixed) { | |
| 209 this._transformHeader(null); | |
| 210 } else { | |
| 211 this._scroll(); | |
| 212 } | |
| 213 }, | |
| 214 | |
| 215 _transformHeader: function(y) { | |
| 216 var s = this.$.headerContainer.style; | |
| 217 this._translateY(s, -y); | |
| 218 | |
| 219 if (this.condenses) { | |
| 220 this._condenseHeader(y); | |
| 221 } | |
| 222 | |
| 223 this.fire('paper-header-transform', {y: y, height: this.headerHeight, | |
| 224 condensedHeight: this.condensedHeaderHeight}); | |
| 225 }, | |
| 226 | |
| 227 _condenseHeader: function(y) { | |
| 228 var reset = (y === null); | |
| 229 | |
| 230 // adjust top bar in paper-header so the top bar stays at the top | |
| 231 if (!this.scrollAwayTopbar && this.header.$ && this.header.$.topBar) { | |
| 232 this._translateY(this.header.$.topBar.style, | |
| 233 reset ? null : Math.min(y, this._headerMargin)); | |
| 234 } | |
| 235 // transition header bg | |
| 236 var hbg = this.$.headerBg.style; | |
| 237 if (!this.noDissolve) { | |
| 238 hbg.opacity = reset ? '' : (this._headerMargin - y) / this._headerMargin
; | |
| 239 } | |
| 240 // adjust header bg so it stays at the center | |
| 241 this._translateY(hbg, reset ? null : y / 2); | |
| 242 // transition condensed header bg | |
| 243 if (!this.noDissolve) { | |
| 244 var chbg = this.$.condensedHeaderBg.style; | |
| 245 chbg = this.$.condensedHeaderBg.style; | |
| 246 chbg.opacity = reset ? '' : y / this._headerMargin; | |
| 247 | |
| 248 // adjust condensed header bg so it stays at the center | |
| 249 this._translateY(chbg, reset ? null : y / 2); | |
| 250 } | |
| 251 }, | |
| 252 | |
| 253 _translateY: function(s, y) { | |
| 254 var t = (y === null) ? '' : 'translate3d(0, ' + y + 'px, 0)'; | |
| 255 setTransform(s, t); | |
| 256 }, | |
| 257 | |
| 258 /** @param {Event=} event */ | |
| 259 _scroll: function(event) { | |
| 260 if (!this.header) { | |
| 261 return; | |
| 262 } | |
| 263 | |
| 264 var sTop = this.scroller.scrollTop; | |
| 265 | |
| 266 this._y = this._y || 0; | |
| 267 this._prevScrollTop = this._prevScrollTop || 0; | |
| 268 | |
| 269 var y = Math.min(this.keepCondensedHeader ? | |
| 270 this._headerMargin : this.headerHeight, Math.max(0, | |
| 271 (this.noReveal ? sTop : this._y + sTop - this._prevScrollTop))); | |
| 272 | |
| 273 if (this.condenses && this._prevScrollTop >= sTop && sTop > this._headerMa
rgin) { | |
| 274 y = Math.max(y, this._headerMargin); | |
| 275 } | |
| 276 | |
| 277 if (!event || !this.fixed && y !== this._y) { | |
| 278 this._transformHeader(y); | |
| 279 } | |
| 280 | |
| 281 this._prevScrollTop = Math.max(sTop, 0); | |
| 282 this._y = y; | |
| 283 | |
| 284 if (event) { | |
| 285 this.fire('content-scroll', {target: this.scroller}, {cancelable: false}
); | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 }); | |
| 290 | |
| 291 //determine proper transform mechanizm | |
| 292 if (document.documentElement.style.transform !== undefined) { | |
| 293 var setTransform = function(style, string) { | |
| 294 style.transform = string; | |
| 295 } | |
| 296 } else { | |
| 297 var setTransform = function(style, string) { | |
| 298 style.webkitTransform = string; | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 })(); | |
| 303 | |
| OLD | NEW |